智能手机网站建设,广告视频,vps建设网站别人访问不了,swoole wordpress文章目录 目的关键配置与代码轮询方式中断方式收发测试 示例链接总结 目的
CAN是非常常用的一种数据总线#xff0c;被广泛用在各种车辆系统中。这篇文章将对STM32中FDCAN的使用做个示例。
CAN的一些基础介绍与使用可以参考下面文章#xff1a; 《CAN基础概念》https://blo… 文章目录 目的关键配置与代码轮询方式中断方式收发测试 示例链接总结 目的
CAN是非常常用的一种数据总线被广泛用在各种车辆系统中。这篇文章将对STM32中FDCAN的使用做个示例。
CAN的一些基础介绍与使用可以参考下面文章 《CAN基础概念》https://blog.csdn.net/Naisu_kun/article/details/132814079 《STM32 CAN使用记录bxCAN基础通讯》https://blog.csdn.net/Naisu_kun/article/details/132830073
本文使用STM32H750作为主控芯片PD0设置为FDCAN1_RX 、 PD1设置为FDCAN1_TX 。本文使用使用STM32CubeIDE进行开发。
关键配置与代码
轮询方式 除了默认生成的代码只需在 main.c 中手动添加一些代码即可
#include main.hFDCAN_HandleTypeDef hfdcan1;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_FDCAN1_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_FDCAN1_Init();/**************** 以下为过滤器设置 ****************/FDCAN_FilterTypeDef sFilterConfig;// 下面这组设置只接受标准帧ID为0x666的消息sFilterConfig.IdType FDCAN_STANDARD_ID;sFilterConfig.FilterIndex 0;sFilterConfig.FilterType FDCAN_FILTER_MASK;sFilterConfig.FilterConfig FDCAN_FILTER_TO_RXFIFO0;sFilterConfig.FilterID1 0x666;sFilterConfig.FilterID2 0x7FF;sFilterConfig.RxBufferIndex 0;HAL_FDCAN_ConfigFilter(hfdcan1, sFilterConfig);// 下面这组设置只接受扩展ID为0x233和0x2233的消息sFilterConfig.IdType FDCAN_EXTENDED_ID;sFilterConfig.FilterIndex 0;sFilterConfig.FilterType FDCAN_FILTER_MASK;sFilterConfig.FilterConfig FDCAN_FILTER_TO_RXFIFO0;sFilterConfig.FilterID1 0x00002233;sFilterConfig.FilterID2 0x1FFFDFFF;sFilterConfig.RxBufferIndex 0;HAL_FDCAN_ConfigFilter(hfdcan1, sFilterConfig);// 默认情况下如果未配置全局过滤器则会接收所有不匹配的帧并将其重定向到RxFIFO0// 后面四个参数分别 拒绝未匹配的标准数据帧 拒绝未匹配的扩展数据帧 拒绝标准远程帧 拒绝扩展远程帧HAL_FDCAN_ConfigGlobalFilter(hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);/**************** 以下为启动CAN外设 ****************/HAL_FDCAN_Start(hfdcan1);while (1){/**************** 以下为接收消息并回发处理 ****************/if(HAL_FDCAN_GetRxFifoFillLevel(hfdcan1, FDCAN_RX_FIFO0) ! 0) // 接收队列不为0有数据可读{FDCAN_RxHeaderTypeDef RxHeader; // 用来保存接收到的数据帧头部信息uint8_t RxData[64]; // 用来保存接收数据端数据if(HAL_FDCAN_GetRxMessage(hfdcan1, FDCAN_RX_FIFO0, RxHeader, RxData) HAL_OK) // 从接收队列中读取数据帧{FDCAN_TxHeaderTypeDef TxHeader {0}; // 用来保存发送数据帧头部信息uint8_t TxData[64]; // 用来保存发送数据帧数据TxHeader.Identifier RxHeader.Identifier;TxHeader.IdType RxHeader.IdType; // 标准-FDCAN_STANDARD_ID; 扩展-FDCAN_EXTENDED_IDTxHeader.TxFrameType RxHeader.RxFrameType; // 数据帧-FDCAN_DATA_FRAME; 远程帧-FDCAN_REMOTE_FRAMETxHeader.DataLength RxHeader.DataLength; // FDCAN_DLC_BYTES_xx// xx 0 1 2 3 4 5 6 7 8 12 16 20 24 32 48 64TxHeader.ErrorStateIndicator RxHeader.ErrorStateIndicator; // FDCAN_ESI_ACTIVE FDCAN_ESI_PASSIVETxHeader.BitRateSwitch RxHeader.BitRateSwitch; // 波特率不可变-FDCAN_BRS_OFF; 波特率可变-FDCAN_BRS_ONTxHeader.FDFormat RxHeader.FDFormat; // 经典CAN-FDCAN_CLASSIC_CAN; CANFD-FDCAN_FD_CAN// TxHeader.TxEventFifoControl FDCAN_NO_TX_EVENTS;// TxHeader.MessageMarker 0;for(int i0; i64; i){TxData[i] RxData[i];}while(HAL_FDCAN_GetTxFifoFreeLevel(hfdcan1) 0); // 等待有发送邮箱可用HAL_FDCAN_AddMessageToTxFifoQ(hfdcan1, TxHeader, TxData); // 发送数据帧}}}
}中断方式 除了默认生成的代码只需在 main.c 中手动添加一些代码即可
#include main.hFDCAN_HandleTypeDef hfdcan1;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_FDCAN1_Init(void);/**************** 以下为重写中断回调函数 ****************/
// Fifo0收到消息回调
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{if (hfdcan hfdcan1) // 判断是hfdcan1的中断{if ((RxFifo0ITs FDCAN_IT_RX_FIFO0_NEW_MESSAGE) ! RESET) // 判断是FIFO0_NEW_MESSAGE回调{FDCAN_RxHeaderTypeDef RxHeader; // 用来保存接收到的数据帧头部信息uint8_t RxData[64]; // 用来保存接收数据端数据if(HAL_FDCAN_GetRxMessage(hfdcan1, FDCAN_RX_FIFO0, RxHeader, RxData) HAL_OK) // 从接收队列中读取数据帧{FDCAN_TxHeaderTypeDef TxHeader {0}; // 用来保存发送数据帧头部信息uint8_t TxData[64]; // 用来保存发送数据帧数据TxHeader.Identifier RxHeader.Identifier;TxHeader.IdType RxHeader.IdType; // 标准-FDCAN_STANDARD_ID; 扩展-FDCAN_EXTENDED_IDTxHeader.TxFrameType RxHeader.RxFrameType; // 数据帧-FDCAN_DATA_FRAME; 远程帧-FDCAN_REMOTE_FRAMETxHeader.DataLength RxHeader.DataLength; // FDCAN_DLC_BYTES_xx// xx 0 1 2 3 4 5 6 7 8 12 16 20 24 32 48 64TxHeader.ErrorStateIndicator RxHeader.ErrorStateIndicator; // FDCAN_ESI_ACTIVE FDCAN_ESI_PASSIVETxHeader.BitRateSwitch RxHeader.BitRateSwitch; // 波特率不可变-FDCAN_BRS_OFF; 波特率可变-FDCAN_BRS_ONTxHeader.FDFormat RxHeader.FDFormat; // 经典CAN-FDCAN_CLASSIC_CAN; CANFD-FDCAN_FD_CAN// TxHeader.TxEventFifoControl FDCAN_NO_TX_EVENTS;// TxHeader.MessageMarker 0;for(int i0; i64; i){TxData[i] RxData[i];}while(HAL_FDCAN_GetTxFifoFreeLevel(hfdcan1) 0); // 等待有发送邮箱可用HAL_FDCAN_AddMessageToTxFifoQ(hfdcan1, TxHeader, TxData); // 发送数据帧}}}
}int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_FDCAN1_Init();/**************** 以下为过滤器设置 ****************/FDCAN_FilterTypeDef sFilterConfig;// 下面这组设置只接受标准帧ID为0x666的消息sFilterConfig.IdType FDCAN_STANDARD_ID;sFilterConfig.FilterIndex 0;sFilterConfig.FilterType FDCAN_FILTER_MASK;sFilterConfig.FilterConfig FDCAN_FILTER_TO_RXFIFO0;sFilterConfig.FilterID1 0x666;sFilterConfig.FilterID2 0x7FF;sFilterConfig.RxBufferIndex 0;HAL_FDCAN_ConfigFilter(hfdcan1, sFilterConfig);// 下面这组设置只接受扩展ID为0x233和0x2233的消息sFilterConfig.IdType FDCAN_EXTENDED_ID;sFilterConfig.FilterIndex 0;sFilterConfig.FilterType FDCAN_FILTER_MASK;sFilterConfig.FilterConfig FDCAN_FILTER_TO_RXFIFO0;sFilterConfig.FilterID1 0x00002233;sFilterConfig.FilterID2 0x1FFFDFFF;sFilterConfig.RxBufferIndex 0;HAL_FDCAN_ConfigFilter(hfdcan1, sFilterConfig);// 默认情况下如果未配置全局过滤器则会接收所有不匹配的帧并将其重定向到RxFIFO0// 后面四个参数分别 拒绝未匹配的标准数据帧 拒绝未匹配的扩展数据帧 拒绝标准远程帧 拒绝扩展远程帧HAL_FDCAN_ConfigGlobalFilter(hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);/**************** 以下为启动中断 ****************/HAL_FDCAN_ActivateNotification(hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); // 使能FIFO0数据接收中断/**************** 以下为启动CAN外设 ****************/HAL_FDCAN_Start(hfdcan1);while (1){}
}收发测试
本示例演示结果可以通过各种CAN工具配合上位机软件进行测试
示例链接
仓库地址 https://github.com/NaisuXu/STM32_MCU_Examples
本文中的示例位于仓库中 FDCAN_RxTxPoll_H750 和 FDCAN_RxTxIT_H750 。
总结
STM32中使用FDCAN并不复杂进行配置生成代码后只需要设置过滤器然后就可以收发数据了。