CH04-03-操作系統(tǒng)原理與實踐-μCOS-III任務(wù)通信_第1頁
CH04-03-操作系統(tǒng)原理與實踐-μCOS-III任務(wù)通信_第2頁
CH04-03-操作系統(tǒng)原理與實踐-μCOS-III任務(wù)通信_第3頁
CH04-03-操作系統(tǒng)原理與實踐-μCOS-III任務(wù)通信_第4頁
CH04-03-操作系統(tǒng)原理與實踐-μCOS-III任務(wù)通信_第5頁
已閱讀5頁,還剩82頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

《嵌入式系統(tǒng)設(shè)計原理》嵌入式操作系統(tǒng)原理與實踐μC/OS-III通信機制主講人:賴樹明東莞理工學(xué)院05事件標(biāo)志組01通信機制概述02信號量03互斥信號量04消息隊列01通信機制概述通信機制概述01使用實時操作系統(tǒng),相對于裸機程序的一個優(yōu)勢是可以把復(fù)雜的功能劃分到不同的任務(wù)中,但這些任務(wù)的數(shù)據(jù)以及邏輯功能是存在密切的聯(lián)系的,因此需要有一種機制可以實現(xiàn)任務(wù)之間的通信,以便于使用這些獨立的任務(wù)可以按我們的設(shè)想?yún)f(xié)調(diào)運行起來,uc/OS-III操作系統(tǒng)提供了豐富的任務(wù)間通信的機制,可以讓我們根據(jù)使用場景,選擇不同的通信方式。概述A信號量B互斥信號量C消息隊列D事件標(biāo)志組E任務(wù)信號量F任務(wù)消息隊列概述02信號量信號量介紹API函數(shù)接口任務(wù)同步示例任務(wù)互斥示例信號量02信號量(Semaphore)是一種實現(xiàn)任務(wù)間通信的機制,用于任務(wù)之間同步或臨界資源的互斥訪問。通俗理解:信號量是一個正值變量,表示資源的可申請數(shù),當(dāng)任務(wù)申請信號量時,變量值減1,任務(wù)使用完成后,再釋放信號量,效果是變量值

加1;信號量為0時,申請信號號的任務(wù)則無法獲得信號,表現(xiàn)為退出或者等待掛起,直到有其他任務(wù)釋放了信號量,這些等待的任務(wù)會按照優(yōu)先級來獲取信號量,繼續(xù)執(zhí)行其代碼。概念信號量介紹信號量可以細分為兩種類型:二進制信號量和計數(shù)信號量。二進制信號量只能取兩個值:0或者1,在開發(fā)中使用最多的還是是二值信號量這種情形;計數(shù)信號量允許的值介于0~255/65535/4294967295之間,具體取決于信號量機制是使用8位、16位,還是32位數(shù)據(jù)類型實現(xiàn)的。對于μC/OS-III,信號量的最大值由數(shù)據(jù)類型OS_SEM_CTR(見os_type.h)決定,可以根據(jù)需要更改其他類似。特征信號量的使用流程有三個必需的步驟,分別是創(chuàng)建信號量、申請信號量、發(fā)送信號量,其他可選操作有刪除信號量、中止等待信號量、修改信號值等。使用流程表4.1信號量函數(shù)序號函數(shù)名功能描述備注1OSSemCreate()創(chuàng)建一個信號量必須調(diào)用2OSSemDel()刪除一個信號量必須調(diào)用3OSSemPend()等待信號量必須調(diào)用4OSSemPendAbort()中止對信號量的等待可選調(diào)用5OSSemPost()發(fā)送或發(fā)出信號量信號可選調(diào)用6OSSemSet()強制信號量計數(shù)為所需值可選調(diào)用信號量02API函數(shù)接口μC/OS-III系統(tǒng)使用OS_SEM結(jié)構(gòu)來表示一個信號量,創(chuàng)建信號量,只需要調(diào)用系統(tǒng)提供的OSSemCreate函數(shù),根據(jù)需要傳遞必須參數(shù)即可創(chuàng)建信號量原型:voidOSSemCreate(OS_SEM*p_sem,CPU_CHAR*p_name,OS_SEM_CTRcnt,RTOS_ERR*p_err)功能:創(chuàng)建信號量參數(shù):p_sem:指向要初始化的信號量的指針,一般傳遞OS_SEM類型變量地址。p_name:指向要分配給信號量名稱的指針。cnt:信號量的初始值,如果用于共享資源,則應(yīng)初始化為可用資源數(shù);如用于表示事件的發(fā)生,則應(yīng)初始化為0。p_err:指向存放錯誤代碼變量的地址,函數(shù)調(diào)用可能產(chǎn)生的錯誤碼如下:OS_ERR_NONE:無錯誤,指示信號量創(chuàng)建成功;OS_ERR_CREATE_ISR:在中斷服務(wù)程序中調(diào)用了此函數(shù);OS_ERR_ILLEGAL_CREATE_RUN_TIME:在調(diào)用OSSafetyCriticalStart()后嘗試創(chuàng)建信號量。OS_ERR_NAME:如果'p_name'是一個NULL指針OS_ERR_OBJ_CREATED:如果信號量已經(jīng)創(chuàng)建,即p_sem前面已經(jīng)被創(chuàng)建過了。OS_ERR_OBJ_PTR_NULL:如果'p_sem'是一個NULL指針OS_ERR_OBJ_TYPE:p_sem類型不是OS_SEM*;信號量02API函數(shù)接口示例代碼OS_SEMmy_sem_test;

//定義信號量全局變量,用于任務(wù)同步。//創(chuàng)建一個信號量OSSemCreate((OS_SEM*)&my_sem_test,(CPU_CHAR*)"MySemTest",(OS_SEM_CTR)0,(OS_ERR*)&err);//創(chuàng)建失敗,讓程序進入死循環(huán),這樣在開發(fā)階段方便發(fā)現(xiàn)問題。if(err!=OS_ERR_NONE){ while(1){;}}信號量02API函數(shù)接口調(diào)用OSSemPend函數(shù)申請指定的信號量,如果所申請的信號量其信號值大于0,則馬上獲得信號量,同時把信號值減去1,繼續(xù)執(zhí)行后面的代碼。如果當(dāng)前信號值是0,則表示當(dāng)前信號量不可用,此時任務(wù)可以選擇繼續(xù)往下運行或者進入掛起狀態(tài)等待信號量變成正數(shù)。申請信號量函數(shù)原型:OS_SEM_CTROSSemPend(OS_SEM*p_sem,OS_TICKtimeout,

OS_OPTopt,CPU_TS*p_ts,OS_ERR*p_err)函數(shù)功能:申請信號量,申請成功任務(wù)繼續(xù)往下運行,信號量不可用時,任務(wù)掛起或者返回錯誤碼后繼續(xù)往下運行(具體哪一種情況由調(diào)用函數(shù)時給opt參數(shù)傳遞的值決定)。函數(shù)參數(shù):p_sem:是指向信號量的指針,一般傳遞OS_SEM類型變量地址;

timeout:超時時間(以時鐘節(jié)拍為單位)。當(dāng)opt參數(shù)傳遞為OS_OPT_PEND_BLOCKING,timeout值為大于0時,表示信號量任務(wù)掛起的最長等待時間,如超過在該參數(shù)指定的時長,信號量還不可用,則任務(wù)恢復(fù)運行,并且將p_err指向的錯誤碼變量值設(shè)置為OS_ERR_TIMEOUT。當(dāng)值為0時,表示任務(wù)將永久掛起,直到等待的信號量變成可用,然后獲得信號量恢復(fù)運行。

opt:OS_OPT_PEND_BLOCKING:任務(wù)會阻塞;OS_OPT_PEND_NON_BLOCKING:任務(wù)不會阻塞.

p_ts:用于存放信號量釋放/掛起中止/信號量刪除時的時間戳。如不需要時間戳,傳NULL。

p_err:指向存放錯誤代碼變量的地址,函數(shù)調(diào)用可能產(chǎn)生的錯誤碼如下:

OS_ERR_NONE:指示成功獲得信號量;.......

OS_ERR_PEND_ISR:指示從ISR調(diào)用此函數(shù),結(jié)果將導(dǎo)致掛起;

OS_ERR_TIMEOUT:指示在指定的超時時間內(nèi)未收到信號量。函數(shù)返回值:信號量計數(shù)器的當(dāng)前值,值為0表示當(dāng)前信號量不可用。一般是通過p_err指向的錯誤碼來判斷申請結(jié)果。信號量02API函數(shù)接口示例代碼函數(shù)示例:假設(shè)當(dāng)前信號量my_sem_test已經(jīng)創(chuàng)建好了。OS_ERRerr;//存放函數(shù)調(diào)用錯誤碼//沒有獲得信號量會掛起任務(wù)OSSemPend(&my_sem_test,0,OS_OPT_PEND_BLOCKING,0,&err);//請求信號量//判斷申請信號量是否成功if(err!=OS_ERR_NONE){//在以下編寫沒有正確獲得信號量但是函數(shù)返回時的處理代碼……//根據(jù)實際情況編寫出錯處理代碼}

信號量02API函數(shù)接口本示例是使用信號量實現(xiàn)兩個任務(wù)同步,演示通過信號量實現(xiàn)任務(wù)間通信的方法。任務(wù)1負責(zé)檢測按鍵1是否按下,按下了則發(fā)送信號量;任務(wù)2負責(zé)申請信號量,等待任務(wù)1發(fā)送信號量后,往下執(zhí)行代碼,控制開發(fā)板上的LED。實驗的效果是每按下按鍵1一次,開發(fā)板上的LED就會反轉(zhuǎn)一次。發(fā)送信號量信號量02任務(wù)同步示例主函數(shù)OS_SEMkey_sem;//定義一個信號量,用于任務(wù)同步intmain(void){OS_ERRerr;CPU_SR_ALLOC();......OSInit(&err);//初始化μC/OS-III//創(chuàng)建一個信號量OSSemCreate((OS_SEM*)&key_sem,(CPU_CHAR*)"key_sem",(OS_SEM_CTR)0,//信號值初始值設(shè)置為0(OS_ERR*)&err);//創(chuàng)建失敗,讓程序進入死循環(huán),這樣在開發(fā)階段方便發(fā)現(xiàn)問題。if(err!=OS_ERR_NONE){while(1){;}}OS_CRITICAL_ENTER();//進入臨界區(qū)//創(chuàng)建開始任務(wù).......//調(diào)用OSTaskCreate創(chuàng)建啟動任務(wù)OS_CRITICAL_EXIT();//退出臨界區(qū)OSStart(&err);//開啟μC/OS-III}信號量02任務(wù)同步示例主函數(shù)OS_SEMkey_sem;//定義一個信號量,用于任務(wù)同步intmain(void){OS_ERRerr;CPU_SR_ALLOC();......OSInit(&err);//初始化μC/OS-III//創(chuàng)建一個信號量OSSemCreate((OS_SEM*)&key_sem,(CPU_CHAR*)"key_sem",(OS_SEM_CTR)0,//信號值初始值設(shè)置為0(OS_ERR*)&err);//創(chuàng)建失敗,讓程序進入死循環(huán),這樣在開發(fā)階段方便發(fā)現(xiàn)問題。if(err!=OS_ERR_NONE){while(1){;}}OS_CRITICAL_ENTER();//進入臨界區(qū)//創(chuàng)建開始任務(wù).......//調(diào)用OSTaskCreate創(chuàng)建啟動任務(wù)OS_CRITICAL_EXIT();//退出臨界區(qū)OSStart(&err);//開啟μC/OS-III}信號量02任務(wù)同步示例任務(wù)1函數(shù)//任務(wù)1的任務(wù)函數(shù)voidtask1_task(void*p_arg){

u8key;

OS_ERRerr;

while(1)

{ key=KEY_Scan(0);

//掃描按鍵 if(key==KEY1_PRES)

//如果按下開發(fā)板按鍵1 { printf("Task1:發(fā)送一個信號量\r\n");

//輸出發(fā)送信號量提示 OSSemPost(&key_sem,OS_OPT_POST_1,&err);

//發(fā)送信號量 printf("當(dāng)前信號值:%u\r\n",key_sem.Ctr); } OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);//延時10ms

}}信號量02任務(wù)同步示例任務(wù)1函數(shù)voidtask2_task(void*p_arg){u8num;OS_ERRerr;while(1){//沒有獲得信號量會掛起任務(wù)OSSemPend(&key_sem,0,OS_OPT_PEND_BLOCKING,0,&err);//請求信號量//判斷申請信號量是否成功if(err!=OS_ERR_NONE){//在以下編寫沒有正確獲得信號量但是函數(shù)返回時的處理代碼//......}LED1_Toglge();//翻轉(zhuǎn)LED1狀態(tài)}}信號量02任務(wù)同步示例本示例是使用信號量實現(xiàn)對共享資源的互斥訪問,演示通過信號量實現(xiàn)任務(wù)間通信的另一種使用場景。任務(wù)1和任務(wù)2都需要訪問一個共享資源,即一塊數(shù)據(jù)緩沖區(qū),程序中可表示為一個數(shù)組,其中任務(wù)1對這塊數(shù)組進行寫操作,任務(wù)2負責(zé)讀取出任務(wù)1寫入的數(shù)據(jù)。為了保證任務(wù)2每次都可以完整讀取任務(wù)1的一次完成寫操作數(shù)據(jù),保證數(shù)據(jù)不會混亂,則任務(wù)1和任務(wù)2在訪問這塊共享的內(nèi)存(數(shù)組)時都需要申請同一個信號量,如果信號量被其中一個持有了,則需要等待對方訪問完共享資源,然后發(fā)送信號量,才可以訪問共享資源,從而保證了共享資源的互斥訪問。功能說明信號量02任務(wù)互斥示例示例框圖信號量02任務(wù)互斥示例主函數(shù)OS_SEMshare_mem_sem;//定義一個信號量,用于保護共享資訪問。intmain(void){OS_ERRerr;CPU_SR_ALLOC();......OSInit(&err);//初始化μC/OS-III//創(chuàng)建一個信號量share_mem_semOSSemCreate((OS_SEM*)&share_mem_sem,(CPU_CHAR*)"share_mem_sem",(OS_SEM_CTR)1,//注意本示例初始值不能為0(OS_ERR*)&err);//創(chuàng)建失敗,讓程序進入死循環(huán),這樣在開發(fā)階段方便發(fā)現(xiàn)問題。if(err!=OS_ERR_NONE){while(1){;}}OS_CRITICAL_ENTER();//進入臨界區(qū)……//調(diào)用OSTaskCreate創(chuàng)建啟動任務(wù)。OS_CRITICAL_EXIT();//退出臨界區(qū)OSStart(&err);//開啟μC/OS-III}信號量02任務(wù)互斥示例主函數(shù)voidtask1_task(void*p_arg){ OS_ERRerr; uint32_tcnt=1;//記錄寫入數(shù)據(jù)的次數(shù) while(1) { OSSemPend(&share_mem_sem,0,OS_OPT_PEND_BLOCKING,0,&err);//請求信號量 //判斷申請信號量是否成功 if(err!=OS_ERR_NONE){ //在以下編寫沒有正確獲得信號量但是函數(shù)返回時的處理代碼 } //以下開始訪問共享資源,往array_buf數(shù)組中寫入數(shù)據(jù) sprintf(array_buf,"cnt:%05d",cnt);//開始訪問共享資源 printf("第%d次寫入數(shù)據(jù):%s\r\n",cnt,array_buf);//輸出寫入內(nèi)容提示 cnt++;//寫入次數(shù)增加 OSSemPost(&share_mem_sem,OS_OPT_POST_1,&err);//釋放信號量 OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//延時1s }}信號量02任務(wù)互斥示例任務(wù)1函數(shù)//任務(wù)1的任務(wù)函數(shù)voidtask1_task(void*p_arg){

u8key;

OS_ERRerr;

while(1)

{ key=KEY_Scan(0);

//掃描按鍵 if(key==KEY1_PRES)

//如果按下開發(fā)板按鍵1 { printf("Task1:發(fā)送一個信號量\r\n");

//輸出發(fā)送信號量提示 OSSemPost(&key_sem,OS_OPT_POST_1,&err);

//發(fā)送信號量 printf("當(dāng)前信號值:%u\r\n",key_sem.Ctr); } OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);//延時10ms

}}信號量02任務(wù)互斥示例任務(wù)2函數(shù)voidtask2_task(void*p_arg){OS_ERRerr;charread_buf[50]={0};//用于存放臨時數(shù)據(jù)uint32_tcnt=1;

//記錄讀取數(shù)據(jù)的次數(shù)while(1){

//沒有獲得信號量會掛起任務(wù)OSSemPend(&share_mem_sem,0,OS_OPT_PEND_BLOCKING,0,&err);if(err!=OS_ERR_NONE){//在以下編寫沒有正確獲得信號量但是函數(shù)返回時的處理代碼....}//以下開始訪問共享資源,把array_buf數(shù)組中的字符串復(fù)制到read_buf中strcpy(read_buf,array_buf);//開始訪問共享資源//輸出讀取到的內(nèi)容提示,寫入次數(shù)增加printf("第%d次讀取數(shù)據(jù):%s\r\n",cnt++,read_buf);OSSemPost(&share_mem_sem,OS_OPT_POST_1,&err);//釋放信號量OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_PERIODIC,&err);}}信號量02任務(wù)互斥示例03互斥信號量互斥信號量介紹API函數(shù)接口任務(wù)互斥示例----------優(yōu)先級反轉(zhuǎn),是指某個共享資源被較低優(yōu)先級的任務(wù)所持有,較高優(yōu)先級的任務(wù)任務(wù)申請該共享資源無法獲得,導(dǎo)致較高優(yōu)先級任務(wù)反而被更低優(yōu)先級的任務(wù)推遲被調(diào)度執(zhí)行的現(xiàn)象?;コ庑盘柫?3互斥信號量介紹優(yōu)先級反轉(zhuǎn)概念μC/OS-III支持一種特殊類型的二值互斥信號量,稱為互斥信號量(也稱為互斥體),相對于前面學(xué)習(xí)過普通二值互斥信號量,它解決了優(yōu)先級反轉(zhuǎn)的問題。接下來的先來學(xué)習(xí)什么是什么級轉(zhuǎn)換,才可以更好理解互斥信號量的作用?;コ庑盘柫扛拍钣覉D展示一個優(yōu)先級反轉(zhuǎn)的示例:系統(tǒng)中有高(TaskH),中(TaskM),低(TaskL)三個級別優(yōu)先級任務(wù),某一時刻低TaskL任務(wù)持有信號量S,此時TaskH就緒搶占TaskL,然后申請信號量S,但是此時信號量被TaskL持有,因此TaskH掛起,放棄CPU。然后TaskL恢復(fù)運行,運行過程中TaskM就緒搶占TaskL,TaskM沒有申請信號量S,因此它可以長時間持有CPU,這樣就導(dǎo)致了TaskH反而被比它低的任務(wù)TaskM推遲調(diào)度,因為只有TaskM釋放CPU,TaskL才可以繼續(xù)運行,從而釋放信號量,Task才有機會運行,這現(xiàn)象就是優(yōu)先級反轉(zhuǎn)?;コ庑盘柫?3互斥信號量介紹優(yōu)先級反轉(zhuǎn)示例互斥信號量的使用流程很簡單:創(chuàng)建互斥信號量、申請互斥信號量、釋放互斥信號量三個必需的步驟,其他可選操作有刪除互斥信號量、中止等待互斥信號量?;コ庑盘柫拷涌诨コ庑盘柫?3API函數(shù)接口

互斥信號量函數(shù)序號函數(shù)名功能描述備注1OSMutexCreate()創(chuàng)建一個互斥信號量必須調(diào)用2OSMutexDel()刪除一個互斥信號量必須調(diào)用3OSMutexPend()等待互斥信號量必須調(diào)用4OSMutexPendAbort()中止對互斥信號量的等待可選調(diào)用5OSMutexPost()釋放互斥信號量可選調(diào)用μC/OS-III系統(tǒng)使用OS_MUTEX結(jié)構(gòu)來表示一個互斥信號量,要創(chuàng)建互斥信號量,我們只需要調(diào)用系統(tǒng)提供的OSMutexCreateAPI函數(shù),根據(jù)需要傳遞必須參數(shù)即可創(chuàng)建互斥信號量互斥信號量03API函數(shù)接口函數(shù)原型:voidOSMutexCreate(OS_MUTEX*p_mutex,CPU_CHAR*p_name,OS_ERR*p_err)函數(shù)功能:創(chuàng)建互斥信號量函數(shù)參數(shù):p_mutex:指向要初始化的互斥信號量的指針,一般是傳遞OS_MUTEX類型的變量地址。

p_name:指向要分配給互斥信號量的名稱的指針

p_err:指向存放錯誤代碼變量的指針,函數(shù)調(diào)用可能產(chǎn)生的錯誤碼如下:

OS_ERR_NONE:指示互斥信號量創(chuàng)建成功;

OS_ERR_CREATE_ISR:指示在中斷服務(wù)程序中調(diào)用了此函數(shù);

OS_ERR_NAME:指令'p_name'是一個NULL指針;

OS_ERR_OBJ_CREATED:指示p_mutex已經(jīng)創(chuàng)建過了;

OS_ERR_OBJ_PTR_NULL:指示'p_mutex'是一個NULL指針;示例代碼函數(shù)示例:OS_MUTEXmy_mutex_test;//定義互斥信號量全局變量,用于共享資源保護。OSMutexCreate((OS_MUTEX*)&my_mutex_test,(CPU_CHAR*)"my_mutex_test",(OS_ERR*)&err);//創(chuàng)建失敗,讓程序進入死循環(huán),這樣在開發(fā)階段方便發(fā)現(xiàn)問題。if(err!=OS_ERR_NONE){ while(1){;}}示例說明:①使用互斥信號量時,互斥信號量變量需要定義為全局變量,否則其他任務(wù)不能使用;②不要在中斷服務(wù)程序中去創(chuàng)建互斥信號量;備注:函數(shù)提供的錯誤碼比較多,寫代碼時一般判斷錯誤碼值是否等于OS_ERR_NONE,如果不等于該值表示函數(shù)調(diào)用出錯了,如果需要分析具體哪一種錯誤,再使用單步調(diào)試的方法來觀察函數(shù)返回的錯誤碼。互斥信號量03API函數(shù)接口調(diào)用OSMutexPend函數(shù)申請指定的互斥信號量,如果持有互斥信號量的任務(wù)優(yōu)先級比當(dāng)前申請互斥信號量的任務(wù)優(yōu)先級低,則會把持有互斥信號量的任務(wù)的優(yōu)先級臨時提升到和當(dāng)前申請互斥信號量的任務(wù)優(yōu)先級一樣。然后,當(dāng)前任務(wù)進入掛起狀態(tài),把CPU歸還給原來持有互斥信號量的任務(wù),讓持有互斥信號量的任務(wù)繼續(xù)運行。當(dāng)持有該互斥信號量的任務(wù)釋放掉互斥信號量后,其優(yōu)先級重新恢復(fù)到原來的優(yōu)先級?;コ庑盘柫?3API函數(shù)接口申請互斥信號量函數(shù)原型:voidOSMutexPend(OS_MUTEX*p_mutex,OS_TICKtimeout,OS_OPTopt,CPU_TS*p_ts,OS_ERR*p_err)函數(shù)功能:申請指定的互斥信號量,函數(shù)形參:p_sem:指向互斥信號量的指針;timeout:超時時間(以時鐘節(jié)拍為單位),用法和作用和申請信號量函數(shù)時一樣。opt:用法和作用和申請信號量函數(shù)時一樣。。p_ts:用于保存互斥信號量發(fā)布或掛起中止或互斥信號量刪除時的時間戳。不需要時間戳,可傳NULL。p_err:指向存放錯誤代碼變量的指針,函數(shù)調(diào)用可能產(chǎn)生的錯誤碼如下:

OS_ERR_NONE:指示成功獲得互斥信號量

OS_ERR_PEND_ISR:指示在中斷服務(wù)程序中調(diào)用了此函數(shù),結(jié)果將導(dǎo)致掛起。

OS_ERR_TIMEOUT:指示在指定的超時時間內(nèi)未能成功獲得互斥信號量

.......示例代碼函數(shù)示例:假設(shè)當(dāng)前互斥信號量my_mutex_test已經(jīng)創(chuàng)建好。OS_ERRerr;//存放函數(shù)調(diào)用錯誤碼//沒有獲得互斥信號量會掛起任務(wù)OSMutexPend(&my_mutex_test,0,OS_OPT_PEND_BLOCKING,0,&err);//請求互斥信號量//判斷互斥信號量是否成功獲得if(err!=OS_ERR_NONE){ //在以下編寫沒有正確獲得互斥信號量但是函數(shù)返回時的處理代碼 ......//根據(jù)實際情況編寫出錯處理代碼}互斥信號量03API函數(shù)接口調(diào)用OSMutexPost函數(shù)可以釋放互斥信號量,如果有等待該互斥信號量的任務(wù)就緒,并比當(dāng)前任務(wù)有更高的優(yōu)先級,則執(zhí)行任務(wù)調(diào)度,CPU執(zhí)行切換到新任務(wù)執(zhí)行。否則,原任務(wù)在釋放互斥信號量之后繼續(xù)執(zhí)行后面代碼。函數(shù)原型:voidOSMutexPost(OS_MUTEX*p_mutex,OS_OPTopt,OS_ERR*p_err)函數(shù)功能:釋放互斥信號量,如果有等待此互斥信號量的高優(yōu)先級任務(wù),則馬上發(fā)生任務(wù)切換,否則繼續(xù)運行當(dāng)前任務(wù)后面的代碼。函數(shù)形參:p_sem:是指向互斥信號量的指針

opt:確定執(zhí)行的POST類型

OS_OPT_POST_NONE:表示未選擇特殊選項

OS_OPT_POST_NO_SCHED:表示如果你不希望在釋放互斥信號量后開始調(diào)度程序p_err:指向存放錯誤代碼變量的指針。函數(shù)調(diào)用可能產(chǎn)生的錯誤碼如下:

OS_ERR_NONE:指示調(diào)用成功釋放互斥信號量;

OS_ERR_MUTEX_NESTING:指示互斥鎖擁有者嵌套了它對互斥鎖的使用;

OS_ERR_MUTEX_NOT_OWNER:指示釋放互斥信號量的任務(wù)不是互斥鎖所有者;

OS_ERR_OBJ_PTR_NULL:指示'p_mutex'是一個NULL指針;

OS_ERR_OBJ_TYPE:指示'p_mutex'沒有指向OS_MUTEX類型變量;

OS_ERR_POST_ISR:指示在中斷服務(wù)程序中釋放互斥信號量?;コ庑盘柫?3API函數(shù)接口釋放互斥信號量示例代碼函數(shù)示例:假設(shè)當(dāng)前互斥信號量my_mutex_test已經(jīng)創(chuàng)建好了。OS_ERRerr;//存放函數(shù)調(diào)用錯誤碼OSMutexPost(&my_mutex_test,OS_OPT_POST_NONE,&err);//發(fā)送互斥信號量//判斷互斥信號量是否成功發(fā)送,發(fā)送一般都不會出錯,以下判斷代碼也可以不寫if(err!=OS_ERR_NONE){ //在以下編寫沒有成功發(fā)送互斥信號量時的處理代碼,一般情況不用寫。 ……//}互斥信號量03API函數(shù)接口本示例是使用互斥信號量實現(xiàn)對共享資源的互斥訪問。任務(wù)1和任務(wù)2都需要訪問一個共享資源,即一塊數(shù)據(jù)緩沖區(qū),程序中可表示為一個數(shù)組,其中任務(wù)1對這塊數(shù)組進行寫操作,任務(wù)2負責(zé)讀取出數(shù)據(jù)緩沖區(qū)任務(wù)1寫入的數(shù)據(jù)。為了保證任務(wù)2每次都可以完整讀取任務(wù)1的一次完成寫操作,保證數(shù)據(jù)不會混亂,則任務(wù)1和任務(wù)2在訪問這塊共享的內(nèi)存(數(shù)組)時都需要申請同一個互斥信號量,如果互斥信號量被其中一個任務(wù)持有了,則需要等待對方訪問完共享資源,然后互斥信號量才可以訪問共享資源,從而保證了共享資源的互斥訪問。功能說明互斥信號量03任務(wù)互斥示例示例框圖互斥信號量03任務(wù)互斥示例主函數(shù)OS_MUTEXshare_mem_mutex;//定義一個互斥信號量,用于保護共享資訪問intmain(void){OS_ERRerr;CPU_SR_ALLOC();......OSInit(&err);//初始化μC/OS-III//創(chuàng)建一個互斥信號量OSMutexCreate((OS_MUTEX*)&share_mem_mutex,(CPU_CHAR*)"share_mem_mutex",(OS_ERR*)&err);//創(chuàng)建失敗,讓程序進入死循環(huán),這樣在開發(fā)階段方便發(fā)現(xiàn)問題if(err!=OS_ERR_NONE){while(1){;}}OS_CRITICAL_ENTER();//進入臨界區(qū)//調(diào)用OSTaskCreate創(chuàng)建啟動任務(wù),和前面講解的代碼相同,此時省略......OS_CRITICAL_EXIT();//退出臨界區(qū)OSStart(&err);//開啟μC/OS-III}互斥信號量03任務(wù)互斥示例主函數(shù)voidtask1_task(void*p_arg){ OS_ERRerr; uint32_tcnt=1;//記錄寫入數(shù)據(jù)的次數(shù) while(1) { OSSemPend(&share_mem_sem,0,OS_OPT_PEND_BLOCKING,0,&err);//請求信號量 //判斷申請信號量是否成功 if(err!=OS_ERR_NONE){ //在以下編寫沒有正確獲得信號量但是函數(shù)返回時的處理代碼 } //以下開始訪問共享資源,往array_buf數(shù)組中寫入數(shù)據(jù) sprintf(array_buf,"cnt:%05d",cnt);//開始訪問共享資源 printf("第%d次寫入數(shù)據(jù):%s\r\n",cnt,array_buf);//輸出寫入內(nèi)容提示 cnt++;//寫入次數(shù)增加 OSSemPost(&share_mem_sem,OS_OPT_POST_1,&err);//釋放信號量 OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//延時1s }}互斥信號量03任務(wù)互斥示例任務(wù)1函數(shù)voidtask1_task(void*p_arg){OS_ERRerr;uint32_tcnt=1;//記錄寫入數(shù)據(jù)的次數(shù)while(1){

//請求互斥信號量OSMutexPend(&share_mem_mutex,0,OS_OPT_PEND_BLOCKING,0,&err);

if(err!=OS_ERR_NONE){//在以下編寫沒有正確獲得互斥信號量但是函數(shù)返回時的處理代碼//……} //以下開始訪問共享資源,往array_buf數(shù)組中寫入數(shù)據(jù)sprintf(array_buf,"cnt:%05d",cnt);//開始訪問共享資源printf("第%d次寫入數(shù)據(jù):%s\r\n",cnt++,array_buf);//輸出寫入內(nèi)容提示,寫入次數(shù)增加OSMutexPost(&share_mem_mutex,OS_OPT_POST_NONE,&err);//釋放互斥信號量OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//延時1s}}互斥信號量03任務(wù)互斥示例任務(wù)2函數(shù)voidtask2_task(void*p_arg){OS_ERRerr;charread_buf[50]={0};//用于存放臨時數(shù)據(jù)uint32_tcnt=1;

//記錄讀取數(shù)據(jù)的次數(shù)while(1){//請求互斥信號量,沒有獲得互斥信號量會掛起任務(wù)OSMutexPend(&share_mem_mutex,0,OS_OPT_PEND_BLOCKING,0,&err);if(err!=OS_ERR_NONE){//判斷申請互斥信號量是否成功//在以下編寫沒有正確獲得互斥信號量但是函數(shù)返回時的處理代碼}//以下開始訪問共享資源,把array_buf數(shù)組中的字符串復(fù)制到read_buf中strcpy(read_buf,array_buf);//開始訪問共享資源printf("第%d次讀取數(shù)據(jù):%s\r\n",cnt++,read_buf);//輸出讀取到的內(nèi)容提示OSMutexPost(&share_mem_mutex,OS_OPT_POST_NONE,&err);//釋放互斥信號量OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_PERIODIC,&err);//延時0.5s}}互斥信號量03任務(wù)互斥示例04消息隊列量消息隊列介紹API函數(shù)接口任務(wù)同步示例μC/OS-III提供的信號量和互斥信號量,它們可以實現(xiàn)任務(wù)間的通信和中斷與任務(wù)之間的通信,但是它們還是有缺陷的,它們不支持在任務(wù)間傳遞用戶自定義的數(shù)據(jù),僅僅是由系統(tǒng)報告了一個事件的發(fā)生而已。在實現(xiàn)編程中,很多場景需要在任務(wù)間或中斷與任務(wù)間傳輸自定義的數(shù)據(jù)。比如,有鍵盤掃描任務(wù)和動作執(zhí)行任務(wù),鍵盤掃描任務(wù)負責(zé)掃描用戶按下了哪個按鍵,然后把按鍵碼發(fā)送給動作執(zhí)行任務(wù)。動作執(zhí)行任務(wù)接收鍵盤掃描任務(wù)發(fā)來的按鍵碼,根據(jù)不同的按鍵碼執(zhí)行不同的控制動作。要實現(xiàn)這樣的功能,就需要使用到μC/OS-III提供的消息隊列功能了。消息隊列04消息隊列介紹消除隊列特征消息隊列也是任務(wù)間通信的一種機制,可以看成一個容器,可存放多條消息。一條消息由指向具體數(shù)據(jù)的指針、存放指向數(shù)據(jù)大小的變量和指示消息發(fā)送時間的時間戳組成。數(shù)據(jù)的指針可以指向任何用戶自定義的數(shù)據(jù)區(qū),甚至可以指向一個函數(shù)。消息隊列概念消息隊列04消息隊列介紹消息內(nèi)容在消息發(fā)出后,在被任務(wù)接收前,必須保持靜態(tài),中途不能改變它的值,因為數(shù)據(jù)是通過發(fā)送其內(nèi)存地址而不是通過值發(fā)送的。換句話說,發(fā)送的數(shù)據(jù)不會被復(fù)制,或者,傳遞指向全局變量、全局數(shù)據(jù)結(jié)構(gòu)、全局數(shù)組或函數(shù)等的指針。μC/OS-III中消息隊列是用戶創(chuàng)建的內(nèi)核對象,只有內(nèi)存資源足夠大,數(shù)量沒有限制。下圖展示了對消息隊列進行的操作有數(shù)據(jù)流程。認識消息隊列消息隊列04消息隊列介紹消息隊列默認是使用先進先出管道(FIFO)的方式,即先進入隊列的消息也是先被取出來。在μC/OS-III中,還可以按后進先出順序(LIFO)發(fā)布消息。當(dāng)任務(wù)或中斷服務(wù)程序必須向任務(wù)發(fā)送“緊急”消息時,LIFO機制很有用。往任務(wù)中發(fā)送消息是通過調(diào)用OSQPost()函數(shù)來實現(xiàn),至于使用FIFO,還是LIFO方式,則由傳遞給OSQPost()函數(shù)的參數(shù)來決定。認識消息隊列消息隊列使用OSQPend()函數(shù)來接收消息,接收消息的任務(wù)旁邊的小沙漏表示任務(wù)可以指定一個超時等待時間,如果任務(wù)指定的時間內(nèi)沒有收到消息,則會超時喚醒任務(wù),并且返回錯誤碼指示當(dāng)前任務(wù)是因為接收消息超時而被喚醒的,不是正確接收到消息被喚醒。如果指定超時時間為0,任務(wù)就會永遠等待下去,直到接收到消息為止。消息隊列04消息隊列介紹消息隊列還包含一個等待消息發(fā)送到消息隊列的任務(wù)列表。多個任務(wù)可以在一個消息隊列上等待,如右圖所示。當(dāng)消息發(fā)送到消息隊列時,等待消息隊列的最高優(yōu)先級任務(wù)接收該消息,還可以向所有在消息隊列上等待的任務(wù)廣播發(fā)送一條消息,從廣播中接收到消息的任務(wù),只要它們的優(yōu)先級高于發(fā)送消息的任務(wù),或者如果任務(wù)是被中斷打斷,消息是在中斷服務(wù)程序中發(fā)送,μC/OS-III都會發(fā)生任務(wù)調(diào)度,μC/OS-III將運行這些處于就緒狀態(tài)優(yōu)先級最高的任務(wù)。認識消息隊列消息隊列的使用流程很簡單:創(chuàng)建消息郵箱、讀取消息、發(fā)送消息三個必需的步驟,其他可選操作有刪除等待消息、中止等待消息。消息隊列接口消息隊列04API函數(shù)接口消息隊列函數(shù)序號函數(shù)名功能描述備注1OSQCreate()創(chuàng)建消息隊列必須調(diào)用2OSQPend()等待接收消息必須調(diào)用3OSQPost()發(fā)送消息到消息隊列中必須調(diào)用4OSQDel()刪除消息隊列可選調(diào)用5OSQFlush()清空消息隊列可選調(diào)用6OSQPendAbort()取消等待消除隊列可選調(diào)用μC/OS-III系統(tǒng)使用OS_Q結(jié)構(gòu)來表示一個消息隊列,創(chuàng)建消息隊列,只需要調(diào)用系統(tǒng)提供的OSQCreateAPI函數(shù),根據(jù)需要傳遞必需的參數(shù)即可。創(chuàng)建消息隊列函數(shù)原型:voidOSQCreate(OS_Q*p_q,CPU_CHAR*p_name,OS_MSG_QTYmax_qty,OS_ERR*p_err)函數(shù)功能:創(chuàng)建消息隊列函數(shù)形參:p_q:指向消息隊列的指針,傳遞OS_Q類型變量的地址;p_name:一個字符串指針,用于給消息隊列命名;max_qty:表示消息隊列的大?。ū仨毞橇悖?,即消息隊列中可以容納消息的數(shù)量;p_err:一個指向存放錯誤碼變量的指針,該變量將包含此函數(shù)返回的錯誤代碼,可取錯誤碼有:OS_ERR_NONE:成功創(chuàng)建消息隊列OS_ERR_CREATE_ISR:指示不能從ISR創(chuàng)建OS_ERR_NAME:指示'p_name'是一個NULL指針OS_ERR_Q_SIZE:指示max_qty指定的大小為0。.......消息隊列04API函數(shù)接口示例代碼函數(shù)示例:創(chuàng)建消息隊列key_msg_qOSQCreate((OS_Q*)&key_msg_q,//消息隊列(CPU_CHAR*)"key_msg_q",

//消息隊列名稱(OS_MSG_QTY)10,

//消息隊列長度,這里設(shè)置為10。(OS_ERR*)&err);

//錯誤碼//創(chuàng)建失敗,讓程序進入死循環(huán),這樣在開發(fā)階段方便發(fā)現(xiàn)問題。if(err!=OS_ERR_NONE){while(1){;}}消息隊列04API函數(shù)接口當(dāng)一個任務(wù)要獲得其他任務(wù)或中斷程序發(fā)來的消息,然后執(zhí)行某些操作時,通過用OSQPend函數(shù)接收消息,如果當(dāng)前沒有消息可接收,任務(wù)會進入掛起狀態(tài)或直接返回(具體行為和調(diào)用時傳遞的參數(shù)有關(guān)),并且在參數(shù)中攜帶返回錯誤碼.從隊列獲取消息函數(shù)原型:void*OSQPend(OS_Q*p_q,OS_TICKtimeout,OS_OPTopt,OS_MSG_SIZE*p_msg_size,CPU_TS*p_ts,OS_ERR*p_err)函數(shù)功能:等待接收消息,如果成功在消息隊列中接收到消息。函數(shù)形參:p_q:是指向消息隊列的指針,傳遞OS_Q類型變量的地址;timeout:超時時間(以時鐘節(jié)拍為單位),和信號量函數(shù)中的timeout參數(shù)相同。opt:指示在接收消息時,和信號量函數(shù)中的opt參數(shù)相同。p_ts:存放消息接收、掛起中止或消息隊列刪除時的時間戳。不需要時間戳?xí)r,傳遞NULL;p_err該變量將包含此函數(shù)返回的錯誤代碼。函數(shù)調(diào)用可能產(chǎn)生的錯誤碼如下:OS_ERR_NONE:指示成功接收到消息。OS_ERR_PEND_ISR:指示在中斷服務(wù)程序中調(diào)用此函數(shù)OS_ERR_TIMEOUT:指示在指定的時間內(nèi)未收到消息導(dǎo)致超時返回....函數(shù)返回值:非NULL:指向接收到的消息指針

消息隊列04API函數(shù)接口示例代碼函數(shù)示例:假設(shè)當(dāng)前消息隊列key_msg_q已經(jīng)創(chuàng)建好了OS_ERRerr;//存放函數(shù)調(diào)用的錯誤碼CPU_TSts;//保存時間戳uint32_tkey_code;//保存消息傳遞來的按鍵碼//假設(shè)OSQPost發(fā)送來的消息是uint32_t類型按鍵碼,因此接收到后需要轉(zhuǎn)換為原來數(shù)據(jù)類型。key_code=(uint32_t)OSQPend((OS_Q*)&key_msg_q,

(OS_TICK)0,

OS_OPT_PEND_BLOCKING,

(OS_MSG_SIZE*)&key_code,

(CPU_TS*)&ts,(OS_ERR*)&err);消息隊列04API函數(shù)接口調(diào)用OSQPost函數(shù)可以發(fā)送一條消息到消息隊列中,如果有在此消息隊列上等待接收消息,并比當(dāng)前任務(wù)有更高優(yōu)先級的任務(wù),則執(zhí)行任務(wù)調(diào)度,CPU執(zhí)行切換到新任務(wù)中執(zhí)行。函數(shù)原型:voidOSQPost(OS_Q*p_q,void*p_void,OS_MSG_SIZEmsg_size,OS_OPTopt,OS_ERR*p_err)函數(shù)功能:向消息隊列中發(fā)送一條消息函數(shù)形參:p_q:是指向消息隊列的指針,傳遞OS_Q類型變量的地址;opt:確定執(zhí)行的POST類型,可取值有:

OS_OPT_POST_ALL:表示POST到隊列中等待的所有任務(wù)。該選項可以添加到OS_OPT_POST_FIFO或OS_OPT_POST_LIFO上。

OS_OPT_POST_FIFOPOST:表示消息到隊列末尾(FIFO)并喚醒單個等待任務(wù)。

OS_OPT_POST_LIFOPOST:表示消息到隊列前面的LIFO)并喚醒單個等待任務(wù)。

OS_OPT_POST_NO_SCHED:表示發(fā)送消息到消息隊列上后,不調(diào)用調(diào)度器。

可能出現(xiàn)的選項組合:

OS_OPT_POST_FIFO、OS_OPT_POST_LIFO、OS_OPT_POST_FIFO+OS_OPT_POST_ALL、

OS_OPT_POST_LIFO+OS_OPT_POST_ALL、

OS_OPT_POST_FIFO+OS_OPT_POST_NO_SCHED

、OS_OPT_POST_LIFO+OS_OPT_POST_NO_SCHED、

OS_OPT_POST_FIFO+OS_OPT_POST_ALL+OS_OPT_POST_NO_SCHED、OS_OPT_POST_LIFO+OS_OPT_POST_ALL+OS_OPT_POST_NO_SCHEDp_err:指向存放錯誤代碼的變量的指針,可能產(chǎn)生的錯誤碼如下:OS_ERR_NONE:指示成功發(fā)送消息到消息隊列上;........發(fā)送消息到隊列消息隊列04API函數(shù)接口示例代碼函數(shù)示例:假設(shè)當(dāng)前消息隊列key_msg_q已經(jīng)創(chuàng)建好OS_ERRerr;uint32_tkey=0x01;//注意類型是uint32_t,后面接收到需要轉(zhuǎn)換回來//發(fā)送key的值到消息隊列中OSQPost((OS_Q*)&key_msg_q,

(void*)key,

//注意:把按鍵碼強制轉(zhuǎn)換為Void

(OS_MSG_SIZE)sizeof(key),

//消息內(nèi)存占用的字節(jié)數(shù)量

(OS_OPT)OS_OPT_POST_FIFO,

//使用先進先出的方式發(fā)送消息

(OS_ERR*)&err);

//接收函數(shù)的錯誤碼消息隊列04API函數(shù)接口本示例是使用消息隊列實現(xiàn)任務(wù)間通信的方法。任務(wù)1負責(zé)檢測按鍵1~按鍵4是否按下,檢測到有鍵按下了,則把按鍵碼當(dāng)成消息內(nèi)容發(fā)送到消息隊列上;任務(wù)2負責(zé)接收消息,并且根據(jù)消息內(nèi)容執(zhí)行不同的代碼。實驗的效果是開發(fā)板上KEY1~KEY4,每按下一個按鍵,開發(fā)板上的對應(yīng)的LED1~LED4狀態(tài)就會翻轉(zhuǎn)一次。功能說明消息隊列04任務(wù)間傳遞數(shù)據(jù)示例示例框圖消息隊列04任務(wù)間傳遞數(shù)據(jù)示例主函數(shù)OS_Qkey_msg_q;//定義一個消息隊列變量intmain(void){OS_ERRerr;CPU_SR_ALLOC();......OSInit(&err);//初始化μC/OS-III//創(chuàng)建消息隊列key_msg_qOSQCreate((OS_Q*)&key_msg_q,//消息隊列(CPU_CHAR*)"key_msg_q",

//消息隊列名稱(OS_MSG_QTY)10,

//消息隊列長度,這里設(shè)置為10(OS_ERR*)&err);

//錯誤碼if(err!=OS_ERR_NONE){//創(chuàng)建失敗,讓程序進入死循環(huán),這樣在開發(fā)階段方便發(fā)現(xiàn)問題while(1){;}}OS_CRITICAL_ENTER();

//進入臨界區(qū)//調(diào)用OSTaskCreate創(chuàng)建啟動任務(wù),和前面講解的代碼相同,此時省略......OS_CRITICAL_EXIT();

//退出臨界區(qū)OSStart(&err);

//開啟μC/OS-III}消息隊列04任務(wù)間傳遞數(shù)據(jù)示例主函數(shù)voidtask1_task(void*p_arg){uint32_tkey;OS_ERRerr;while(1){key=KEY_Scan(0);//掃描按鍵if(key){//如果檢測到有鍵按下//發(fā)送按鍵碼OSQPost((OS_Q*)&key_msg_q,(void*)key,//注意:把按鍵碼強制轉(zhuǎn)換為void*(OS_MSG_SIZE)sizeof(key),//消息內(nèi)存占用的字節(jié)數(shù)量(OS_OPT)OS_OPT_POST_FIFO,//使用先進先出的方式發(fā)送消息(OS_ERR*)&err);//接收函數(shù)的錯誤碼OSTimeDlyHMSM(0,0,0,50,OS_OPT_TIME_PERIODIC,&err);//延時50ms}}}消息隊列04任務(wù)間傳遞數(shù)據(jù)示例任務(wù)1函數(shù)voidtask1_task(void*p_arg){OS_ERRerr;uint32_tcnt=1;//記錄寫入數(shù)據(jù)的次數(shù)while(1){

//請求互斥信號量OSMutexPend(&share_mem_mutex,0,OS_OPT_PEND_BLOCKING,0,&err);

if(err!=OS_ERR_NONE){//在以下編寫沒有正確獲得互斥信號量但是函數(shù)返回時的處理代碼//……} //以下開始訪問共享資源,往array_buf數(shù)組中寫入數(shù)據(jù)sprintf(array_buf,"cnt:%05d",cnt);//開始訪問共享資源printf("第%d次寫入數(shù)據(jù):%s\r\n",cnt++,array_buf);//輸出寫入內(nèi)容提示,寫入次數(shù)增加OSMutexPost(&share_mem_mutex,OS_OPT_POST_NONE,&err);//釋放互斥信號量OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//延時1s}}消息隊列04任務(wù)間傳遞數(shù)據(jù)示例voidtask2_task(void*p_arg){OS_ERRerr;CPU_TSts;//保存時間戳uint32_tkey_code;//保存消息傳遞來的按鍵碼while(1){//沒有接收到消息會掛起任務(wù)//OSQPend發(fā)送來的消息是uint32_t類型按鍵碼,因此接收到后還原原來的數(shù)據(jù)類型。key_code=(uint32_t)OSQPend(

(OS_Q*)&key_msg_q,

(OS_TICK)0,

(OS_OPT)OS_OPT_PEND_BLOCKING,

(OS_MSG_SIZE*)&key_code,

(CPU_TS*)&ts,

(OS_ERR*)&err);if(err!=OS_ERR_NONE){//沒有正確獲得消息但是函數(shù)返回時的處理代碼}消息隊列04任務(wù)間傳遞數(shù)據(jù)示例//根據(jù)接收到的按鍵碼執(zhí)行不同的操作:這里分別改變LED1~LED4狀態(tài)switch(key_code){caseKEY1_PRES://按鍵1按下LED1_Toglge();//翻轉(zhuǎn)LED1狀態(tài)break;caseKEY2_PRES://按鍵2按下LED2_Toglge();//翻轉(zhuǎn)LED1狀態(tài)break;caseKEY3_PRES://按鍵3按下LED3_Toglge();//翻轉(zhuǎn)LED3狀態(tài)break;caseKEY4_PRES://按鍵4按下LED4_Toglge();//翻轉(zhuǎn)LED4狀態(tài)break;}OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_PERIODIC,&err);//延時0.5s}}任務(wù)2函數(shù)總結(jié)與信號量和互斥信號量不同,它們并不能攜帶用戶自定義的數(shù)據(jù)給其他任務(wù),消息隊列設(shè)計可以用于任務(wù)間或中斷與任務(wù)間傳遞數(shù)據(jù),消息隊列可以容納多條消息,可以用作事件的緩沖區(qū),暫時存儲當(dāng)前沒有及時處理的事件,不會因為系統(tǒng)當(dāng)前工作負載過重,無法及時處理導(dǎo)致的事件丟失。使用消息隊列時,不能在中斷程序中調(diào)用OSQPend,以阻塞從消息隊列中等待接收消息。往消息隊列發(fā)送消息支持FIFO和FILO方式,對于后面發(fā)生的要緊急處理的消息,可以通過指定FILO方式來實現(xiàn)接收者優(yōu)先處理的效果。消息隊列04小結(jié)05事件標(biāo)志組事件標(biāo)志組介紹API函數(shù)接口任務(wù)同步示例事件標(biāo)志組05事件標(biāo)志組介紹事件標(biāo)志組是μC/OS-III系統(tǒng)提供的一種用于任務(wù)間通信的同步機制,它和信號量類似,都可以實現(xiàn)任務(wù)等待某個事件的發(fā)生再繼續(xù)往下運行。但事件標(biāo)志組在任務(wù)同步方面比信號量功能更強大,使用更靈活。一個事件標(biāo)志組同步等待多個事件發(fā)生或者等待多個事件中任何一個事件的發(fā)生。從專業(yè)術(shù)語角度描述,即多個事件的“邏輯與”和多個事件的“邏輯或”?!斑壿嬇c”:等待所有事件都發(fā)生時,條件才成立,任務(wù)恢復(fù)運行;“邏輯或”:等待所有的事件的中任意一個事件發(fā)生,條件成立,任務(wù)恢復(fù)運行;事件標(biāo)志組概念051.μC/OS-III“事件標(biāo)志組”使用OS_FLAG_GRP類型來表示,也是一個內(nèi)核對象,由一系列位(8位/16位/32位,由源碼中的OS_FLAGS定義的數(shù)據(jù)類型決定)組成,可以簡單理解為一個二進制位表示一個等待的事件,即圖中間的多個小方格。創(chuàng)建事件標(biāo)志組通過OSFlagCreate()函數(shù)創(chuàng)建,創(chuàng)建成功后就可以在任務(wù)/中斷服務(wù)程序中使用它了;2.任務(wù)或中斷服務(wù)程序可通過OSFlagPost()函數(shù)發(fā)布事件標(biāo)志。注意:只有任務(wù)可以創(chuàng)建、刪除和取消其他任務(wù)在事件標(biāo)志組上掛起狀態(tài),不能在中斷服務(wù)程序中執(zhí)行這幾種操作;認識事件標(biāo)志組事件標(biāo)志組事件標(biāo)志組介紹053.調(diào)用OSFlagPend()函數(shù),任務(wù)可以等待(掛起)事件標(biāo)志組(所有位的子集)中任意數(shù)量的位(一個二進制位就是一個事件)發(fā)生期望的事件(邏輯與、邏輯或)。和前面學(xué)習(xí)過的信號量、消息隊列的掛起一樣,在調(diào)用OSFlagPend()可指定最長的等待超時值,如在指定的時間量(以時鐘節(jié)拍為單位)內(nèi)未發(fā)生期望的事件,則掛起的任務(wù)將恢復(fù)并返回超時錯誤碼。認識事件標(biāo)志組事件標(biāo)志組事件標(biāo)志組介紹054.調(diào)用OSFlagPend()函數(shù)時可以通過參數(shù)決定等待的方式是采用邏輯與還是邏輯或、等待目標(biāo)事件位是清零還是置位。這樣就出現(xiàn)了四種等級組合:①等待所有位集合邏輯“與”置位事件;

②等待所有位集合邏輯“與”清零事件;③等待所有位集合邏輯“或”置位事件;④等待所有位集合邏輯“或”清零事件認識事件標(biāo)志組事件標(biāo)志組事件標(biāo)志組介紹事件標(biāo)志組的使用流程很簡單:創(chuàng)建事件標(biāo)志組、等待事件標(biāo)志、發(fā)送事件標(biāo)志三個必需的步驟,其他可選操作有刪除事件標(biāo)志組、中止等待事件標(biāo)志。事件標(biāo)志組接口事件標(biāo)志組05API函數(shù)接口事件標(biāo)志組函數(shù)序號函數(shù)名功能描述備注1OSFlagCreate()創(chuàng)建事件標(biāo)志組必須調(diào)用2OSFlagPend()等待事件標(biāo)志發(fā)布必須調(diào)用3OSFlagPost()發(fā)布事件標(biāo)志到事件標(biāo)志組必須調(diào)用4OSFlagPendAbort()取消等待事件標(biāo)志組可選調(diào)用5OSFlagDel()刪除事件標(biāo)志組可選調(diào)用6OSFl

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論