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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.