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%
时间: 2024-10-24 00:03:51

Calculate CAN bit timing parameters -- STM32的相关文章

Calculate CAN bit timing parameters

Calculate CAN bit timing parameters TSYNC_SEG === 1 TSEG1 = Prop_Seg + Phase_Seg1 TSEG2 = Phase_Seg2 TBit = TSYNC_SEG + TSEG1 + TSEG2 TSEG2 / TBit = Sample Point A detailed description about setting the correct CAN bit timing is given in a paper by F

0xWS2812 STM32 driver for WS2812(B) RGB LEDs

0xWS2812 STM32 driver for WS2812(B) RGB LEDs 0xWS2812 pronounced "hex-WS2812" This code aims at providing a basic interface to the WS2812(B) individually addressable RGB LEDs by WorldSemi. The code outputs 16 parallel data streams to 16 parallel

CRT/LCD/VGA Information and Timing

彩色阴极射线管的剖面图: 1. 电子QIANG Three Electron guns (for red, green, and blue phosphor dots)2. 电子束 Electron beams3. 聚焦线圈 Focusing coils4. 偏向线圈 Deflection coils5. 阳极接点 Anode connection6. Mask for separating beams for red, green, and blue part of displayed ima

uboot2011.09源代码ReadMe译文

# # (C) Copyright 2000 - 2011 # Wolfgang Denk, DENX Software Engineering, [email protected] #查看建立这个工程的文件列表人 # #这个程序是自由软件,你可以重新分配它或者修改它在GNU通用公共许可证以由自由软件基#金会发布:第二版或者任何之后的版本. #本程序是分布在希望它是有用的,但没有任何保证:甚至没有隐含保证. #查看 GNU通用公共许可证对于更多的细节. #你应该收到一份GNU通用公共许可证随着这

【转】linux设备驱动之MMC SD卡——核心层简单分析

原文网址:http://blog.chinaunix.net/uid-28685940-id-3889878.html /*************************************************************************************************************************************//* bus.c */ /* *  linux/drivers/mmc/core/bus.c * *  Cop

Nmap 源码学习三 nmap_main主程序分析

主体程序位置在nmap.cc line:1640 学习要点: 程序在1650行,新建一个主机的单例对象, #ifndef NOLUA /* Only NSE scripts can add targets */ NewTargets *new_targets = NULL; /* Pre-Scan and Post-Scan script results datastructure */ ScriptResults *script_scan_results = NULL; #endif 从168

Timequest静态时序分析(STA)基础

Setup Slack Hold Slack Recovery&Removal Recovery: The minimum time an asynchronous signal must be stable BEFORE clock edgeRemoval  : The minimum time an asynchronous signal must be stable AFTER clock edge I/O Analysis Analyzing I/O performance in a s

selenium docs

Note to the Reader - Docs Being Revised for Selenium 2.0! Introduction Test Automation for Web Applications To Automate or Not to Automate? Introducing Selenium Brief History of The Selenium Project Selenium’s Tool Suite Choosing Your Selenium Tool S

SDRAM总结

使用的流程 W9825G6JH winbond sdram 4M words X 4banks X 16bits=. Accesses to the SDRAM are burst oriented. Up to 200MHz CAS Latency 2 and 3 Burst Length 1,2,4,9 and Full page BUrst Read, Single Writes Mode 8K Refresh Cycles/64mS 1 After power up, an initia