stm32 cubemx can通讯(3)bsp_can

文章目录


前言

stm32 cubemx can通讯(1)回环模式
stm32 cubemx can通讯(2)过滤器设置说明代码分析

根据前两篇文章已经能够实现can标准帧的收发,但是调用的函数没有标准化和可扩展性。

所以本文讲解bsp,在bsp中已经有了发送函数和接受回调函数的任务映射处理回调函数。

暂时(2023.8.10)还未加入过滤器配置,所以过滤器还是需要在can_init中进行配置。

文件


一、bsp

bsp_can.h

c 复制代码
#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

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;
                }
            }
        }
    }
}

二、如何使用

发送函数可以直接调用。

c 复制代码
uint8_t TXmessage[8] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
CANSend(&hcan,0x12,CAN_ID_STD,CAN_RTR_DATA,TXmessage,8);

接收函数的回调函数不需要进行修改,当有任务需要处理的时候先写任务处理的回调函数也就是示例代码中的void handle_ID_0x01(uint8_t *data)之类的。

然后再进行初始化映射CAN_CallbackMapType callbackMap[]

所以只需要在/* USER CODE BEGIN mapping_function */之间修改函数即可。其他的不需要更改。


总结

相关推荐
烬羽1 分钟前
给 Agent 一个检索式记忆:把对话历史存进 Milvus,该记的都记得
javascript·数据库·agent
磐链科技11 分钟前
区块链开发入门实战:用 Hardhat 与 Ethers.js 搭建你的第一个 DApp
开发语言·javascript·区块链
码艺-Alimjan25 分钟前
维吾尔语数字转文本
java·javascript·python·算法·go
可乐鸡翅yeah_25 分钟前
hls.js 多实例并发踩坑,多视频页面播放器内存与冲突问题解决
开发语言·前端·javascript·音视频·hls·m3u8·m3u8在线播放
涛涛ing34 分钟前
你的页面为什么总是卡成PPT?2026年,90%的前端都忽略了主线程
前端
SoaringHeart35 分钟前
Flutter 进阶 | 组件封装:用 CustomPainter 实现光环动画组件AnimatedHalo
前端·flutter
IT_陈寒39 分钟前
JavaScript的隐式转换太坑了,我的==比较怎么就炸了?
前端·人工智能·后端
单片机仿真设计41 分钟前
【Proteus 仿真】基于 STM32 单片机智能楼宇照明控制系统设计(定制仿真咨询)
stm32·单片机·嵌入式硬件·proteus·毕设
雪芽蓝域zzs1 小时前
第十四节:后端返回权限动态路由
前端·javascript·vue.js
小磊哥er1 小时前
Wonder Claude Code - 一个可运行的、教学级的 Claude Code 精简复刻
javascript·ai编程