STM32 CubeMX
學(xué)習(xí)使用Freertos第二步
在 FreeRTOS 中,任務(wù)通信可以通過以下函數(shù)來實(shí)現(xiàn):
-
xQueueCreate()
:用于創(chuàng)建一個(gè)消息隊(duì)列??梢栽O(shè)置隊(duì)列長(zhǎng)度和每個(gè)消息的大小。
xQueueSend()
:將一條消息發(fā)送到隊(duì)列中。可以選擇阻塞或非阻塞發(fā)送。
xQueueReceive()
:從隊(duì)列中接收一條消息??梢赃x擇阻塞或非阻塞接收。
xQueuePeek():
查看隊(duì)列中的下一條消息,但不將其移除。
xQueueReset()
:清空隊(duì)列中的所有消息。
2. xQueueSemaphoreTake()
和xQueueSemaphoreGive()
:用于實(shí)現(xiàn)二值信號(hào)量,控制任務(wù)之間的互斥訪問。
3. xSemaphoreCreateMutex()
:創(chuàng)建一個(gè)互斥信號(hào)量,用于實(shí)現(xiàn)任務(wù)之間的互斥訪問。
4. xTaskNotify()
和ulTaskNotifyTake()
:用于任務(wù)間的通知機(jī)制,一個(gè)任務(wù)可以通知另一個(gè)任務(wù)進(jìn)行某種操作。
5. xEventGroupCreate()、xEventGroupSetBits()和xEventGroupWaitBits()
:用于創(chuàng)建、設(shè)置和等待事件標(biāo)志組。
一、STM32 CubeMX設(shè)置
時(shí)鐘配置
HAL時(shí)基選擇TIM1(不要選擇滴答定時(shí)器;滴答定時(shí)器留給OS系統(tǒng)做時(shí)基)
使用STM32 CubeMX 庫,配置Freertos
選擇CMISS_V1接口就可以滿足Freertos接口;且代碼量比CMISS_V2?。–MISS_V2支持更多的RTOS接口,所以代碼量比CMISS_V1多)
二、實(shí)驗(yàn)一:消息隊(duì)列
消息隊(duì)列是什么?適用于什么地方?
- 數(shù)據(jù)傳遞:消息隊(duì)列允許任務(wù)之間傳遞數(shù)據(jù),一個(gè)任務(wù)可以將數(shù)據(jù)打包成消息發(fā)送到隊(duì)列,另一個(gè)任務(wù)則可以從隊(duì)列中接收該消息并處理其中的數(shù)據(jù)。這使得任務(wù)之間可以方便地進(jìn)行數(shù)據(jù)交換和共享。
- 任務(wù)解耦:通過使用消息隊(duì)列,任務(wù)之間的耦合度可以降低。一個(gè)任務(wù)只需要關(guān)注發(fā)送和接收消息,而不需要知道消息的具體處理細(xì)節(jié)和目標(biāo)任務(wù)的實(shí)現(xiàn)。這樣,當(dāng)需要更改或替換某個(gè)任務(wù)時(shí),只需要保證消息的格式和接口不變即可,不會(huì)對(duì)其他任務(wù)產(chǎn)生影響。
- 同步與協(xié)作:消息隊(duì)列可以用于實(shí)現(xiàn)任務(wù)之間的同步和協(xié)作。例如,一個(gè)任務(wù)可以等待某個(gè)特定的消息到達(dá)隊(duì)列后才繼續(xù)執(zhí)行,從而實(shí)現(xiàn)任務(wù)間的同步。另外,多個(gè)任務(wù)可以通過發(fā)送和接收消息來協(xié)調(diào)彼此的執(zhí)行順序和操作。
- 緩沖和調(diào)節(jié):消息隊(duì)列可以充當(dāng)緩沖區(qū),用于存儲(chǔ)一定數(shù)量的消息。當(dāng)發(fā)送方發(fā)送消息速度較快,而接收方處理速度較慢時(shí),消息隊(duì)列可以暫時(shí)存儲(chǔ)未處理的消息,避免數(shù)據(jù)丟失。同時(shí),消息隊(duì)列還可以調(diào)節(jié)發(fā)送和接收任務(wù)之間的速度差異,以平衡任務(wù)負(fù)載。
FreeRTOS 消息隊(duì)列和數(shù)組 的幾個(gè)區(qū)別:
- 數(shù)據(jù)組織方式:消息隊(duì)列是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ)和傳遞消息。每個(gè)消息都可以包含不同類型和長(zhǎng)度的數(shù)據(jù)。而數(shù)組是一種線性的、連續(xù)的數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ)相同類型和長(zhǎng)度的元素。
- 功能和用途:消息隊(duì)列主要用于任務(wù)間通信,允許任務(wù)之間傳遞數(shù)據(jù)和進(jìn)行同步。它提供了數(shù)據(jù)傳遞、解耦、同步和協(xié)作等功能。而數(shù)組通常用于存儲(chǔ)一組具有相同類型的元素,可以進(jìn)行遍歷、訪問和修改等操作。
- 大小和容量:消息隊(duì)列的大小是可以動(dòng)態(tài)調(diào)整的,可以根據(jù)需要增加或減少隊(duì)列的容量。而數(shù)組的大小在創(chuàng)建時(shí)就確定,并且通常是固定的。
- 可用性和效率:消息隊(duì)列可以實(shí)現(xiàn)多個(gè)任務(wù)之間的并發(fā)通信,提供了較高的可用性和靈活性。而數(shù)組通常在單個(gè)任務(wù)內(nèi)進(jìn)行操作,具有較高的效率和直接性
- 總的來說,消息隊(duì)列和數(shù)組是兩種不同的數(shù)據(jù)結(jié)構(gòu),適用于不同的場(chǎng)景和需求。消息隊(duì)列主要用于任務(wù)間通信和數(shù)據(jù)傳遞,具有靈活性和可調(diào)節(jié)性;而數(shù)組主要用于存儲(chǔ)相同類型的元素,并進(jìn)行遍歷和訪問操作。選擇使用哪種數(shù)據(jù)結(jié)構(gòu)取決于具體的應(yīng)用需求和功能要求。
創(chuàng)建消息隊(duì)列
- Queue Name: 隊(duì)列名稱
- Queue Size: 隊(duì)列能夠存儲(chǔ)的最大單元數(shù)目,即隊(duì)列深度
- Queue Size: 隊(duì)列中數(shù)據(jù)單元的長(zhǎng)度,以字節(jié)為單位
- Allocation: 分配方式:Dynamic 動(dòng)態(tài)內(nèi)存創(chuàng)建
- Buffer Name: 緩沖區(qū)名稱
- Buffer Size: 緩沖區(qū)大小
- Conrol Block Name: 控制塊名稱
創(chuàng)建任務(wù)
- Task Name: 任務(wù)名稱
- Priority: 優(yōu)先級(jí),在 FreeRTOS 中,數(shù)值越大優(yōu)先級(jí)越高,0 代表最低優(yōu)先級(jí)
- Stack Size (Words): 堆棧大小,單位為字,在32位處理器(STM32),一個(gè)字等于4字節(jié),如果傳入128那么任務(wù)大小為128*4字節(jié)
- Entry Function: 入口函數(shù)
- Code Generation Option: 代碼生成選項(xiàng)
- Parameter: 任務(wù)入口函數(shù)形參,不用的時(shí)候配置為0或NULL即可
- Allocation: 分配方式:Dynamic 動(dòng)態(tài)內(nèi)存創(chuàng)建
- Buffer Name: 緩沖區(qū)名稱
- Conrol Block Name: 控制塊名稱
代碼部分
void sendTask1(void const * argument)
{
/* USER CODE BEGIN sendTask1 */
BaseType_t xsatus;
uint32_t buff=9600;
/* Infinite loop */
for(;;)
{
xsatus=xQueueSendToBack(myQueue01Handle,&buff,0);
if( xsatus!=pdPASS)
{
printf("輸入失敗\r\n"); // printf輸出字符串
}
else
{
printf("成功寫入%d\r\n", buff); // printf輸出字符串
}
osDelay(1000);
}
/* USER CODE END sendTask1 */
}
void readTask3(void const * argument)
{
/* USER CODE BEGIN readTask3 */
BaseType_t xsatus;
uint32_t buff=115200;
/* Infinite loop */
for(;;)
{
xsatus=xQueueReceive(myQueue01Handle,&buff,0);
if( xsatus!=pdPASS)
{
printf("讀取失敗\r\n"); // printf輸出字符串
}
else
{
printf("成功讀取%d\r\n", buff); // printf輸出字符串
}
osDelay(3000);
}
/* USER CODE END readTask3 */
}
實(shí)驗(yàn)現(xiàn)象
xsatus=xQueueSendToBack(myQueue01Handle,&buff,portMAX_DELAY);//一直等待
if( xsatus!=pdPASS)
{
printf("輸入失敗\r\n"); // printf輸出字符串
}
else
{
printf("成功寫入%d\r\n", buff); // printf輸出字符串
}
還一種方式:讀取不會(huì)刪除信息(偷窺信息)
三,實(shí)驗(yàn)二:信號(hào)量
信號(hào)量是什么?適用于什么地方?
FreeRTOS中的信號(hào)量是一種用于任務(wù)間同步和資源共享的機(jī)制。它可以用來實(shí)現(xiàn)任務(wù)之間的互斥訪問共享資源,或者在某個(gè)任務(wù)等待某個(gè)事件發(fā)生時(shí)進(jìn)行阻塞。
FreeRTOS提供了兩種類型的信號(hào)量:二進(jìn)制信號(hào)量(Binary Semaphore)和計(jì)數(shù)信號(hào)量(Counting Semaphore)。
二進(jìn)制信號(hào)量是一種簡(jiǎn)單的信號(hào)量,只有兩種狀態(tài):空閑和占用。當(dāng)一個(gè)任務(wù)獲取到二進(jìn)制信號(hào)量時(shí),它就可以繼續(xù)執(zhí)行,而其他任務(wù)則會(huì)被阻塞。當(dāng)任務(wù)釋放二進(jìn)制信號(hào)量時(shí),其他任務(wù)可以獲取到它并繼續(xù)執(zhí)行。
計(jì)數(shù)信號(hào)量是一種更復(fù)雜的信號(hào)量,它可以有多個(gè)資源可供獲取。計(jì)數(shù)信號(hào)量可以用來實(shí)現(xiàn)資源池的管理,例如限制同時(shí)訪問某個(gè)資源的任務(wù)數(shù)量。
在FreeRTOS中,可以使用以下函數(shù)來創(chuàng)建和操作信號(hào)量:
- xSemaphoreCreateBinary(): 創(chuàng)建二進(jìn)制信號(hào)量。
- xSemaphoreCreateCounting(): 創(chuàng)建計(jì)數(shù)信號(hào)量。
- xSemaphoreTake(): 獲取一個(gè)信號(hào)量。
- xSemaphoreGive(): 釋放一個(gè)信號(hào)量。
需要注意的是,使用信號(hào)量時(shí)要確保正確的獲取和釋放順序,以避免出現(xiàn)死鎖或資源競(jìng)爭(zhēng)的問題。
二值信號(hào)量
創(chuàng)建信號(hào)量
代碼部分
void sendTask1(void const * argument)
{
/* USER CODE BEGIN sendTask1 */
BaseType_t xsatus;
uint32_t buff=9600;
/* Infinite loop */
for(;;)
{
if( xSemaphoreTake(myBinarySem01Handle,portMAX_DELAY)!=pdPASS)
{
printf("刷新失敗#信號(hào)量獲取失敗\r\n"); // printf輸出字符串
}
else
{
printf("成功刷新#信號(hào)量獲取成功\r\n"); // printf輸出字符串
}
osDelay(2000);
}
/* USER CODE END sendTask1 */
}
void readTask3(void const * argument)
{
/* USER CODE BEGIN readTask3 */
BaseType_t xsatus;
uint32_t buff=115200;
/* Infinite loop */
for(;;)
{
if( xSemaphoreGive(myBinarySem01Handle)!=pdPASS)
{
printf("讀取失敗#信號(hào)量不能釋放\r\n"); // printf輸出字符串
}
else
{
printf("成功讀取#信號(hào)量已經(jīng)釋放\r\n"); // printf輸出字符串
}
osDelay(1000);
}
/* USER CODE END readTask3 */
}
實(shí)驗(yàn)現(xiàn)象
計(jì)數(shù)信號(hào)量
創(chuàng)建計(jì)數(shù)信號(hào)量
代碼部分
void sendTask1(void const * argument)
{
/* USER CODE BEGIN sendTask1 */
BaseType_t xsatus;
uint32_t buff=9600;
/* Infinite loop */
for(;;)
{
if( xSemaphoreGive(myCountingSem01Handle)!=pdTRUE)
{
printf("停車已滿\r\n"); // printf輸出字符串
}
else
{
printf("停車成功\r\n"); // printf輸出字符串
}
osDelay(2000);
}
/* USER CODE END sendTask1 */
}
void readTask3(void const * argument)
{
/* USER CODE BEGIN readTask3 */
BaseType_t xsatus;
uint32_t buff=115200;
/* Infinite loop */
for(;;)
{
if( xSemaphoreTake(myCountingSem01Handle,0)!=pdTRUE)
{
printf("無車\r\n"); // printf輸出字符串
}
else
{
printf("取走車\r\n"); // printf輸出字符串
}
osDelay(1000);
}
/* USER CODE END readTask3 */
}
實(shí)驗(yàn)現(xiàn)象
四,實(shí)驗(yàn)三:互斥量
互斥量是什么?適用于什么地方?
FreeRTOS中的互斥量(Mutex)是一種用于保護(hù)共享資源的同步機(jī)制。它可以確保在任何給定時(shí)刻只有一個(gè)任務(wù)可以訪問被保護(hù)資源,以避免競(jìng)爭(zhēng)條件和數(shù)據(jù)損壞。
在FreeRTOS中,互斥量通過以下API函數(shù)進(jìn)行創(chuàng)建、獲取和釋放:
-
xSemaphoreCreateMutex()
:用于創(chuàng)建一個(gè)互斥量,并返回一個(gè)指向該互斥量的句柄。 -
xSemaphoreTake()
:用于獲?。ㄦi定)互斥量。如果互斥量當(dāng)前未被鎖定,則任務(wù)可以 獲取互斥量并繼續(xù)執(zhí)行;否則,任務(wù)將被阻塞,直到互斥量可用。 -
xSemaphoreGive()
:用于釋放(解鎖)互斥量。一旦任務(wù)完成了對(duì)共享資源的訪問,應(yīng)該調(diào)用此函數(shù)來釋放互斥量,以允許其他任務(wù)獲取它。
創(chuàng)建互斥量
代碼部分
void sendTask1(void const * argument)
{
/* USER CODE BEGIN sendTask1 */
BaseType_t xsatus;
uint32_t buff=9600;
/* Infinite loop */
for(;;)
{
osDelay(20);
if(xSemaphoreTake(myMutex01Handle,portMAX_DELAY)!=pdTRUE)
{
printf("1號(hào):你上完廁所,下一個(gè)就輪到我了\r\n"); // printf輸出字符串
}
else
{
printf("1號(hào):現(xiàn)在是我在上廁所\r\n"); // printf輸出字符串
xSemaphoreGive(myMutex01Handle);
printf("1號(hào):我上完了\r\n"); // printf輸出字符串
}
osDelay(2000);
}
/* USER CODE END sendTask1 */
}
/* USER CODE BEGIN Header_sendTask2 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_sendTask2 */
void sendTask2(void const * argument)
{
/* USER CODE BEGIN sendTask2 */
BaseType_t xsatus;
uint32_t buff=115200;
/* Infinite loop */
for(;;)
{
xSemaphoreTake(myMutex01Handle,0);
printf("2號(hào):我在廁所\r\n"); // printf輸出字符串
osDelay(3000);
printf("2號(hào):我上完了\r\n"); // printf輸出字符串
xSemaphoreGive(myMutex01Handle);
osDelay(2000);
}
/* USER CODE END sendTask2 */
}
/* USER CODE BEGIN Header_readTask3 */
/**
* @brief Function implementing the read thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_readTask3 */
void readTask3(void const * argument)
{
/* USER CODE BEGIN readTask3 */
BaseType_t xsatus;
uint32_t buff=115200;
/* Infinite loop */
for(;;)
{
if(xSemaphoreTake(myMutex01Handle,0)!=pdTRUE)
{
printf("3號(hào):廁所有人,等一會(huì)兒再來\r\n"); // printf輸出字符串
}
else
{
printf("3號(hào):到我上小便了\r\n"); // printf輸出字符串
printf("3號(hào):我撒完尿了\r\n"); // printf輸出字符串
xSemaphoreGive(myMutex01Handle);
}
osDelay(1000);
}
/* USER CODE END readTask3 */
}
實(shí)驗(yàn)現(xiàn)象
五,實(shí)驗(yàn)四:事件組
互斥量是什么?適用于什么地方?
FreeRTOS事件組是一個(gè)用于多任務(wù)協(xié)調(diào)和通信的機(jī)制。它允許任務(wù)等待多個(gè)事件同時(shí)發(fā)生,并在事件發(fā)生后恢復(fù)任務(wù)的執(zhí)行。事件組可以用于線程同步、互斥、事件通知等應(yīng)用場(chǎng)景。
FreeRTOS事件組由32位的二進(jìn)制位表示,每個(gè)事件標(biāo)志位對(duì)應(yīng)一個(gè)事件。任務(wù)可以通過等待特定的事件標(biāo)志位來掛起自己的執(zhí)行,并在其中一個(gè)或多個(gè)事件標(biāo)志位被設(shè)置時(shí)被喚醒。任務(wù)還可以使用事件組的API函數(shù)來設(shè)置或清除特定的事件標(biāo)志位。
以下是一些常用的FreeRTOS事件組API函數(shù):
-
xEventGroupCreate()
:創(chuàng)建一個(gè)新的事件組。 -
vEventGroupDelete()
:刪除已創(chuàng)建的事件組。 -
xEventGroupSetBits()
:設(shè)置一個(gè)或多個(gè)事件標(biāo)志位。 -
xEventGroupClearBits()
:清除一個(gè)或多個(gè)事件標(biāo)志位。 -
xEventGroupWaitBits()
:等待一個(gè)或多個(gè)事件標(biāo)志位被設(shè)置。
使用FreeRTOS事件組可以實(shí)現(xiàn)任務(wù)之間的同步和通信,提高系統(tǒng)的可靠性和效率。
**CMSIS_V1不支持創(chuàng)建事件組,所以手創(chuàng)建 **
EventGroupHandle_t myEvent=NULL;//創(chuàng)建句柄
myEvent = xEventGroupCreate(); //創(chuàng)建事件組
與邏輯,事件組
任務(wù)代碼:
/* USER CODE END Header_sendTask1 */
void sendTask1(void const * argument)
{
/* USER CODE BEGIN sendTask1 */
BaseType_t xsatus;
uint32_t buff=9600;
/* Infinite loop */
for(;;)
{
printf("1號(hào):這個(gè)方案我同意了\r\n"); // printf輸出字符串
xEventGroupSetBits(myEvent,0x0001);
osDelay(2000);
}
/* USER CODE END sendTask1 */
}
/* USER CODE BEGIN Header_sendTask2 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_sendTask2 */
void sendTask2(void const * argument)
{
/* USER CODE BEGIN sendTask2 */
BaseType_t xsatus;
uint32_t buff=115200;
/* Infinite loop */
for(;;)
{
osDelay(5000);
printf("2號(hào):這個(gè)方案我同意了\r\n"); // printf輸出字符串
xEventGroupSetBits(myEvent,0x0010);
}
/* USER CODE END sendTask2 */
}
/* USER CODE BEGIN Header_readTask3 */
/**
* @brief Function implementing the read thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_readTask3 */
void readTask3(void const * argument)
{
/* USER CODE BEGIN readTask3 */
BaseType_t xsatus;
uint32_t buff=115200;
/* Infinite loop */
for(;;)
{
buff=xEventGroupWaitBits(myEvent,0x0011,pdTRUE,pdTRUE,portMAX_DELAY);//1.句柄;2.哪些位;3.讀完清零;4.全部有效(與邏輯);5.等待時(shí)間
if(buff==0x0011)
{
printf("3號(hào):好這個(gè)方案全票同意\r\n"); // printf輸出字符串
}
osDelay(10000);
}
/* USER CODE END readTask3 */
}
實(shí)驗(yàn)現(xiàn)象
文章來源:http://www.zghlxwxcb.cn/news/detail-664843.html
或邏輯,事件組
void sendTask1(void const * argument)
{
/* USER CODE BEGIN sendTask1 */
BaseType_t xsatus;
uint32_t buff=9600;
/* Infinite loop */
for(;;)
{
printf("1號(hào):這個(gè)方案我同意了\r\n"); // printf輸出字符串
xEventGroupSetBits(myEvent,0x0001);
osDelay(2000);
}
/* USER CODE END sendTask1 */
}
/* USER CODE BEGIN Header_sendTask2 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_sendTask2 */
void sendTask2(void const * argument)
{
/* USER CODE BEGIN sendTask2 */
BaseType_t xsatus;
uint32_t buff=115200;
/* Infinite loop */
for(;;)
{
osDelay(5000);
printf("2號(hào):這個(gè)方案我同意了\r\n"); // printf輸出字符串
xEventGroupSetBits(myEvent,0x0010);
}
/* USER CODE END sendTask2 */
}
/* USER CODE BEGIN Header_readTask3 */
/**
* @brief Function implementing the read thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_readTask3 */
void readTask3(void const * argument)
{
/* USER CODE BEGIN readTask3 */
BaseType_t xsatus;
uint32_t buff=115200;
/* Infinite loop */
for(;;)
{
buff=xEventGroupWaitBits(myEvent,0x0011,pdTRUE,pdFALSE,portMAX_DELAY);//1.句柄;2.哪些位;3.讀完清零;4.全部有效(與邏輯);5.等待時(shí)間
if((buff==0x0010)||(buff==0x0001))
{
printf("3號(hào):好方案通過,下一個(gè)方案\r\n"); // printf輸出字符串
}
}
/* USER CODE END readTask3 */
}
實(shí)驗(yàn)現(xiàn)象
文章來源地址http://www.zghlxwxcb.cn/news/detail-664843.html
六,實(shí)驗(yàn)五:任務(wù)通知
到了這里,關(guān)于STM32 CubeMX (第二步Freertos任務(wù)通信:隊(duì)列、信號(hào)量、互斥量,事件組,任務(wù)通知)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!