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通信,波特率、滤波器设置,都需要清楚,才能真正用好。
文章转载自并进行了部分修改: 转载
STM32F103 CAN通信波特率的计算方法的更多相关文章
- 十天学会单片机Day4串行口通信
并行与串行基本通信方式 1.并行通信方式 通常是将数据字节的各位用多条数据线同时进行传送. 并行通信控制简单.传输速度快:由于传输线较多,长距离传送时成本高且接收方的各位同时接收存在困难. 2.串行通 ...
- 单片机modebus RTU通信实现,採用C语言,可适用于单片机,VC,安卓等
当前使用的是STM32+ucos_ii编写的,能够移植到安卓以及VC .NET等方便移植使用,採用modebus poll測试过. 仅仅须要改动响应的通信接口就可以,方便多串口使用 //modebus ...
- 单片机modebus RTU通信实现,采用C语言,可适用于单片机,VC,安卓等(转)
源:单片机modebus RTU通信实现,采用C语言,可适用于单片机,VC,安卓等 //modebus_rtu.c /***************************************** ...
- 在C#中实现串口通信的方法
通常,在C#中实现串口通信,我们有四种方法: 第一:通过MSCOMM控件这是最简单的,最方便的方法.可功能上很难做到控制自如,同时这个控件并不是系统本身所带,所以还得注册,不在本文讨论范围.可以访问h ...
- PC软件与PLC串口通信 奇偶检验问题
PC软件与PLC进行串口通信 波特率:19200 校验位:偶检验 数据位:8 停止位:1 现象 一,PC软件向PLC可以发送1,2,4,5,7,8,但是3,6,9发送出去后,PLC无法收到 二,使 ...
- 抽屉柜式MCC柜中PROFIBUS设备推荐波特率及相应传输距离
抽屉柜式MCC柜中PROFIBUS设备推荐波特率及相应传输距离.例如以下图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L ...
- [4G]Linux平台上实现4G通信
转自:http://blog.sina.com.cn/s/blog_7880d3350102wb92.html 在ARM平台上实现4G模块的PPP拨号上网,参考网上的资料和自己的理解,从一无所知到开发 ...
- PC和FPGA间的串口通信实现
应用笔记 V1.0 2015/03/26 PC和FPGA间的串口通信实现 概述 本文将介绍PC和FPGA间的串口通信实现的基本思路和Verilog代码,对于通信而言,收发双方都要有相应的控制. ...
- STM32F103 GU906B模块GPRS、短信收发、拨号等功能的实现
这个程序搞了我很久,尤其是对如何提高响应速度上,程序流程很简单,大概就是: 发送AT指令->等待模块响应->一旦响应了,立即返回,并处理掉. 这个程序不一定只能用在GU906上,程序框架在 ...
- RS485通信和Modbus协议(转)
转自:http://www.51hei.com/bbs/dpj-23230-1.html 在工业控制.电力通讯.智能仪表等领域,通常情况下是采用串口通信的方式进行数据交换.最初采用的方式是RS232接 ...
随机推荐
- Variable 'xxxx' is accessed from within inner class, needs to be final or effectively final-Lambda 表达式的变量与作用域
问题的原因 问题代码: public static void main(String[] args) { Integer sum = 0; Integer count = 0; List<Int ...
- C++ 核心指南之 C++ 哲学/基本理念(下)
C++ 核心指南(C++ Core Guidelines)是由 Bjarne Stroustrup.Herb Sutter 等顶尖 C+ 专家创建的一份 C++ 指南.规则及最佳实践.旨在帮助大家正确 ...
- 使用logrotate定期切割nginx日志
前言 默认情况下,nginx的日志都会写到access.log文件中,访问流量大的话,日志文件很快就会膨胀到几十G,不方便分析处理,也占用硬盘空间.借助linux自带的logrotate工具可以很方便 ...
- redis集群:MASTER aborted replication with an error: NOAUTH Authentication required.
发现个问题:redis集群所在服务器,磁盘空间很快就被占满,使用 "du -sh *"查看每个文件夹的大小,发现redis集群三个从节点的日志文件占用空间很大. 下面记录问题排查及 ...
- 一行命令即可启动 Walrus丨入门教程
应用管理平台 Walrus 已正式开源,本文将介绍如何上手安装 Walrus 以及如何借助 Walrus 进行应用部署. 开源地址:https://github.com/seal-io/walrus ...
- 《Linux基础》05. 定时任务调度 · 磁盘分区与挂载 · 网络配置
@ 目录 1:定时任务调度 1.1:crontab 1.2:at 2:磁盘分区与挂载 2.1:原理介绍 2.2:硬盘说明 2.3:磁盘目录情况查询 2.3.1:lsblk 2.3.2:df 2.3.3 ...
- Vue【原创】时间轴 【time-axis】&【date-axis】
封装了关于时间轴的组件,有时候统计页面会用到. 效果图: 时间轴分为2种,一种是time-axis:范围选择模式,一种是date-axis:步长选择模式. 代码中涉及到的工具类和图片资源,请移步页面底 ...
- 以程序员为视角,关于商品详情API接口的说明
商品详情API接口是现代电商平台中非常重要的一部分,它提供了获取淘宝商品详细信息的能力.作为一个程序员,了解如何调用这个API接口是非常关键的. 首先,我们需要明确的是,API接口是应用程序与服务 ...
- 弹性数据库连接池探活策略调研(一)——HikariCP
调研背景: 数据库连接建立是比较昂贵的操作(至少对于 OLTP),不仅要建立 TCP 连接外还需要进行连接鉴权操作,所以客户端通常会把数据库连接保存到连接池中进行复用.连接池维护到弹性数据库(JED) ...
- 关于TCP 四次挥手过程中的reset包问题
数据包过程 TCP状态机转换过程 客户端在接受到第32个数据包之后,应该发送1个对FIN的ACK数据包,然而客户端缺直接连续发送了3个Rest数据包36~38,客户端并未进入time wait阶段,直 ...