STM32-18 CAN-BUS (上)

前几篇有介绍过CANBus~透过MCP2515模块去完成通讯。
这篇会使用STM32当中的CAN-Bus来实现通讯~


与之前介绍Can不同的是在STM32当中将一个bit分为3个区段而已,将传播段与相位缓冲段1结合。
http://img2.58codes.com/2024/20146325iCrgPyrniY.png
http://img2.58codes.com/2024/20146325kvpgVsPi6H.jpg
可以看到在STM32当中将Bit仅分为3个区段,而同步区段固定为1Tq ; BS1为0-16TQ ;BS2为0-8TQ,採样点同样落在BS1与BS2交界。


计算说明

计算Time Quantum (TQ)

TQ = (BRP+1) x Tpclk

TQ= (15+1) x (1/16) = 0.9375(us) = 937.5(ns)

BPR : 预分频係数 Tpclk : APB Clock 週期

计算Bit Timing

这时可以知道1个TQ为937.5ns,同时SyncSeg固定为1TQ 后续BS1为4TQ BS2为3TQ:

Bit Timing : TQ timing x (1+BS1+BS2)

937.5ns x 8 = 7500ns

TQ Timing : 上方计算出来1 TQ的时间
BS1 : BS1 的TQ数量 BS2 : BS2的TQ数量

计算Baud Rate

Baud Rate = 1 / Bit Timing
1 / 7500ns x 1000000000 = 133333 bit/s

1000000000是因为ns换为s

採样点计算

(SyncSeg + BS1 )/ 总TQ数量 *100%

以上方来说即为 5 / 8 x 100% = 62.5%

採样点在通讯过程最好是落在60~70%,所以在选择TQ数量时要注意採样点位置!


传送与接收

发送 :3 个 Tx Buffer (Tx0 Tx1 Tx2)可设置Buffer优先级,根据优先级决定哪个Buffer优先发送接收 :2 个 FIFO Rx Buffer (RX0 RX1)每个Rx Buffer当中可以接收3笔资料

FIFO (First In First Out) : 先进先出,在RX Buffer当中可以储存3笔资料,会按照接收到的讯息顺序,读取最先接收到的讯息。

换个方式说假如今天邮差送了一封信到信箱当中而且信箱大小只能容纳3封,那这封信就会变成编号1的信件(CAN_RFR→FMP = 0b01),这时候可以选择去收信或是晚点收。

马上收信 : 从信箱当中拿走信(CAN_RFR→RFOM = 1),信箱当中是空的了,这时候信箱会将编号归0,可以重複这个步骤接收下一封信件。

晚点收信 : 信箱中还是有着一封信,假设又收到一封信但由于刚刚没有取走第一封,这时候就会改为编号2的信件(CAN_RFR→FMP = 0b10),当累积到第三封信件时(CAN_RFR→FMP = 0b11)信箱已经满了,所以当第四封信件就会放置在信箱外面(溢出)。

针对信箱满了的情况下可以分为两种处理方法:

新的信件直接覆盖掉刚刚接收的最后一封信件也就是编号3的信件 (CAN_MCR→RFLM = 0)丢弃新信件,保留前面所接收到的3封信(CAN_MCR→RFLM = 1)

CAN 中断说明

在STM32当中CAN具有4个向量中断 :

TX Interrupt : 传送中断,有3个Tx Buffer (0 1 2)当Tx Buffer 0 当中为空时,触发传送中断(CAN_TSR→RQCP0 = 1)当Tx Buffer 1 当中为空时,触发传送中断(CAN_TSR→RQCP1 = 1)当Tx Buffer 2 当中为空时,触发传送中断(CAN_TSR→RQCP2 = 1)FIFO0 Interrupt : 接收中断,有2个Rx Buffer (0 1),每一个Buffer可以储存3笔资料当FIFO0接收到一笔讯息,触发中断当FIFO0当中接收满3讯息时,触发中断(CAN_RF0R→FULL0 = 1)当FIFO0接收满3讯息时又接收了第4笔,发生溢位触发中断(CAN_RF0R→FOVR0 = 1)FIFO1 Interrupt : 接收中断,有2个Rx Buffer (0 1),每一个Buffer可以储存3笔资料当FIFO1接收到一笔讯息,触发中断当FIFO1当中接收满3讯息时,触发中断(CAN_RF1R→FULL1 = 1)当FIFO1接收满3讯息时又接收了第4笔,发生溢位触发中断(CAN_RF1R→FOVR1 = 1)SCE Interrupt (status change error interrupt) : 状态改变与错误中断当出现错误导致中断(CAN_ESR) EX: 接收错误计数器>127、离线唤醒节点时进入睡眠模式时

.IOC设置说明

我使用的板子是L476RG,只具备一个CAN通讯(CAN1)。
http://img2.58codes.com/2024/20146325zDRvc7aoKg.png

Prescaler : 等于上方计算公式的BPR,影响的是TQ的时间。
这边我APB Clock为16 ,Prescaler 设为15
(15+1) x (1/16) = 0.9375(us) = 937.5(ns)

Time Quanta Bit Segment 1 : 传播段与相位缓冲段1结合,会影响到採样点的位置

Time Quanta Bit Segment 2 : 相位缓冲段2,会影响到採样点的位置

以上我设置为4TQ与3TQ,而同步段固定为1TQ共8TQ,所以看以看到下方Time for One Bit 为7500ns (937.5ns x 8 = 7500ns)

Baud Rate : 1 / 7500ns x 1000000000 = 133333 bit/s

ReSynchronization Jump Width : 重新同步跳转宽度,用来弥补两设备间的通讯误差,可设置範围0-4TQ。
http://img2.58codes.com/2024/20146325Foe7DH04EC.png
上方图为基本模式设定,这边就都选Disable即可。
而最后的是工作模式选择 : 分为正常模式、环回模式、静默模式等等,因为我手边只有一块就先选环回模式来测试。
http://img2.58codes.com/2024/201463256z1weYUx9u.png
四个中断向量则是上方说明的四个,根据需要可以开启对应的中断。


相关函数

设定CAN接收的Filter
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)
启动CAN
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan)
停止CAN
HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan)
CAN发送讯息: 将一笔讯息送至Buffer当中,同时会请求传送
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox)
停止传送请求
HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes)
检查所选的TxBuffer是否有传送请求
uint32_t HAL_CAN_IsTxMessagePending(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes)
从RXBuffer获取接收的讯息
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])
检查指定的RxBuffer内所接收到的讯息数(FIFO = 1 2 3)
uint32_t HAL_CAN_GetRxFifoFillLevel(CAN_HandleTypeDef *hcan, uint32_t RxFifo)
CAN中断处理函数 : 依照状态调用下方对应接收与传送回调函数
void HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan)
Tx Buffer 0 传送中断回调函数
__weak void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
Tx Buffer 1 传送中断回调函数
__weak void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan)
Tx Buffer 2 传送中断回调函数
__weak void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan)
Rx Buffer 0 接收中断回调函数
__weak void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan){if(hcan->Instance==CAN1){HAL_CAN_GetRxMessage(&hcan1,CAN_FILTER_FIFO0,&rxheader1,msg);}}
Rx Buffer 0 溢出中断回调函数 : 当接收满3笔讯息时
__weak void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan){  /* Prevent unused argument(s) compilation warning */  UNUSED(hcan);  /* NOTE : This function Should not be modified, when the callback is needed,            the HAL_CAN_RxFifo0FullCallback could be implemented in the user            file   */}
Rx Buffer 1 接收中断回调函数
__weak void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan){if(hcan->Instance==CAN1){HAL_CAN_GetRxMessage(&hcan1,CAN_FILTER_FIFO0,&rxheader1,msg);}}
Rx Buffer 1 溢出中断回调函数 : 当接收满3笔讯息时
__weak void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan){  /* Prevent unused argument(s) compilation warning */  UNUSED(hcan);  /* NOTE : This function Should not be modified, when the callback is needed,            the HAL_CAN_RxFifo0FullCallback could be implemented in the user            file   */}

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章