STM32在裸机(无RTOS)环境下,需要手动实现队列机制来替代FreeRTOS的CAN发送接收函数

xQueueSendToBackFromISR(ecuCanRxQueue, hcan->pRxMsg, &xHigherPriorityTaskWoken),xQueueReceive(mscCanRxQueue,&mscRxMsg,0)和xQueueSendToBack(mscCanTxQueue, &TxMessageTemp, 0 )这3个函数,在裸机下实现:
在裸机(无RTOS)环境下,需要手动实现队列机制来替代FreeRTOS的这三个函数。以下是完整的裸机实现方案:

1. 队列结构定义

#define CAN_RX_QUEUE_SIZE  20  // 接收队列大小
#define CAN_TX_QUEUE_SIZE  30  // 发送队列大小/* CAN接收消息结构 */
typedef struct {uint32_t id;        // CAN IDuint8_t data[8];    // 数据uint8_t length;     // 数据长度
} CanRxMsg_t;/* CAN发送消息结构 */ 
typedef struct {uint32_t id;        // CAN IDuint8_t data[8];    // 数据uint8_t length;     // 数据长度
} CanTxMsg_t;/* 环形队列结构 */
typedef struct {void *buffer;       // 数据缓冲区uint16_t size;      // 队列容量volatile uint16_t head;  // 队头volatile uint16_t tail;  // 队尾volatile uint16_t count; // 当前元素数
} Queue_t;/* 全局队列实例 */
Queue_t ecuCanRxQueue;  // ECU CAN接收队列
Queue_t mscCanRxQueue;  // MSC CAN接收队列  
Queue_t mscCanTxQueue;  // MSC CAN发送队列/* 队列存储区 */
CanRxMsg_t ecuRxBuffer[CAN_RX_QUEUE_SIZE];
CanRxMsg_t mscRxBuffer[CAN_RX_QUEUE_SIZE];
CanTxMsg_t mscTxBuffer[CAN_TX_QUEUE_SIZE];

2. 队列初始化

void Queues_Init(void)
{/* ECU接收队列 */ecuCanRxQueue.buffer = ecuRxBuffer;ecuCanRxQueue.size = CAN_RX_QUEUE_SIZE;ecuCanRxQueue.head = 0;ecuCanRxQueue.tail = 0;ecuCanRxQueue.count = 0;/* MSC接收队列 */mscCanRxQueue.buffer = mscRxBuffer;mscCanRxQueue.size = CAN_RX_QUEUE_SIZE;mscCanRxQueue.head = 0;mscCanRxQueue.tail = 0; mscCanRxQueue.count = 0;/* MSC发送队列 */mscCanTxQueue.buffer = mscTxBuffer;mscCanTxQueue.size = CAN_TX_QUEUE_SIZE;mscCanTxQueue.head = 0;mscCanTxQueue.tail = 0;mscCanTxQueue.count = 0;
}

3. 替代函数实现
(1) 替代xQueueSendToBackFromISR

/* 中断安全入队函数 */
uint8_t Queue_SendFromISR(Queue_t *q, void *item, uint16_t itemSize)
{if (q->count >= q->size) {return 0; // 队列满}__disable_irq(); // 关中断保证原子操作// 拷贝数据到队尾memcpy((uint8_t*)q->buffer + q->head * itemSize, item, itemSize);q->head = (q->head + 1) % q->size;q->count++;__enable_irq(); // 开中断return 1; // 成功
}/* 使用示例(在CAN中断中)*/
void CAN_RX0_IRQHandler(void)
{CanRxMsg_t rxMsg;// 从CAN硬件读取数据...// 替代xQueueSendToBackFromISRQueue_SendFromISR(&ecuCanRxQueue, &rxMsg, sizeof(CanRxMsg_t));
}

(2) 替代xQueueReceive

/* 非阻塞出队函数 */
uint8_t Queue_Receive(Queue_t *q, void *item, uint16_t itemSize)
{if (q->count == 0) {return 0; // 队列空}// 从队头取出数据memcpy(item, (uint8_t*)q->buffer + q->tail * itemSize, itemSize);q->tail = (q->tail + 1) % q->size;q->count--;return 1; // 成功
}/* 使用示例 */
CanRxMsg_t mscRxMsg;
if (Queue_Receive(&mscCanRxQueue, &mscRxMsg, sizeof(CanRxMsg_t))) {// 处理接收到的消息
}

(3) 替代xQueueSendToBack

/* 非阻塞入队函数 */ 
uint8_t Queue_Send(Queue_t *q, void *item, uint16_t itemSize)
{if (q->count >= q->size) {return 0; // 队列满}// 拷贝数据到队尾memcpy((uint8_t*)q->buffer + q->head * itemSize, item, itemSize);q->head = (q->head + 1) % q->size;q->count++;return 1; // 成功
}/* 使用示例 */
CanTxMsg_t TxMessageTemp;
// 填充TxMessageTemp...
Queue_Send(&mscCanTxQueue, &TxMessageTemp, sizeof(CanTxMsg_t));

4. 主循环处理

int main(void)
{// 初始化硬件和队列Queues_Init();CAN_Init();while (1) {// 处理发送队列CanTxMsg_t txMsg;if (Queue_Receive(&mscCanTxQueue, &txMsg, sizeof(CanTxMsg_t))) {// 通过CAN硬件发送消息CAN_SendMessage(txMsg.id, txMsg.data, txMsg.length);}// 其他任务...}
}

关键点说明
中断安全:在中断中操作队列时使用__disable_irq()/__enable_irq()

内存管理:使用memcpy确保数据正确拷贝

非阻塞设计:所有函数立即返回,不等待

通用队列:通过itemSize参数支持不同消息类型

这个实现完整替代了FreeRTOS队列功能,同时保持了裸机环境下的高效性和可靠性。

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

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

相关文章

使用PX4,gazebo,mavros为旋翼添加下视的相机(仿真采集openrealm数据集-第一步)

目录 一.方法一(没成功) 1.运行PX4 2.运行mavros通讯 3.启动仿真世界和无人机 (1)单独测试相机 (2)make px4_sitl gazebo启动四旋翼iris无人机 二.方法二(成功) 1.通过 rosl…

7、nRF52xx蓝牙学习(nrf_gpiote.c库函数学习)

续前一篇文章。 3、nrfx_gpiote_in_event_enable void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable) {NRFX_ASSERT(nrf_gpio_pin_present_check(pin));NRFX_ASSERT(pin_in_use_by_gpiote(pin));if (pin_in_use_by_port(pin)){nrf_gpiote_polarity_t…

Java 实现插入排序:[通俗易懂的排序算法系列之三]

引言 大家好!欢迎继续关注我的排序算法系列。今天,我们要学习的是另一种非常基础且重要的排序算法——插入排序 (Insertion Sort)。 插入排序的思路非常贴近我们日常整理扑克牌的方式,理解起来相对自然。虽然它在最坏情况下的效率不高,但在某些特定场景下,它的表现甚至优…

Java的spring boot项目编译成功启动报错

问题现象:spring boot项目,候删除一些无用代码后,build成功,启动时报错:找不到java.util.Map或者其他对象(用Lombok注解Data)中的字段属性找不到等错误。解答: 常见是Lombok版本问题…

PyTorch参数管理详解:从访问到初始化与共享

本文通过实例代码讲解如何在PyTorch中管理神经网络参数,包括参数访问、多种初始化方法、自定义初始化以及参数绑定技术。所有代码可直接运行,适合深度学习初学者进阶学习。 1. 定义网络与参数访问 1.1 定义单隐藏层多层感知机 import torch from torch…

基于springboot+vue的课程管理系统

一、系统架构 前端:vue | element-ui 后端:springboot | mybatis-plus 环境:jdk1.8 | mysql8 | maven | node v16.20.2 | idea 二、代码及数据 三、功能介绍 01. 登录 02. 管理员-首页 03. 管理员-系管理 04. 管理员-专业管理 05. 管…

ssh密钥连接远程服务器并用scp传输文件

ssh密钥连接远程服务器 私钥的权限必须是600chmod 600 id_rsa连接时在命令中加上私钥的地址ssh -i PATH_to_id_rsa usernameip -p port scp -P port -i PATH_to_id_rsa file usernameip:PATH

ElasticSearch迁移数据

一、查询索引 1、查询所有索引 curl --user elastic:123456 -XGET "http://localhost:19200/_cat/indices?v&sindex" 2、查询索引配置 以索引名称hello为例 curl --user elastic:123456 -XGET "http://localhost:19200/hello/_settings?pretty" 3…

【Unity】animator检测某state动画播放完毕方法

博主对动画系统很不熟,可能使用的方法比较曲折,但是我确实没找到更有效的方法了。 unity的这个animator在我看来简直有毛病啊,为什么那么难以获取某状态动画的信息呢??? 想要知道动画播完没有只有用norma…

Jmeter 插件【性能测试监控搭建】

1. 安装Plugins Manager 1.1 下载路径: Install :: JMeter-Plugins.org 1.2 放在lib/ext目录下 1.3 重启Jmeter,会在菜单-选项下多一个 Plugins Manager菜单,打开即可对插件进行安装、升级。 2. 客户端(Jmeter端) 2.1 安装plugins manager…

ollama+open-webui本地部署自己的模型到d盘+两种open-webui部署方式(详细步骤+大量贴图)

一、ollama准备 1.官网下载ollama:https://ollama.com/download 2.在 d 盘创建 ollama 文件夹,把软件包放进去 3.管理员身份运行黑窗口 win r 弹出运行窗口 输入 cmd 后, ctrl shift 回车,以管理员身份打开 3.切换到 d 盘&a…

(学习总结33)Linux Ext2 文件系统与软硬链接

Linux Ext2 文件系统与软硬链接 理解硬件磁盘、服务器、机柜、机房磁盘物理结构磁盘的逻辑结构实际过程 CHS 与 LBA 地址转换 引入文件系统引入 " 块 " 概念引入 " 分区 " 概念引入 " inode " 概念 ext2 文件系统宏观认识Block Group 块组与其内…

Go语言sync.Mutex包源码解读

互斥锁sync.Mutex是在并发程序中对共享资源进行访问控制的主要手段,对此Go语言提供了非常简单易用的机制。sync.Mutex为结构体类型,对外暴露Lock()、Unlock()、TryLock()三种方法,分别用于阻塞加锁、解锁、非阻塞加锁操作(加锁失败…

SQL注入流量分析

免责声明:本文仅作分享 ~ 目录 SQL注入流量分析 特征: sqlmap注入类型 漏洞环境搭建 error_sql: bool_sql: time_sql: union_sql: Stacked Queries: Inline Queries: SQL注入流量分析 https://www.freebuf.com/column/161797.html SQLMAP攻击…

Linux 时间同步工具 Chrony 简介与使用

一、Chrony 是什么? chrony 是一个开源的网络时间同步工具,主要由两个组件组成: chronyd:后台服务进程,负责与时间服务器交互,同步系统时钟。chronyc:命令行工具,用于手动查看或修…

Flutter:Flutter SDK版本控制,fvm安装使用

1、首先已经安装了Dart,cmd中执行 dart pub global activate fvm2、windows配置系统环境变量 fvm --version3、查看本地已安装的 Flutter 版本 fvm releases4、验证当前使用的 Flutter 版本: fvm flutter --version5、切换到特定版本的 Flutter fvm use …

Vue 项目中的package.json各部分的作用和用法的详细说明

1. 基本信息 {"name": "my-vue-app","version": "1.0.0","description": "A Vue.js project","author": "Your Name <your.emailexample.com>","license": "MIT"…

Linux网络编程——TCP通信的四次挥手

一、前言 上篇文章讲到了TCP通信建立连接的“三次握手”的一些细节&#xff0c;本文再对TCP通信断开连接的“四次挥手”的过程做一些分析了解。 二、TCP断开连接的“四次挥手” 我们知道TCP在建立连接的时需要“三次握手”&#xff0c;三次握手完后就可以进行通信了。而在通…

某碰瓷国赛美赛,号称第三赛事的数模竞赛

首先我非常不能理解的就是怎么好意思自称第三赛事的呢&#xff1f;下面我们进行一个简单讨论&#xff0c;当然这里不对国赛和美赛进行讨论。首先我们来明确一点&#xff0c;比赛的含金量由什么来定&#xff1f;这个可能大家的评价指标可能不唯一&#xff0c;我通过DeepSeek选取…

Redis 缓存问题:缓存雪崩、缓存击穿、缓存穿透

文章目录 缓存雪崩缓存击穿缓存穿透在实际的业务场景中,Redis 通常作为缓存和其他数据库(例如 MySQL)搭配使用,用来减轻数据库的压力。但是在使用 Redis 作为缓存数据库的过程中,可能会遇到一些常见问题,例如缓存穿透、缓存击穿和缓存雪崩等。 缓存雪崩 缓存雪崩是指缓存…