0
\$\begingroup\$

I am using keil drivers to use CAN bus on an STM22F107. The method below is used to set CAN baud rate.

status = ptrCAN->SetBitrate    (ARM_CAN_BITRATE_NOMINAL,              // Set nominal bitrate
                              125000U,                              // Set bitrate to 125 kbit/s ||||| 150k in SW -> 50k in oscilloscope | 200k->1.25meg | 125k->71.4k;
                              ARM_CAN_BIT_PROP_SEG(5U)   |          // Set propagation segment to 5 time quanta
                              ARM_CAN_BIT_PHASE_SEG1(1U) |          // Set phase segment 1 to 1 time quantum (sample point at 87.5% of bit time)
                              ARM_CAN_BIT_PHASE_SEG2(1U) |          // Set phase segment 2 to 1 time quantum (total bit is 8 time quanta long)
                              ARM_CAN_BIT_SJW(1U));                 // Resynchronization jump width is same as phase segment 2

The function definition is as below:

static int32_t CANx_SetBitrate (ARM_CAN_BITRATE_SELECT select, uint32_t bitrate, uint32_t bit_segments, uint8_t x) {
CAN_TypeDef *ptr_CAN;
uint32_t     mcr, sjw, prop_seg, phase_seg1, phase_seg2, pclk, brp, tq_num;

if (x >= CAN_CTRL_NUM)                 { return ARM_DRIVER_ERROR;               }
if (select != ARM_CAN_BITRATE_NOMINAL) { return ARM_CAN_INVALID_BITRATE_SELECT; }
if (can_driver_powered[x] == 0U)       { return ARM_DRIVER_ERROR;               }

prop_seg   = (bit_segments & ARM_CAN_BIT_PROP_SEG_Msk  ) >> ARM_CAN_BIT_PROP_SEG_Pos;
phase_seg1 = (bit_segments & ARM_CAN_BIT_PHASE_SEG1_Msk) >> ARM_CAN_BIT_PHASE_SEG1_Pos;
phase_seg2 = (bit_segments & ARM_CAN_BIT_PHASE_SEG2_Msk) >> ARM_CAN_BIT_PHASE_SEG2_Pos;
sjw        = (bit_segments & ARM_CAN_BIT_SJW_Msk       ) >> ARM_CAN_BIT_SJW_Pos;

if (((prop_seg + phase_seg1) < 1U) || ((prop_seg + phase_seg1) > 16U)) { return ARM_CAN_INVALID_BIT_PROP_SEG;   }
if (( phase_seg2             < 1U) || ( phase_seg2             >  8U)) { return ARM_CAN_INVALID_BIT_PHASE_SEG2; }
if (( sjw                    < 1U) || ( sjw                    >  4U)) { return ARM_CAN_INVALID_BIT_SJW;        }

ptr_CAN = ptr_CANx[x];

tq_num = 1U + prop_seg + phase_seg1 + phase_seg2;
pclk   = CAN_GetClock ();           if (pclk == 0U)  { return 
ARM_DRIVER_ERROR;        }
brp    = pclk / (tq_num * bitrate); if (brp > 1024U) { return ARM_CAN_INVALID_BITRATE; }
if (pclk > (brp * tq_num * bitrate)) {
if ((((pclk - (brp * tq_num * bitrate)) * 1024U) / pclk) > CAN_CLOCK_TOLERANCE) { return ARM_CAN_INVALID_BITRATE; }
  } else if (pclk < (brp * tq_num * bitrate)) {
if (((((brp * tq_num * bitrate) - pclk) * 1024U) / pclk) > CAN_CLOCK_TOLERANCE) { return ARM_CAN_INVALID_BITRATE; }
  }

mcr = ptr_CAN->MCR;
ptr_CAN->MCR = CAN_MCR_INRQ;                  // Activate initialization mode
while ((ptr_CAN->MSR&CAN_MSR_INAK) == 0U);    // Wait to enter initialization mode

ptr_CAN->BTR = (ptr_CAN->BTR & (CAN_BTR_LBKM | CAN_BTR_SILM)) | ((brp - 1U) & CAN_BTR_BRP) | ((sjw - 1U) << 24) | ((phase_seg2 - 1U) << 20) | ((prop_seg + phase_seg1 - 1U) << 16);
ptr_CAN->MCR =  mcr;                          // Return to previous mode

return ARM_DRIVER_OK;

Unfortunately, when I use this method, I get wrong baud rate in CAN (I checked with oscilloscope). For example, when I set baud rate as 125kb/s, the actual value on the pin is 71.4kb/s for example.

Could you please help me to find the problem. Many thanks.

\$\endgroup\$
3
  • \$\begingroup\$ Your code formatting is all over the place. Please adopt a conventional coding standard and format the code properly, or otherwise don't expect other people to read it or help you with it. \$\endgroup\$
    – Lundin
    Commented Apr 25, 2022 at 9:54
  • \$\begingroup\$ In general though: bitrate = tq * peripheral_clock. So for 1/(125*10^3) = 8us bit length and 1+(5+1)+(1+1)+(1+1)=11 tq, you need an 8us / 11 = 1.375MHz clock. But in reality you'll have something like 2MHz or 4MHz probably? As previously pointed out in another question, I don't think your tq settings make sense to begin with. \$\endgroup\$
    – Lundin
    Commented Apr 25, 2022 at 10:03
  • \$\begingroup\$ @Lundin thanks for your helpful comments. \$\endgroup\$
    – user15847
    Commented Apr 25, 2022 at 11:43

0

Browse other questions tagged or ask your own question.