怎样实现CAN数据的接收和发送?

news2025/3/30 20:16:51

在裸机环境下实现CAN数据的接收和发送,需要通过 硬件寄存器操作 或 HAL库函数 结合 手动实现的队列 来完成。以下是完整的接收和发送流程实现:

1. 硬件初始化
首先初始化CAN控制器和GPIO:

void CAN_Init(void) {
    // 1. 使能CAN时钟
    __HAL_RCC_CAN1_CLK_ENABLE();
    
    // 2. 配置CAN GPIO(以PB8/PB9为例)
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;  // CAN_RX/CAN_TX
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // 3. 配置CAN控制器
    hcan.Instance = CAN1;
    hcan.Init.Prescaler = 6;          // 波特率 = APB1时钟/(Prescaler*(BS1+BS2+SJW))
    hcan.Init.Mode = CAN_MODE_NORMAL; // 正常模式
    hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
    hcan.Init.TimeSeg1 = CAN_BS1_8TQ; 
    hcan.Init.TimeSeg2 = CAN_BS2_3TQ;
    hcan.Init.TimeTriggeredMode = DISABLE;
    hcan.Init.AutoBusOff = DISABLE;
    hcan.Init.AutoWakeUp = DISABLE;
    hcan.Init.AutoRetransmission = ENABLE; // 自动重传
    hcan.Init.ReceiveFifoLocked = DISABLE;
    hcan.Init.TransmitFifoPriority = DISABLE;
    HAL_CAN_Init(&hcan);

    // 4. 配置CAN过滤器(接收所有消息)
    CAN_FilterTypeDef filter;
    filter.FilterIdHigh = 0x0000;
    filter.FilterIdLow = 0x0000;
    filter.FilterMaskIdHigh = 0x0000;
    filter.FilterMaskIdLow = 0x0000;
    filter.FilterFIFOAssignment = CAN_RX_FIFO0; // 使用FIFO0
    filter.FilterBank = 0;
    filter.FilterMode = CAN_FILTERMODE_IDMASK;
    filter.FilterScale = CAN_FILTERSCALE_32BIT;
    filter.FilterActivation = ENABLE;
    HAL_CAN_ConfigFilter(&hcan, &filter);

    // 5. 启动CAN和中断
    HAL_CAN_Start(&hcan);
    HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING); // 启用FIFO0中断
}

2. 数据接收实现
(1)中断中接收数据并存入队列

void CAN_RX0_IRQHandler(void) {
    CanRxMsg_t rxMsg;
    
    // 从CAN硬件读取数据
    if (HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &rxMsg.id, rxMsg.data, &rxMsg.length) == HAL_OK) {
        // 存入接收队列(中断安全)
        if (!Queue_SendFromISR(&canRxQueue, &rxMsg, sizeof(CanRxMsg_t))) {
            // 队列满时的处理(如点亮LED警告)
            HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
        }
    }
    HAL_CAN_IRQHandler(&hcan); // 处理其他CAN中断
}

(2)主循环处理接收队列

while (1) {
    CanRxMsg_t rxMsg;
    
    // 从队列取出数据
    if (Queue_Receive(&canRxQueue, &rxMsg, sizeof(CanRxMsg_t))) {
        // 处理接收到的数据(示例:通过串口打印)
        printf("ID:0x%lX, Data:", rxMsg.id);
        for (int i = 0; i < rxMsg.length; i++) {
            printf("%02X ", rxMsg.data[i]);
        }
        printf("\n");
    }
    
    // 其他任务...
}

3. 数据发送实现
(1)发送数据到队列

void SendCANMessage(uint32_t id, uint8_t *data, uint8_t length) {
    CanTxMsg_t txMsg;
    txMsg.id = id;
    txMsg.length = length;
    memcpy(txMsg.data, data, length);
    
    // 非阻塞发送到队列
    if (!Queue_Send(&canTxQueue, &txMsg, sizeof(CanTxMsg_t))) {
        // 队列满处理
        printf("TX Queue Full!\n");
    }
}

(2)主循环处理发送队列

while (1) {
    CanTxMsg_t txMsg;
    
    // 检查发送队列
    if (Queue_Receive(&canTxQueue, &txMsg, sizeof(CanTxMsg_t))) {
        // 通过CAN硬件发送
        CAN_TxHeaderTypeDef txHeader;
        txHeader.StdId = txMsg.id;
        txHeader.IDE = CAN_ID_STD;
        txHeader.RTR = CAN_RTR_DATA;
        txHeader.DLC = txMsg.length;
        
        uint32_t mailbox;
        if (HAL_CAN_AddTxMessage(&hcan, &txHeader, txMsg.data, &mailbox) != HAL_OK) {
            printf("CAN Send Failed!\n");
        }
    }
    
    // 其他任务...
    HAL_Delay(1); // 防止CPU占用率100%
}

4. 关键机制说明
机制 实现方式
中断安全 在中断中使用 __disable_irq()/__enable_irq() 保护队列操作
非阻塞设计 所有队列操作立即返回,不等待
硬件发送 主循环轮询发送队列,通过 HAL_CAN_AddTxMessage 发送
错误处理 队列满时触发标志位或LED警告
数据一致性 使用 memcpy 保证数据完整拷贝
5. 完整示例流程
初始化

int main(void) {
    HAL_Init();
    SystemClock_Config();
    Queues_Init();
    CAN_Init();
    
    while (1) {
        ProcessRxQueue(); // 处理接收队列
        ProcessTxQueue(); // 处理发送队列
    }
}

外部调用发送:

// 发送示例数据
uint8_t data[] = {0x01, 0x02, 0x03};
SendCANMessage(0x123, data, 3);

中断自动接收:

数据到达 → 触发 CAN_RX0_IRQHandler → 存入 canRxQueue → 主循环处理。

6. 性能优化建议
DMA发送:对于高频发送,配置CAN TX DMA。

双缓冲接收:使用两个队列交替处理,避免数据覆盖。

优先级控制:为CAN中断设置合适优先级(通常高于普通任务)。

通过这种方式,裸机系统可以实现与RTOS类似的可靠通信,同时保持更高的实时性和更低的内存开销。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2322733.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux笔记---动静态库(使用篇)

目录 1. 库的概念 2. 静态库&#xff08;Static Libraries&#xff09; 2.1 静态库的制作 2.2 静态库的使用 2.2.1 显式指定库文件及头文件路径 2.2.2 将库文件安装到系统目录 2.2.3 将头文件安装到系统目录 3. 动态库 3.1 动态库的制作 3.2 动态库的使用 3.2.1 显式…

手机销售终端MPR+LTC项目项目总体方案P183(183页PPT)(文末有下载方式)

资料解读&#xff1a;手机销售终端 MPRLTC 项目项目总体方案 详细资料请看本解读文章的最后内容。在当今竞争激烈的市场环境下&#xff0c;企业的销售模式和流程对于其发展起着至关重要的作用。华为终端正处于销售模式转型的关键时期&#xff0c;波士顿 - 华为销售终端 MPRLTC …

【Python LeetCode Patterns】刷力扣,15 个学习模式总结

1. 前缀和&#xff08;Prefix Sum&#xff09;—— 查询子数组中元素和303. 区域和检索 - 数组不可变304. 二维区域和检索 - 矩阵不可变 2. 双指针&#xff08;Two Pointers&#xff09;—— 移向彼此或远离彼此3. 滑动窗口&#xff08;Sliding Window&#xff09;—— 找到满足…

蓝桥杯单片机刷题——串口发送显示

设计要求 通过串口接收字符控制数码管的显示&#xff0c;PC端发送字符A&#xff0c;数码管显示A&#xff0c;发送其它非法字符时&#xff0c;数码管显示E。 数码管显示格式如下&#xff1a; 备注&#xff1a; 单片机IRC振荡器频率设置为12MHz。 串口通信波特率&#xff1a;…

探索抓包利器ProxyPin,实现手机APP请求抓包,支持https请求

以下是ProxyPin的简单介绍&#xff1a; - ProxyPin是一个开源免费HTTP(S)流量捕获神器&#xff0c;支持 Windows、Mac、Android、IOS、Linux 全平台系统- 可以使用它来拦截、检查并重写HTTP(S)流量&#xff0c;支持捕获各种应用的网络请求。ProxyPin基于Flutter开发&#xff0…

文献学习:单细胞+临床+模型构建 | 一篇Molecular Cancer文献如何完整解读CDK4/6i耐药机制

&#x1f44b; 欢迎关注我的生信学习专栏~ 如果觉得文章有帮助&#xff0c;别忘了点赞、关注、评论&#xff01; &#x1f4cc;一、研究背景&#xff1a;CDK4/6i 是不是“万无一失”&#xff1f; HR/HER2- 是最常见的乳腺癌亚型&#xff0c;占比超过70%。近年来&#xff0c;随…

网盘解析工具更新,解决了一些bug

解析工具v1.2.1版本更新&#xff0c;本次是小版本更新&#xff0c;修复了一些bug。 之前小伙伴反应的网盘进入文件后不能返回上一级&#xff0c;现在这个bug修复了&#xff0c;已经可以点击了。 点击资源后会回到资源那一级目录&#xff0c;操作上是方便了不少。 增加了检查自…

5种生成模型(VAE、GAN、AR、Flow 和 Diffusion)的对比梳理 + 易懂讲解 + 代码实现

目录 1 变分自编码器&#xff08;VAE&#xff09;​ 1.1 概念 1.2 训练损失 1.3 VAE 的实现 2 生成对抗网络&#xff08;GAN&#xff09;​ 2.1 概念 2.2 训练损失 a. 判别器的损失函数 b. 生成器的损失函数 c. 对抗训练的动态过程 2.3 GAN 的实现 3 自回归模型&am…

计算机期刊推荐 | 计算机-人工智能、信息系统、理论和算法、软件工程、网络系统、图形学和多媒体, 工程技术-制造, 数学-数学跨学科应用

Computers, Materials & Continua 学科领域&#xff1a; 计算机-人工智能、信息系统、理论和算法、软件工程、网络系统、图形学和多媒体, 工程技术-制造, 数学-数学跨学科应用 期刊类型&#xff1a; SCI/SSCI/AHCI 收录数据库&#xff1a; SCI(SCIE),EI,Scopus,知网(CNK…

【教学类-58-14】黑白三角拼图12——单页1页图。参考图1页6张(黑白、彩色)、板式(无圆点、黑圆点、白圆点)、宫格2-10、张数6张,适合集体操作)

背景需求&#xff1a; 基于以下两个代码&#xff0c;设计一个单页1页黑白三角、彩色三角&#xff08;包含黑点、白点、无点&#xff09;的代码。 【教学类-58-12】黑白三角拼图10&#xff08;N张参考图1张操作卡多张彩色白块&#xff0c;适合个别化&#xff09;-CSDN博客文章…

C++项目:高并发内存池_下

目录 8. thread cache回收内存 9. central cache回收内存 10. page cache回收内存 11. 大于256KB的内存申请和释放 11.1 申请 11.2 释放 12. 使用定长内存池脱离使用new 13. 释放对象时优化成不传对象大小 14. 多线程环境下对比malloc测试 15. 调试和复杂问题的调试技…

消息队列性能比拼: Kafka vs RabbitMQ

本内容是对知名性能评测博主 Anton Putra Kafka vs RabbitMQ Performance 内容的翻译与整理, 有适当删减, 相关数据和结论以原作结论为准。 简介 在本视频中&#xff0c;我们将首先比较 Apache Kafka 和传统的 RabbitMQ。然后&#xff0c;在第二轮测试中&#xff0c;会将 Kaf…

AP 场景架构设计(一) :OceanBase 读写分离策略解析

说明&#xff1a;本文内容对应的是 OceanBase 社区版&#xff0c;架构部分不涉及企业版的仲裁副本功能。OceanBase社区版和企业版的能力区别详见&#xff1a; 官网链接。 概述​ 当两种类型的业务共同运行在同一个数据库集群上时&#xff0c;这对数据库的配置等条件提出了较高…

Java 大视界 -- Java 大数据在智能金融区块链跨境支付与结算中的应用(154)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

手把手教你在linux服务器部署deepseek,打造专属自己的数据库知识库

第一步&#xff1a;安装Ollama 打开官方网址&#xff1a;https://ollama.com/download/linux 下载Ollama linux版本 复制命令到linux操作系统执行 [rootpostgresql ~]# curl -fsSL https://ollama.com/install.sh | sh在Service中增加下面两行 [rootlocalhost ~]# vi /etc/…

C++ 继承:面向对象编程的核心概念(一)

文章目录 引言1. 继承的基本知识1.1 继承的关键词的区别1.2 继承类模版 2. 基类和派生类间的转换3. 继承中的作用域4. 派生类的默认成员函数4.1 默认成员函数的规则4.2 自己实现成员函数4.3 实现一个不能被继承的基类&#xff08;基本不用&#xff09; 引言 在C中&#xff0c;…

蓝桥杯 临时抱佛脚 之 二分答案法与相关题目

二分答案法&#xff08;利用二分法查找区间的左右端点&#xff09; &#xff08;1&#xff09;估计 最终答案可能得范围 是什么 &#xff08;2&#xff09;分析 问题的答案 和 给定条件 之间的单调性&#xff0c;大部分时候只需要用到 自然智慧 &#xff08;3&#xff09;建…

【算法day22】两数相除——给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。

29. 两数相除 给你两个整数&#xff0c;被除数 dividend 和除数 divisor。将两数相除&#xff0c;要求 不使用 乘法、除法和取余运算。 整数除法应该向零截断&#xff0c;也就是截去&#xff08;truncate&#xff09;其小数部分。例如&#xff0c;8.345 将被截断为 8 &#x…

关于服务器只能访问localhost:8111地址,局域网不能访问的问题

一、问题来源&#xff1a; 服务器是使用的阿里云的服务器&#xff0c;服务器端的8111端口没有设置任何别的限制&#xff0c;但是在阿里云服务器端并没有设置相应的tcp连接8111端口。 二、解决办法&#xff1a; 1、使用阿里云初始化好的端口&#xff1b;2、配置新的阿里云端口…

基于ADMM无穷范数检测算法的MIMO通信系统信号检测MATLAB仿真,对比ML,MMSE,ZF以及LAMA

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 ADMM算法 4.2 最大似然ML检测算法 4.3 最小均方误差&#xff08;MMSE&#xff09;检测算法 4.4 迫零&#xff08;ZF&#xff09;检测算法 4.5 OCD_MMSE 检测算法 4.6 LAMA检测算法 …