前言
stm32 cubemx can通讯(1)回环模式
stm32 cubemx can通讯(2)过滤器设置说明代码分析
根据前两篇文章已经能够实现can标准帧的收发,但是调用的函数没有标准化和可扩展性。
所以本文讲解bsp,在bsp中已经有了发送函数和接受回调函数的任务映射处理回调函数。
暂时(2023.8.10)还未加入过滤器配置,所以过滤器还是需要在can_init中进行配置。
(2023.9.29)修改文章,加入了cubemx的配置,以及对can的连接。
文件
一、cubemx配置
1.F407ZET6
2.F103C8T6
二、物理连接【stm32can连接】
系统板上一般不会有can收发器,
所以要自己外置一个,我用的是TJA1050
这个模块的vcc只能接3.3.不要接5v
一定要注意连接如图
这个和串口的不同,千万不要连反了。
三、bsp
bsp_can.h
#ifndef __BSP_CAN_H
#define __BSP_CAN_H
#include "main.h"
#include "can.h"
uint8_t CANSend(CAN_HandleTypeDef *hcan,
uint32_t Source_ID,
uint32_t IDE,
uint32_t RTR,
uint8_t* Datum,
uint8_t DataLength);
typedef struct {
uint32_t id;
uint32_t idType; // CAN_ID_STD or CAN_ID_EXT
void (*callback)(uint8_t* data);
} CAN_CallbackMapType;
#endif
bsp_can.c
#include "bsp_can.h"
/**
* 发送CAN数据
* @param hcan: 使用的CAN句柄
* @param Source_ID: 消息ID
* @param IDE: 标识符类型 (CAN_ID_STD 或 CAN_ID_EXT)
* @param RTR: 消息类型 (CAN_RTR_DATA 或 CAN_RTR_REMOTE)
* @param Datum: 要发送的数据
* @param DataLength: 数据长度
* @return: HAL的状态 ( 1 成功 0 失败 )
*/
#define CAN_MAX_DATA_LENGTH 8
uint8_t CANSend(CAN_HandleTypeDef *hcan,
uint32_t Source_ID,
uint32_t IDE,
uint32_t RTR,
uint8_t* Datum,
uint8_t DataLength)
{
// 参数验证
if (!hcan || !Datum ||
(IDE != CAN_ID_STD && IDE != CAN_ID_EXT) ||
DataLength > CAN_MAX_DATA_LENGTH)
{
return 0;
}
CAN_TxHeaderTypeDef TXHeader;
uint32_t pTxMailbox = 0;
if (IDE == CAN_ID_STD)
{
TXHeader.StdId = Source_ID;
}
else
{
TXHeader.ExtId = Source_ID;
}
TXHeader.IDE = IDE;
TXHeader.DLC = DataLength;
TXHeader.RTR = RTR;
TXHeader.TransmitGlobalTime = DISABLE;
HAL_StatusTypeDef status = HAL_CAN_AddTxMessage(hcan, &TXHeader, Datum, &pTxMailbox);
if (status == HAL_OK)
{
return 1; // 返回1表示成功
}
else
{
return 0; // 返回0表示失败
}
}
/* USER CODE BEGIN mapping_function */
int cc =0;
// 示例的回调函数
void handle_ID_0x01(uint8_t *data) {
// 对于ID 0x01的处理代码
cc=1;
}
void handle_ID_0x02(uint8_t *data) {
// 对于ID 0x02的处理代码
cc=2;
}
void handle_ID_0x12345678(uint8_t *data) {
// 对于ID 0x02的处理代码
cc=4;
}
// 初始化映射表
CAN_CallbackMapType callbackMap[] = {
{0x01, CAN_ID_STD, handle_ID_0x01},
{0x02, CAN_ID_STD, handle_ID_0x02},
// 添加一个扩展ID的例子
{0x12345678, CAN_ID_EXT, handle_ID_0x12345678}
};
/* USER CODE mapping_function */
const uint8_t mapSize = sizeof(callbackMap) / sizeof(CAN_CallbackMapType);
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance == CAN1)
{
// 获取数据
CAN_RxHeaderTypeDef RXHeader;
uint8_t RXmessage[8]; // 确保这里的数组大小正确
if(HAL_CAN_GetRxMessage(hcan, CAN_FILTER_FIFO0, &RXHeader, RXmessage) == HAL_OK)
{
for(uint8_t i = 0; i < mapSize; i++)
{
if(RXHeader.IDE == callbackMap[i].idType &&
(RXHeader.IDE == CAN_ID_STD && RXHeader.StdId == callbackMap[i].id ||
RXHeader.IDE == CAN_ID_EXT && RXHeader.ExtId == callbackMap[i].id) &&
callbackMap[i].callback)
{
callbackMap[i].callback(RXmessage);
break;
}
}
}
}
}
四、发送如何使用
如果不使用过滤器的话
stm32 cubemx can通讯(2)过滤器设置说明代码分析
就需要在初始化的地方加入 HAL_CAN_Start(&hcan);
因为过滤器那个地方有这句话,而如果不加这句话的话就不能正常发送。
发送函数可以直接调用。
uint8_t TXmessage[8] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
CANSend(&hcan,0x12,CAN_ID_STD,CAN_RTR_DATA,TXmessage,8);
五、接收如何使用
要使用接收必须先配置过滤器。!!!
我的过滤函数写在can.c中,我发现写在其他地方不行。原因不明待解决文章来源:https://www.toymoban.com/news/detail-645563.html
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // 16-bit列表模式用于标准ID
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;//采用FIFO0
// 过滤器匹配0x1
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterIdHigh = 0x1 << 5;
sFilterConfig.FilterMaskIdHigh = 0xFFFF;
if(HAL_CAN_ConfigFilter(&hcan2,&sFilterConfig) != HAL_OK)//初始化过滤器
{
Error_Handler();
}
// 过滤器匹配0x1
sFilterConfig.FilterBank = 1;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterIdHigh = 0x2<< 5;
sFilterConfig.FilterMaskIdHigh = 0xFFFF;
if(HAL_CAN_ConfigFilter(&hcan2,&sFilterConfig) != HAL_OK)//初始化过滤器
{
Error_Handler();
}
// HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
// sFilterConfig.FilterActivation = ENABLE;//打开过滤器
// sFilterConfig.FilterBank = 0;//过滤器0 这里可设0-13
// sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;//采用掩码模式
// sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;//采用32位掩码模式
// sFilterConfig.FilterIdHigh = 0x0000; //设置过滤器ID高16位
// sFilterConfig.FilterIdLow = 0x0000;//设置过滤器ID低16位
// sFilterConfig.FilterMaskIdHigh = 0x0000;//设置过滤器掩码高16位
// sFilterConfig.FilterMaskIdLow = 0x0000;//设置过滤器掩码低16位
// if(HAL_CAN_ConfigFilter(&hcan,&sFilterConfig) != HAL_OK)//初始化过滤器
// {
// Error_Handler();
// }
if(HAL_CAN_Start(&hcan2) != HAL_OK)//打开can
{
Error_Handler();
}
if(HAL_CAN_ActivateNotification(&hcan2,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)//开启接受邮箱0挂起中断
{
Error_Handler();
}
接收函数的回调函数不需要进行修改,当有任务需要处理的时候先写任务处理的回调函数也就是示例代码中的void handle_ID_0x01(uint8_t *data)
之类的。
然后再进行初始化映射CAN_CallbackMapType callbackMap[]
所以只需要在/* USER CODE BEGIN mapping_function */
之间修改函数即可。其他的不需要更改。文章来源地址https://www.toymoban.com/news/detail-645563.html
总结
到了这里,关于stm32 cubemx can通讯(3)bsp_can的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!