新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > STM32 uCOS_II 實踐 之 消息郵箱

STM32 uCOS_II 實踐 之 消息郵箱

作者: 時間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
所謂的消息郵箱并不是把數(shù)據(jù)進行傳輸,而是在合適的時間告訴任務(wù)去使用哪些變量或者當(dāng)一些特殊的變量變化后可以及時并準(zhǔn)確的使用變量,消息郵箱傳遞的是這些變量的指針,而這些變量本身就已經(jīng)存在與內(nèi)存中了,他們多以全局變量或者靜態(tài)變量的形式存在。

首先介紹消息郵箱的一種使用方式,就是只傳遞一個非空指針,告訴等待消息的任務(wù)他等待的時間到了,但是這個指針里并沒有有用的數(shù)據(jù),而任務(wù)中也不應(yīng)該對這個地址指向的變量進行任何的讀取和寫入操作,讀寫操作都是無意義的,從另外一個角度來看,雖然借用了別人的地址但是本身并沒有對地址里的數(shù)據(jù)進行操作,所以地址里的數(shù)據(jù)也是安全的,說白了就是消息郵箱版信號量(非計數(shù))。它的好處就是可以在系統(tǒng)里把信號量有關(guān)的代碼給裁剪掉,但缺點是他并無法達(dá)到信號量的全部功能,這種用法無法進行計數(shù),只是單純的傳遞一次狀態(tài)。如果把消息隊列改造成計數(shù)信號量,個人覺得很沒必要,除非你選的MCU非常的尷尬。權(quán)且就讓這種方式作為初步了解消息郵箱的一個引子吧。

本文引用地址:http://m.butianyuan.cn/article/201612/325154.htm

使用消息郵箱可以分為4個步驟:

步驟1:聲明一個指針變量,這個指針變量在初始化消息郵箱的時候會把這個消息郵箱對應(yīng)的事件控制塊的指針存放進去。

void *Mbox_Task_LED1;

步驟2:對消息郵箱進行初始化,也就是初始化對應(yīng)的事件控制塊,并且會把這個事件控制塊的指針作為返回值賦值給第一步聲明的指針變量。消息郵箱初始化函數(shù)有一個參數(shù),應(yīng)該設(shè)置為空指針,表示消息郵箱為空。

Mbox_Task_LED1 = OSMboxCreate((void *)0);

步驟3:在任務(wù)里設(shè)置等待消息函數(shù),當(dāng)這個任務(wù)執(zhí)行到這句話的時候,系統(tǒng)會把這個任務(wù)掛起,等待有消息的發(fā)送。這個函數(shù)里有3個變量,第一個參數(shù)是指等待的是哪個消息郵箱,第二個參數(shù)是指等待時間單位為系統(tǒng)心跳,0指無時間期限的等待,第三個參數(shù)為返回的錯誤類型。

OSMboxPend(Mbox_Task_LED1,0,&err);

步驟4:在其他的任務(wù)里或者中斷服務(wù)程序里設(shè)置發(fā)送消息函數(shù),需要注意的是,這個函數(shù)并不會引起系統(tǒng)調(diào)度,所以如果把它放在中斷服務(wù)函數(shù)里的話就要去中斷里的內(nèi)容盡量簡短,以保證消息發(fā)送出去后,能進來快的進行系統(tǒng)調(diào)度讓消息接受函數(shù)相應(yīng)。在這個函數(shù)里有2個參數(shù),第一個參數(shù)為要發(fā)送給哪個消息郵箱,第二個參數(shù)為發(fā)送的數(shù)據(jù)的地址。在這里其實并沒有真實的數(shù)據(jù),只是把發(fā)送的地址用了一個非空地址,這個地址及其指向的數(shù)據(jù)都沒有任何意義,也不需要進行任何的讀寫操作,只是傳遞一個消息到相應(yīng)的等待函數(shù),以解除對應(yīng)任務(wù)的掛起狀態(tài)。

OSMboxPost(Mbox_Task_LED1,(void *)1);

下面看下具體的代碼:
步驟2和步驟3:

void Task_LED1(void* p_arg)
{
(void) p_arg ;

Mbox_Task_LED1 = OSMboxCreate((void *)0); // 創(chuàng)建消息郵箱,初值為空指針
while(1)
{
OSMboxPend(Mbox_Task_LED1,0,&err); // 等待郵箱的消息

LED1_HIGH;
OSTimeDlyHMSM(0,0,1,0);
LED1_LOW;
OSTimeDlyHMSM(0,0,1,0); // 延時,用來給其他任務(wù)留有運行的時間
}
}

步驟4:

void Interrupt_Handle_KEY3(void)
{
OSIntEnter();

// 在中斷服務(wù)函數(shù)里如果調(diào)用ucos系統(tǒng)函數(shù)的話就必須加上進中斷系統(tǒng)函數(shù)出去的時候要加上出中斷系統(tǒng)函數(shù)

OSMboxPost(Mbox_Task_LED1,(void *)1);

// 發(fā)送郵箱消息,這個函數(shù)并不會引起系統(tǒng)調(diào)度,所以中斷服務(wù)函數(shù)一定要簡潔。
EXTI_ClearITPendingBit(EXTI_Line3); // 清除標(biāo)志位

OSIntExit();
}

=======================================================================================================
下面說下傳遞一個真實的變量,步驟和上面是一樣的,只不過在步驟3和步驟4的地方會有對變量的轉(zhuǎn)換。代碼如下:
步驟2和步驟3:

void Task_LED1(void* p_arg)
{
unsigned char num ;
unsigned char pp;
(void) p_arg ;

Mbox_Task_LED1 = OSMboxCreate((void *)0); // 創(chuàng)建消息郵箱,初值為空指針
while(1)
{
num = *(unsigned char *)OSMboxPend(Mbox_Task_LED1,0,&err); // 等待郵箱的消息
pp = num; // 這個變量用于仿真時數(shù)據(jù)監(jiān)測
while(pp--)
{
LED1_HIGH;
OSTimeDlyHMSM(0,0,0,200);
LED1_LOW;
OSTimeDlyHMSM(0,0,0,200);
}
}
}

步驟4:

void Interrupt_Handle_KEY3(void)
{
OSIntEnter();

// 在中斷服務(wù)函數(shù)里如果調(diào)用ucos系統(tǒng)函數(shù)的話就必須加上進中斷系統(tǒng)函數(shù)出去的時候要加上出中斷系統(tǒng)函數(shù)

OSMboxPost(Mbox_Task_LED1,(void *)&Num);

// 發(fā)送郵箱消息,這個函數(shù)并不會引起系統(tǒng)調(diào)度,所以中斷服務(wù)函數(shù)一定要簡潔。
EXTI_ClearITPendingBit(EXTI_Line3); // 清除標(biāo)志位

OSIntExit();
}

如步驟4紅色注釋部分,在發(fā)送的時候把一個具體的變量取地址,并且強制轉(zhuǎn)換為一個無定義變量的指針;在步驟3紅色注釋部分,在等待函數(shù)外部首先進行的時候變量類型的轉(zhuǎn)換,轉(zhuǎn)換成一個無符號字符型變量的指針,然后在進行間指操作,把地址里的數(shù)據(jù)取出來,最后賦值給函數(shù)的臨時變量進行使用。				   


關(guān)鍵詞: STM32uCOSII消息郵

評論


技術(shù)專區(qū)

關(guān)閉