【STM32】FreeRTOS消息隊列和信號量學習

一、消息隊列(queue)

隊列是一種用于實現任務與任務之間,任務與中斷之間消息交流的機制。

注意:1.數據的操作是FIFO模式。

2.隊列需要明確數據的大小和隊列的長度。

3.寫和讀都會出現堵塞。

實驗:創建一個消息隊列,兩個發送任務,一個接收任務。

其中任務一任務三的等待時間為0,任務二的等待時間為portMAX_DELAY(死等)。

實現:在前一個項目的基礎上進行更改【STM32】利用CubeMX對FreeRTOS用按鍵控制任務

void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* Create the semaphores(s) *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* Create the queue(s) *//* definition and creation of myQueue01 */osMessageQDef(myQueue01, 2, uint32_t);myQueue01Handle = osMessageCreate(osMessageQ(myQueue01), NULL);/* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of Task1 */osThreadDef(Task1, StartDefaultTask, osPriorityNormal, 0, 128);Task1Handle = osThreadCreate(osThread(Task1), NULL);/* definition and creation of Task2 */osThreadDef(Task2, StartTask02, osPriorityIdle, 0, 128);Task2Handle = osThreadCreate(osThread(Task2), NULL);/* definition and creation of Task3 */osThreadDef(Task3, StartTask03, osPriorityIdle, 0, 128);Task3Handle = osThreadCreate(osThread(Task3), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the Task1 thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */BaseType_t xStatus;uint32_t Buf=10086;for(;;){if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){xStatus=xQueueSendToBack(myQueue01Handle,&Buf,0);if(xStatus!=pdTRUE){printf("NO1\r\n");osDelay(500);}else{printf("YES1%u\r\n",Buf);osDelay(500);}}}}/* USER CODE END StartDefaultTask */
}/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{/* USER CODE BEGIN StartTask02 *//* Infinite loop */BaseType_t xStatus;uint32_t Buf=66666;for(;;){		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0){xStatus=xQueueSendToBack(myQueue01Handle,&Buf,portMAX_DELAY);if(xStatus!=pdTRUE){printf("NO2\r\n");osDelay(500);}else{printf("YES2%u\r\n",Buf);osDelay(500);}}}}/* USER CODE END StartTask02 */
}/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the Task3 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{/* USER CODE BEGIN StartTask03 *//* Infinite loop *///BaseType_t xStatus;uint32_t Buf=0;for(;;){if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0){printf("當前%u\r\n",Buf);//xStatus=xQueueReceive(myQueue01Handle,&Buf,portMAX_DELAY);if(xQueueReceive(myQueue01Handle,&Buf,portMAX_DELAY)!=pdTRUE){printf("NO3\r\n");}else{printf("YES3%u\r\n",Buf);}}}}/* USER CODE END StartTask03 */
}

現象:隊列滿了以后,任務一無法發送,任務二會死等,隊列空閑以后完成發送。

二、信號量

消息隊列用于傳輸多個數據,占用時間也相對較長,但有時只需要傳輸狀態,因此引入信號量。信號量也是隊列的一種。信號量有兩種,如果它的量只有0(被拿走的狀態)和1(被填入的狀態)兩種狀態,就稱為二進制的信號量;當量的狀態大于兩種,就稱為計數型信號量。

1.二值信號量

實驗:任務一:按鍵采集數據;任務二:拿走以后串口發送信息

實現:

void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* Create the semaphores(s) *//* definition and creation of myBinarySem01 */osSemaphoreDef(myBinarySem01);myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);/* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* Create the queue(s) *//* definition and creation of myQueue01 */osMessageQDef(myQueue01, 2, uint32_t);myQueue01Handle = osMessageCreate(osMessageQ(myQueue01), NULL);/* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of Task1 */osThreadDef(Task1, StartDefaultTask, osPriorityNormal, 0, 128);Task1Handle = osThreadCreate(osThread(Task1), NULL);/* definition and creation of Task2 */osThreadDef(Task2, StartTask02, osPriorityNormal, 0, 128);Task2Handle = osThreadCreate(osThread(Task2), NULL);/* definition and creation of Task3 */osThreadDef(Task3, StartTask03, osPriorityNormal, 0, 128);Task3Handle = osThreadCreate(osThread(Task3), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the Task1 thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */BaseType_t xStatus;uint32_t Buf=10086;for(;;){
//  {if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){
//				xStatus=xQueueSendToBack(myQueue01Handle,&Buf,0);if(xSemaphoreGive(myBinarySem01Handle)==pdTRUE){printf("NO1\r\n");}else{printf("YES1%u\r\n",Buf);}}}}/* USER CODE END StartDefaultTask */
}/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the Task3 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{/* USER CODE BEGIN StartTask03 *//* Infinite loop */	uint32_t Buf=0;for(;;){if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0){				if(xSemaphoreTake(myBinarySem01Handle,0)==pdTRUE){printf("YES3\r\n");}else{printf("NO3%u\r\n",Buf);}}}}/* USER CODE END StartTask03 */
}

?現象:當按鍵釋放了信號量,串口才能成功發送信息。

2.記數型信號量

實驗:任務一 :按鍵一記錄人進來;按鍵二記錄人出去;(最多有10個人)

任務二:串口每隔3S打印人數。

實現:

void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* Create the semaphores(s) *//* definition and creation of myBinarySem01 */osSemaphoreDef(myBinarySem01);myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);/* definition and creation of myCountingSem01 */osSemaphoreDef(myCountingSem01);myCountingSem01Handle = osSemaphoreCreate(osSemaphore(myCountingSem01), 10);/* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* Create the queue(s) *//* definition and creation of myQueue01 */osMessageQDef(myQueue01, 2, uint32_t);myQueue01Handle = osMessageCreate(osMessageQ(myQueue01), NULL);/* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of Task1 */osThreadDef(Task1, StartDefaultTask, osPriorityNormal, 0, 128);Task1Handle = osThreadCreate(osThread(Task1), NULL);/* definition and creation of Task2 */osThreadDef(Task2, StartTask02, osPriorityNormal, 0, 128);Task2Handle = osThreadCreate(osThread(Task2), NULL);/* definition and creation of Task3 */osThreadDef(Task3, StartTask03, osPriorityNormal, 0, 128);Task3Handle = osThreadCreate(osThread(Task3), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the Task1 thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){if(xSemaphoreGive(myCountingSem01Handle)!=pdTRUE){printf("NO1\r\n");}else{printf("YES1\r\n");}}}if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0){if(xSemaphoreTake(myCountingSem01Handle,0)!=pdTRUE){printf("NO2\r\n");}else{printf("YES2\r\n");}}}}/* USER CODE END StartDefaultTask */
}/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{/* USER CODE BEGIN StartTask02 *//* Infinite loop */for(;;){}/* USER CODE END StartTask02 */
}/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the Task3 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{/* USER CODE BEGIN StartTask03 *//* Infinite loop */for(;;){printf("possess %d people\r\n",(uint16_t)uxSemaphoreGetCount(myCountingSem01Handle));osDelay(3000);}/* USER CODE END StartTask03 */
}

?因為用了函數

myCountingSem01Handle = osSemaphoreCreate(osSemaphore(myCountingSem01), 10);

默認當前計數值為滿值。如果設置為0,使用下面的函數:

myCountingSem01Handle=xSemaphoreCreateCounting(10,0);

現象:通過按鍵一和二實現記錄人數,并串口打印了當前人數。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/35938.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/35938.shtml
英文地址,請注明出處:http://en.pswp.cn/news/35938.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解決 Oracle 數據庫中表被鎖問題的方案和方法

我們經常會遇到表被鎖的情況,這可能會嚴重影響數據庫的性能和可用性。我將與大家分享如何識別、分析和解決這些問題,以及如何使用特定的 SQL 查詢來執行解鎖操作。 了解表鎖的原因 首先,讓我們來了解一下導致表被鎖的常見原因。長時間運行的…

(四)Unity開發Vision Pro——參考文檔

4.參考文檔 4.1 支持的功能和組件 4.1.1 支持的 Unity 功能和組件 大多數 Unity 組件無需修改即可在此平臺上運行 - 包括大多數自定義 MonoBehaviours、動畫邏輯、物理、輸入處理、資產管理、AI 等。然而,需要渲染的組件需要特殊的支持。因此,一些組件…

qt5.15.2 使用mysql8.1

報錯&#xff1a; QMYSQL driver not loaded 報錯&#xff1a;無 QMYSQL 使用 QStringList drivers QSqlDatabase::drivers(); //獲取現在可用的數據庫驅動 foreach(QString driver, drivers) qDebug() << driver; “QSQLITE” “QMARIADB” “QMYSQL” “QMYSQL3” “…

Linux常用命令——dmidecode命令

在線Linux命令查詢工具 dmidecode 在Linux系統下獲取有關硬件方面的信息 補充說明 dmidecode命令可以讓你在Linux系統下獲取有關硬件方面的信息。dmidecode的作用是將DMI數據庫中的信息解碼&#xff0c;以可讀的文本方式顯示。由于DMI信息可以人為修改&#xff0c;因此里面…

網絡編程的使用

文章目錄 基礎代碼URL類進行傳輸編碼解碼 協議TCPUDPhttp PORT端口協議的實現TCPUDP 模擬服務器 基礎代碼 最后一個是&#xff1a;只要再timeout時間內連接上就是true URL類 導了一個common-iojar包&#xff0c;那個IOUtils就是那個里面的工具類 進行傳輸編碼解碼 協議 TC…

多線程:線程池

線程池 提前創建多個線程放入線程池中&#xff0c;使用時直接獲取&#xff0c;使用完直接放入池中&#xff1b;可以避免頻繁創建銷毀&#xff0c;實現重復利用&#xff0c;類似生活中的公共交通工具。好處&#xff1a;提高相應速度&#xff1b;降低資源消耗&#xff1b;便于線…

【Spring Cloud +Vue+UniApp】智慧建筑工地平臺源碼

智慧工地源碼 、智慧工地云平臺源碼、 智慧建筑源碼支持私有化部署&#xff0c;提供SaaS硬件設備運維全套服務。 前言&#xff1a;互聯網建筑工地&#xff0c;是將互聯網的理念和技術引入建筑工地&#xff0c;從施工現場源頭抓起&#xff0c;最大程度的收集人員、安全、環境、材…

微信小程序調用map數據 并在wxml中對數組進行截取的操作

wxs文件的位置如圖 實現數組截取 只保留五張圖片 <wxs module"filter" src"./slicefunc.wxs"></wxs> <view class"wrap"><view class"search-box" bindtap"toSearch"><view class"v1"…

【幾個python虛擬環境會遇到的問題】

幾個python虛擬環境會遇到的問題 twine is not recognized as an internal or external command,operable program or batch file.setup命令不報錯但不起作用pipreqs is not recognized as an internal or external command,operable program or batch file. ‘twine’ is not …

快遞管理系統springboot 寄件物流倉庫java jsp源代碼mysql

本項目為前幾天收費幫學妹做的一個項目&#xff0c;Java EE JSP項目&#xff0c;在工作環境中基本使用不到&#xff0c;但是很多學校把這個當作編程入門的項目來做&#xff0c;故分享出本項目供初學者參考。 一、項目描述 快遞管理系統springboot 系統有1權限&#xff1a;管…

11. Docker Swarm(二)

1、前言 上一篇中我們利用Docker Swarm搭建了基礎的集群環境。那么今天我們就來驗證以下該集群的可用性。上一篇的示例中&#xff0c;我創建了3個實例副本&#xff0c;并且通過訪問http://192.168.74.132:8080得到我們的頁面。 2、驗證高可用 1&#xff09;我們可以通過以下命…

13個頂級AI代碼助手排行榜【2023最新】

AI代碼助手&#xff08;AI Coding Assistant&#xff09;是一種利用人工智能幫助開發人員更快、更準確地編寫代碼的軟件工具。 它可以通過根據提示生成代碼或在你實時編寫代碼時建議自動完成代碼來實現此目的。 以下是AI代碼助手可以做的一些事情&#xff1a; 與你使用的流行代…

YOLOv5可視化界面

Pyside6可視化界面 安裝Pyside6 激活之前的虛擬環境yolov5 在該環境的終端輸入以下命令 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyside6輸入where python找到當前使用的Python的路徑 找到該路徑下的designer.exe文件&#xff08;/Lib/site-packages/PySi…

布置Zabbix監控

一、在 Web 頁面中添加 agent 主機 1.1打開Zabbix的Web頁面 2.2在 Web 頁面中添加 agent 主機 二、在 Web 頁面創建自定義監控項模板 2.1創建模版

《Java面向對象程序設計》學習筆記——第 8 章 設計模式

?專欄&#xff1a;《Java面向對象程序設計》學習筆記 第 8 章 設計模式 一個好的設計系統往往是易維護、易擴展、易復用的。 8.1 設計模式簡介 8.1.1 什么是設計模式 一個設計模式 (pattern) 是針對某一類問題的最佳解決方案&#xff0c;而且己經被成功應用于許多系統的設…

[QT/C++]如何得知鼠標事件是由觸摸事件轉換而來的,使得鼠標觸摸事件分離

依據來源&#xff1a;https://doc.qt.io/qt-5/qml-qtquick-mouseevent.html 具體是在event事件或者mouse系列事件中捕獲到鼠標事件后&#xff0c;用如下代碼判斷鼠標事件是否由觸摸事件轉換而來的 if(mouseEvent->source()Qt::MouseEventSynthesizedBySystem){qDebug()<&…

Chrome

Chrome 簡介下載 簡介 Chrome 是由 Google 開發的一款流行的網絡瀏覽器。它以其快速的性能、強大的功能和用戶友好的界面而聞名&#xff0c;并且在全球范圍內被廣泛使用。Chrome 支持多種操作系統&#xff0c;包括 Windows、macOS、Linux 和移動平臺。 Chrome官網: https://ww…

css3新增選擇器總結

目錄 一、屬性選擇器 二、結構偽類選擇器 三、偽元素選擇器 四、UI狀態偽類選擇器 五、反選偽類選擇器 六、target選擇器 七、父親選擇器、后代選擇器 八、相鄰兄弟選擇器、兄弟們選擇器 一、屬性選擇器 &#xff08;除IE6外的大部分瀏覽器支持&#xff09; E&#…

嵌入式面試筆試刷題(day10)

文章目錄 前言一、數組和鏈表的區別二、什么是內存對齊三、IIC的時序四、static作用五、查看tty設備的方法六、查找指定文件命令七、三次握手和四次揮手1.三次握手2.四次揮手 八、半關閉狀態九、字節流和數據報總結 前言 本篇文章繼續講解筆試和面試。 一、數組和鏈表的區別 …

PHP 使用ThinkPHP實現電子郵件發送示例

文章目錄 首先我們需要設置我們的郵箱客戶端授權&#xff0c;獲取到授權碼找到我們的郵箱設置去賬號中找到這一堆服務&#xff0c;找到后開啟smtp服務開啟服務后管理服務 接下來需要去下載相應的第三方類庫(我這里使用的是PHPMailer)在thinkPHP中封裝一下郵件服務類實際調用效果…