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.pswp.cn/diannao/77253.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/77253.shtml
英文地址,請注明出處:http://en.pswp.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 作為緩存數據庫的過程中,可能會遇到一些常見問題,例如緩存穿透、緩存擊穿和緩存雪崩等。 緩存雪崩 緩存雪崩是指緩存…