AnsweredAssumed Answered

MPC5643L FlexCAN pre-scaler

Question asked by Daniel Lundin on Apr 2, 2012
Latest reply on Apr 6, 2012 by TomE

I'm using MPC5643L with Codewarrior 2.10.


I am trying to correctly configure the pre-scaler clock for FlexCAN. According to the manual, f_canclk / (bitrate * tq_n) = PRESDIV-1, where f_canclk is the frequency of the CAN clock (CPI lock), bitrate is the desire CAN baudrate, tq_n is the desired number of time quanta per byte and PRESDIV is the register value.


If I follow the above formula from manual, I get exactly twice the desired baudrate.


My clock source is the oscillator clock of 8MHz. I want to setup the baudrate to 250kbps, with 16tq per byte. So my formula calculates 8000khz / (250khz * 16) = PRESDIV-1,  --> 2 = PRESDIV-1, --> PRESDIV=1.


This gives me a baudrate of 500kbps, measured with scope and analyser software both. Twice as large as expected. What am I missing?


The oscillator clock is measured to 8MHz with oscilloscope. Other MCU peripherals on the same board behave correctly, with correctly pre-scale values.


16 tq gives me: prop_seg = 11tq, phase_seg1 = 2tq, phase_seg 2 = 2tq, rjw = 2tq. This gives a sample point at 87.5% which is the recommendated sample point location by CANopen DS301 vers4.2, §5.4.


Here is the baudrate calculation code:


static inline can_status_t can_init_baudrate (uint32_t*          ctrl_presdiv,                                               const baudrate_t*  selected_baudrate,                                              uint32_t           clock_khz){  /***** Calculate baudrate *****/  uint32_t freq_tq;                              // time quanta frequency in khz  int32_t  s_presdiv;                            // signed temporary presdiv                     freq_tq   = selected_baudrate->tq_total *               selected_baudrate->baudrate_khz;  s_presdiv = (int32_t)(clock_khz / freq_tq)-1;  // calculate clock and compensate with -1 for register format    if(s_presdiv < 0)                              // insufficient oscillator clock etc  {    return CAN_ERR_PRESCALING;  }    /***** Convert to FlexCAN register format *****/  *ctrl_presdiv = (uint32_t)s_presdiv;  *ctrl_presdiv <<= 24;    return CAN_OK;}



If I simply change the formula to


s_presdiv = (int32_t)(clock_khz / freq_tq)*2-1;


then everything works correctly. I don't understand why.