• 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
    ", error / 10, error % 10 );
          return DRIVER_ERROR_PARAMETER;
        }
        else
        {
          // warn( "bitrate error %ld.%ld%%
    ", 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%
  • 相关阅读:
    DEBIAN下中文显示
    SpringMVC整合Quartz实现定时任务以及Tomcat服务执行初始化定时任务
    SpringMVC 配置定时执行任务
    Mybatis update In
    mybatis在xml文件中处理大于号小于号的方法
    解决Cannot change version of project facet Dynamic web module to 2.5
    android 圆角边框及图片
    Android MotionEvent事件响应机制
    android:configChanges属性
    Android之ScrollView嵌套ListView
  • 原文地址:https://www.cnblogs.com/shangdawei/p/4720637.html
Copyright © 2020-2023  润新知