CAN通信波特率的计算方法
前言
之前使用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 / 位时间
那么,我们只需要计算 CAN 的位时间就可以了
根据参考手册上的计算方法,可以得出: 波特率 = 1 / BT = 1 / ((SEG_1 + 2)+ (SEG_2 + 1)) × TQ = 1 / ((SEG_1 + 2)+ (SEG_2 + 1)) ×( (PRESC + 1) / fcan_clk )
位时间 = 外部晶振频率(比如8Mhz)/((SEG_1 + 2) + (SEG_2 + 1)) ;
那么 125KBps 的计算:
SEG_1 = 3 ,SEG_2 = 2,PRESC = 7
还要注意can的频率,通过手册可知:
也就是说,你把外部晶振使能后,他就自动作为CAN的时钟了,其他地方不需要你配置,这里我用的外部时钟为 8Mhz。
波特率 = (1 / ( ( 5 + 3 ) * (8 / 8Mhz)) = 125Khz
CAN 波特率为 1Mhz的举例:
//<<Can bit time config stcCanInitCfg.stcCanBt.PRESC = 1u-1u; stcCanInitCfg.stcCanBt.SEG_1 = 5u-2u; stcCanInitCfg.stcCanBt.SEG_2 = 3u-1u; stcCanInitCfg.stcCanBt.SJW = 3u-1u; /* Fcanclk = XTAL_VALUE = 8M TQ = (PRESC+1) / Fcanclk = 1 / 8M BT = tseg1 + tseg2 = ((SEG_1+2) + (SEG_2+1)) * TQ = (5+3) * (1/8Mhz) = 1/1M */
1位要1/1M秒,换算成波特率就是1M了。
HC32F460 CAN通信问题刨析与解决 - - 21ic电子技术开发论坛
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)