STM32F103 CAN通信波特率的计算方法

嵌入式软件 专栏收录该内容
52 篇文章 2 订阅

前言

  • 最近看一下CAN通信,翻出来之前做过的STM32 CAN通信的项目代码,有些概念比较模糊了,如波特率是怎么计算的。
  • 最近接触rt-thread比较多,想把之前的CAN通信的代码,移植到RTOS上。

 

CAN波特率

如果主机与从机,波特率不一致,很难正常的通信。

/*
 * 函数名:CAN_Mode_Config
 * 描述  :CAN的模式 配置
 * 输入  :无
 * 输出  : 无
 * 调用  :内部调用
 */
static void CAN_Mode_Config(void)
{
    CAN_InitTypeDef        CAN_InitStructure;
    /************************ CAN通信参数设  *********************************/
    /*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=ENABLE;          //MCR-NART  禁止报文自动重传 DISABLE-自动重传   ENABLE-不自动重传
    CAN_InitStructure.CAN_RFLM=DISABLE;         //MCR-RFLM  接收FIFO 锁定模式 DISABLE-溢出时新报文会覆盖原有报文  
    CAN_InitStructure.CAN_TXFP=DISABLE;         //MCR-TXFP  发送FIFO优先级 DISABLE-优先级取决于报文标示符 
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;  	//正常工作模式

    /************************ CAN通信波特率设置 **********************************/
    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
    CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;      //BTR-TS1 时间段1 占用了5个时间单元
    CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;      //BTR-TS1 时间段2 占用了3个时间单元
    CAN_InitStructure.CAN_Prescaler =4;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+5+3)/4=1Mbps
    #endif

    #if 0
    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_1tq;      //BTR-TS1 时间段2 占用了1个时间单元
    CAN_InitStructure.CAN_Prescaler =9;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+2+1)/9=1Mbps
    #endif

    #if 1
    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_1tq;      //BTR-TS1 时间段2 占用了1个时间单元
    CAN_InitStructure.CAN_Prescaler =18;        //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+2+1)/18=0.5Mbps
    #endif

    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
    CAN_InitStructure.CAN_BS1=CAN_BS1_3tq;      //BTR-TS1 时间段1 占用了2个时间单元
    CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;      //BTR-TS1 时间段2 占用了3个时间单元
    CAN_InitStructure.CAN_Prescaler =12;        //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+3+2)/12=0.5Mbps
    #endif


    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
    CAN_InitStructure.CAN_BS1=CAN_BS1_7tq;      //BTR-TS1 时间段1 占用了7个时间单元
    CAN_InitStructure.CAN_BS2=CAN_BS2_4tq;      //BTR-TS1 时间段2 占用了4个时间单元
    CAN_InitStructure.CAN_Prescaler =6;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+7+4)/6=0.5Mbps
    #endif

    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
    CAN_InitStructure.CAN_BS1=CAN_BS1_13tq;     //BTR-TS1 时间段1 占用了13个时间单元
    CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;      //BTR-TS1 时间段2 占用了2个时间单元
    CAN_InitStructure.CAN_Prescaler =9;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+13+2)/9=250Kbps
    #endif

    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
    CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;      //BTR-TS1 时间段1 占用了8个时间单元
    CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;      //BTR-TS1 时间段2 占用了7个时间单元
    CAN_InitStructure.CAN_Prescaler =9;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+8+7)/9=250Kbps
    #endif

    #if 0
    if (CAN_Init(CAN1, &CAN_InitStructure) == CAN_InitStatus_Failed)
    {
        printf("Initialize CAN failed!\n\r");
    }
    else
    {
        printf("Initialize CAN Success!\n\r");
    }
    #endif
    CAN_Init(CAN1, &CAN_InitStructure);
}

 

计算方法

 

这里的500Kbps,是怎么计算出来的?

 

    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_1tq;      //BTR-TS1 时间段2 占用了1个时间单元
    CAN_InitStructure.CAN_Prescaler =18;        //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+2+1)/18=0.5Mbps

 

通过查看STM32F103 的参考手册,找到了答案

 

 

 

计算过程

 

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

 

 

波特率 = 1 / 位时间

位时间 = (1*tq + tbs1 + tbs2),注意,这里与 CAN_SJW_1tq 无关!!

如果:tbs1 = 2 , tbs2 = 1,则: 位时间 =  (1+2+1)tq = 4 tq。

注意:这里,还有个分频, 分频分的不是主频(71MHz),是CAN总线的APB1 频率,手册上写着,36MHz,也就是 主频的2分频。

系统默认初始化后,APB1总线频率,设置为 36MHz。

这里CAN控制器,可以把APB1 继续分频,如 18,那么,CAN控制器频率:36Mhz / 18 = 2 Mhz。

波特率: =  1 /  4 * (1/2Mhz) = 0.5Mhz = 500 Kbps

 

 

 

总结

 

CAN通信,是比较好用的串行总线,不仅用于汽车上,一些工业总线场合短距离的通信,也可以说使用。

CAN通信,波特率、滤波器设置,都需要清楚,才能真正用好。

 

 

 

  • 0
    点赞
  • 0
    评论
  • 5
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

张世争

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值