Calculate CAN bit timing parameters -- STM32
Calculate CAN bit timing parameters
Calculate CAN bit timing parameters
typedef struct { //char name[ 16 ]; // Name of the CAN controller hardware //uint32_t ref_clk; // CAN system clock frequency in Hz //uint32_t sjw_max; // Synchronisation jump width uint32_t brp_min; // Bit-rate prescaler uint32_t brp_max; uint32_t brp_inc; uint32_t tseg1_min; // Time segement 1 = prop_seg + phase_seg1 uint32_t tseg1_max; uint32_t tseg2_min; // Time segement 2 = phase_seg2 uint32_t tseg2_max; } CAN_BitTimingConst_TypeDef; typedef struct { uint32_t ref_clk; // CAN system clock frequency in Hz uint32_t bitrate; // Bit-rate in bits/second uint32_t sample_point; // Sample point in one-tenth of a percent uint32_t brp; // Bit-rate prescaler uint32_t tq; // Time quanta (TQ) in nanoseconds uint32_t tseg1; // Time segement 1 = prop_seg + phase_seg1 uint32_t tseg2; // Time segement 2 = phase_seg2 uint32_t sjw; // Synchronisation jump width in TQs //uint32_t prop_seg; // Propagation segment in TQs //uint32_t phase_seg1; // Phase buffer segment 1 in TQs //uint32_t phase_seg2; // Phase buffer segment 2 in TQs } CAN_BitTiming_TypeDef;
#define CAN_CALC_MAX_ERROR 50 // in one-tenth of a percent int32_t CAN_UpdateSamplePoint( CAN_BitTimingConst_TypeDef *btc, int32_t sampl_pt, int32_t tseg, int32_t *tseg1, int32_t *tseg2 ) { *tseg2 = tseg + 1 - ( sampl_pt * ( tseg + 1 ) ) / 1000; if ( *tseg2 < btc->tseg2_min ) *tseg2 = btc->tseg2_min; if ( *tseg2 > btc->tseg2_max ) *tseg2 = btc->tseg2_max; *tseg1 = tseg - *tseg2; if ( *tseg1 > btc->tseg1_max ) { *tseg1 = btc->tseg1_max; *tseg2 = tseg - *tseg1; } return 1000 * ( tseg + 1 - *tseg2 ) / ( tseg + 1 ); } // CIA Sample Point : 75.0% : Speed > 800000 // CIA Sample Point : 80.0% : Speed > 500000 // CIA Sample Point : 87.5% : Speed <= 500000 uint32_t CAN_CIA_SamplePoint( uint32_t bitrate ) { uint32_t sampl_pt; if ( bitrate > 800000 ) sampl_pt = 750; else if ( bitrate > 500000 ) sampl_pt = 800; else sampl_pt = 875; return sampl_pt; } int32_t CAN_CalcBitTiming( CAN_BitTimingConst_TypeDef *btc, CAN_BitTiming_TypeDef *bt ) { uint64_t v64; int32_t rate = 0; int32_t best_error = 1000000000, error = 0; int32_t best_tseg = 0, best_brp = 0, brp = 0; int32_t tsegall, tseg = 0, tseg1 = 0, tseg2 = 0; int32_t spt_error = 1000, spt = 0, sampl_pt; // Use gived sample points if ( bt->sample_point ) sampl_pt = bt->sample_point; else // Use CIA recommended sample points sampl_pt = CAN_CIA_SamplePoint( bt->bitrate ); // tseg even = round down, odd = round up for ( tseg = ( btc->tseg1_max + btc->tseg2_max ) * 2 + 1; tseg >= ( btc->tseg1_min + btc->tseg2_min ) * 2; tseg-- ) { tsegall = 1 + tseg / 2; // Compute all possible tseg choices (tseg=tseg1+tseg2) brp = bt->ref_clk / ( tsegall * bt->bitrate ) + tseg % 2; // chose brp step which is possible in system brp = ( brp / btc->brp_inc ) * btc->brp_inc; if ( ( brp < btc->brp_min ) || ( brp > btc->brp_max ) ) continue; rate = bt->ref_clk / ( brp * tsegall ); error = bt->bitrate - rate; // tseg brp biterror if ( error < 0 ) error = -error; if ( error > best_error ) continue; best_error = error; if ( error == 0 ) { spt = CAN_UpdateSamplePoint( btc, sampl_pt, tseg / 2, &tseg1, &tseg2 ); error = sampl_pt - spt; if ( error < 0 ) error = -error; if ( error > spt_error ) continue; spt_error = error; } best_tseg = tseg / 2; best_brp = brp; if ( error == 0 ) break; } if ( best_error ) { /* Error in one-tenth of a percent */ error = ( best_error * 1000 ) / bt->bitrate; if ( error > CAN_CALC_MAX_ERROR ) { // error ( "bitrate error %ld.%ld%% too high\n", error / 10, error % 10 ); return DRIVER_ERROR_PARAMETER; } else { // warn( "bitrate error %ld.%ld%%\n", error / 10, error % 10 ); } } v64 = ( (uint64_t) best_brp * 1000000000UL ) / bt->ref_clk; bt->tq = (uint32_t) v64; bt->brp = best_brp; bt->tseg2 = tseg2; bt->tseg1 = tseg1; bt->sjw = 1; // bt->prop_seg = tseg1 / 2; // bt->phase_seg1 = tseg1 - bt->prop_seg; // bt->phase_seg2 = tseg2; // real bit-rate bt->bitrate = bt->ref_clk / ( bt->brp * ( tseg1 + tseg2 + 1 ) ); // real sample point bt->sample_point = CAN_UpdateSamplePoint( btc, sampl_pt, best_tseg, &tseg1, &tseg2 ); return DRIVER_OK; }
SJW[1:0]: Resynchronization jump width
These bits define the maximum number of time quanta the CAN hardware
is allowed to lengthen or shorten a bit to perform the resynchronization.
tRJW = tq x (SJW[1:0] + 1)
TS2[2:0]: Time segment 2
These bits define the number of time quanta in Time Segment 2.
tBS2 = tq x (TS2[2:0] + 1)
TS1[3:0]: Time segment 1
These bits define the number of time quanta in Time Segment 1
tBS1 = tq x (TS1[3:0] + 1)
BRP[9:0]: Baud rate prescaler
These bits define the length of a time quanta.
tq = (BRP[9:0]+1) x tPCLK
const CAN_BitTimingConst_TypeDef CAN_BitTimingConst = { 1, // Bit-rate prescaler Min 1024, // Bit-rate prescaler Max 1, // Bit-rate prescaler Inc 1, // Time segement 1 = prop_seg + phase_seg1 Min 16, // Time segement 1 = prop_seg + phase_seg1 Max 1, // Time segement 2 = phase_seg2 Min 8, // Time segement 2 = phase_seg2 Max }; static int32_t CAN_SetSpeed( CAN_Controller_TypeDef *can, uint32_t speed ) { int32_t RetValue = CAN_EnterInit( can ); if ( RetValue != DRIVER_OK ) return RetValue; uint32_t Freq = can->freq( ); CAN_BitTiming_TypeDef CAN_BitTiming; CAN_BitTiming.ref_clk = Freq; CAN_BitTiming.bitrate = speed; // be updated to real speed
CAN_BitTiming.sample_point = 0; // be updated to real spt
RetValue = CAN_CalcBitTiming( &CAN_BitTimingConst, &CAN_BitTiming ); if ( RetValue == DRIVER_OK ) { can->info->speed = CAN_BitTiming.bitrate; // updated uint32_t BTR = can->reg->BTR & 0xC0000000; // SILM|LBKM BTR |= ( ( CAN_BitTiming.brp - 1 ) << 0 ) // BRP | ( ( CAN_BitTiming.tseg1 ) << 16 ) // TS1 | ( ( CAN_BitTiming.tseg2 - 1 ) << 20 ) // TS2 | ( ( CAN_BitTiming.sjw - 1 ) << 24 ); // SJW can->reg->BTR = BTR; } return CAN_LeaveInit( can );
/* BPR TSEG1 TSEG2 */ /* 36 MHz 1 Mbps */ { 3, 8, 3}, // 75% /* 36 MHz 800 Kbps */ { 3, 11, 3}, // 80% /* 36 MHz 500 Kbps */ { 4, 14, 3}, // 83.3% /* 36 MHz 250 Kbps */ { 9, 13, 2}, // 87.5% /* 36 MHz 125 Kbps */ {18, 13, 2}, // 87.5% /* 36 MHz 100 Kbps */ {24, 12, 2}, // 86.6% /* 36 MHz 83.3 Kbps */ {24, 14, 3}, // 83.3% /* 36 MHz 62.5 Kbps */ {36, 13, 2}, // 87.5% /* 36 MHz 50 Kbps */ {45, 13, 2}, // 87.5% /* 36 MHz 20 Kbps */ {120,12, 2}, // 86.6% /* 36 MHz 10 Kbps */ {225,13, 2}, // 87.5% /* 36 MHz 500 Kbps */ { 4, 14, 3} // 83.3%