STM32F103 CAN通信波特率的计算方法
前言
- 以下的波特率计算和实例仅针对 STM32F1系列
- 最近看一下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*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通信,波特率、滤波器设置,都需要清楚,才能真正用好。
文章转载自并进行了部分修改: 转载
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)