CAN通信波特率的计算方法

发布时间 2023-08-11 15:26:46作者: lazy12138

前言

之前使用CAN,是直接使用的以前同事的代码,是已经算好的波特率,自己却从来没有计算过,现在想起来对这块有些缺乏。

STM32F103 CAN通信波特率计算方法


  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;  

  /* CAN寄存器初始化 */
  CAN_DeInit(CAN1);
  CAN_StructInit(&CAN_InitStructure);

  /* CAN单元初始化 */
  CAN_InitStructure.CAN_TTCM=DISABLE;               //MCR-TTCM  时间触发通信模式使能
  CAN_InitStructure.CAN_ABOM=DISABLE;               //MCR-ABOM  自动离线管理 
  CAN_InitStructure.CAN_AWUM=DISABLE;               //MCR-AWUM  自动唤醒模式
 /// CAN_InitStructure.CAN_NART=DISABLE;               //MCR-NART  禁止报文自动重传      0-自动重传   1-报文只传一次
  CAN_InitStructure.CAN_NART=DISABLE;               //MCR-NART  禁止报文自动重传      0-自动重传   1-报文只传一次
  CAN_InitStructure.CAN_RFLM=DISABLE;               //MCR-RFLM  接收FIFO 锁定模式  0-溢出时新报文会覆盖原有报文  1-溢出时,新报文丢弃
  CAN_InitStructure.CAN_TXFP = ENABLE;   //1 报文优先级取决于ID号 0  关闭优先级
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;  //正常模式
  //CAN_InitStructure.CAN_TXFP=DISABLE;               //MCR-TXFP  发送FIFO优先级 0-优先级取决于报文标示符 1-优先级取决于发送请求的顺序
  //CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;       //BTR-SILM/LBKM   CAN环回模式
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;           //BTR-SJW 重新同步跳跃宽度 1个时间单元
  CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;           //BTR-TS1 时间段1 占用了2个时间单元
  CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;           //BTR-TS1 时间段2 占用了3个时间单元

#if CAN_BAUDRATE == 1000 //1MBps 
  CAN_InitStructure.CAN_Prescaler =6;               //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+2+3)/6=1Mbps
#elif CAN_BAUDRATE == 500 // 500KBps 
  CAN_InitStructure.CAN_Prescaler =12;
#elif CAN_BAUDRATE == 250 // 250KBps 
  CAN_InitStructure.CAN_Prescaler =24;
#elif CAN_BAUDRATE == 125 // 125KBps 
  CAN_InitStructure.CAN_Prescaler =48;
#elif  CAN_BAUDRATE == 100 // 100KBps
  CAN_InitStructure.CAN_Prescaler =60;
#elif  CAN_BAUDRATE == 50 // 50KBps 
  CAN_InitStructure.CAN_Prescaler =120;
#elif  CAN_BAUDRATE == 20 // 20KBps
  CAN_InitStructure.CAN_Prescaler =300;
#elif  CAN_BAUDRATE == 10 // 10KBps 
  CAN_InitStructure.CAN_Prescaler =600;
#endif  

    CAN_Init(CAN1,&CAN_InitStructure);

但是这里面的1MBps是怎么计算出来的呢,通过查找STM32的参考手册找到了答案:

 注意STM32 CAN 属于APB1总线,APB1总线,默认配置最大主频(36Mhz),而不是72Mhz。

 
位时间 = (1*tq + tbs1 + tbs2),注意,这里与 CAN_SJW_1tq 无关!!
 
如果:tbs1 = 2 , tbs2 = 3,则: 位时间 =  (1+2+3)tq = 6 tq。
 
注意:这里,还有个分频, 分频分的不是主频(72MHz),是CAN总线的APB1 频率,手册上写着,36MHz,也就是 主频的2分频。
 
系统默认初始化后,APB1总线频率,设置为 36MHz。
 
这里CAN控制器,可以把APB1 继续分频,如 6,那么,CAN控制器频率:36Mhz / 6 = 6 Mhz。
 
波特率: =  1 /  6 * (1/6Mhz) = 1Mhz = 1 Mbps

之后再看125KBps的计算:
APB1分频为48,那么,CAN控制频率:36Mhz / 48 = 750 Khz。
那么波特率为: 1 / 6 * (1/750 Khz) = 125Khz

这里,部分内容我转载了:STM32F103 CAN通信波特率的计算方法 - svchao - 博客园 (cnblogs.com)

 

HC32F460 CAN通信波特率计算方法

 

    stc_can_init_config_t   stcCanInitCfg;
    stc_can_filter_t        stcFilter;
        
    stcCanInitCfg.stcCanBt.PRESC = 8u-1u;//分频 // 波特率设置:  8-1:125K     4-1:250K  2-1:500K
    stcCanInitCfg.stcCanBt.SEG_1 = 5u-2u;
    stcCanInitCfg.stcCanBt.SEG_2 = 3u-1u;
    stcCanInitCfg.stcCanBt.SJW   = 3u-1u;

    stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10u;
    stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16u-1u;

    stcCanInitCfg.enCanRxBufAll  = CanRxNormal;
    stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;
    stcCanInitCfg.enCanSAck      = CanSelfAckDisable;
    stcCanInitCfg.enCanSTBMode   = CanSTBFifoMode;

    CAN_Init(&stcCanInitCfg);
        
    stcFilter.enAcfFormat = CanAllFrames;
    stcFilter.enFilterSel = CanFilterSel1;
    stcFilter.u32CODE     = MyID;
    stcFilter.u32MASK     = 0x1FFFFFFFu;
    CAN_FilterConfig(&stcFilter, Enable);
        
    CAN_IrqCmd(CanRxIrqEn, Enable);

通过查看HC32F460的参考手册,可知波特率的计算方法:

波特率 = 时钟(总线时钟/外设时钟) / (波特率分频器值)*(时间段1 + 时间段2 + 1)

 

 那么,我们只需要计算 CAN 的位时间就可以了

根据参考手册上的计算方法,可以得出:

波特率 = 1 / BT = 1 / ((SEG_1 + 2)+ (SEG_2 + 1)) × TQ = 1 / ((SEG_1 + 2)+ (SEG_2 + 1)) ×( (PRESC + 1) / fcan_clk )

那么 125KBps 的计算:
SEG_1 = 3 ,SEG_2 = 2,PRESC = 7 

还要注意can的频率,这里我将CAN的频率设为了125Khz,

波特率 = (1 / ( 5 + 3 ) * (8 / 125Khz) = 125Khz

 

HC32F460 CAN通信问题刨析与解决 - - 21ic电子技术开发论坛