找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4240|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

ucos-ii學(xué)習(xí)筆記—信號量的原理及使用

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:140343 發(fā)表于 2016-9-25 10:42 | 只看該作者 回帖獎勵 |倒序?yàn)g覽 |閱讀模式


#include "INCLUDES.h"

#define  TASK_STK_SIZE        512                 

char *s1="MyTask";
char *s2="YouTask";
INT8U err;   //定義一個錯誤信息
INT8U y=0;
OS_EVENT *Fun_Semp;    //聲明信號量  是事件控制塊ECB類型的
//注意,前面有一個例子2 定義了互斥信號量,定義如下
//BOOLEAN   ac_key;   //信號量,互斥信號量 實(shí)質(zhì)上就是一個標(biāo)志位,是一個全局變量,來標(biāo)志共享資源的訪問情況
//這樣,當(dāng)已經(jīng)有任務(wù)訪問共享資源時,其他的任務(wù)就不能訪問,知道該資源未被訪問,其他的任務(wù)才可以進(jìn)行訪問
//注意這兩個信號量的區(qū)別和使用情況

OS_STK        StartTaskStk[TASK_STK_SIZE];   //定義任務(wù)堆棧區(qū)
OS_STK        MyTaskStk[TASK_STK_SIZE];
OS_STK        YouTaskStk[TASK_STK_SIZE];

void  Fun(INT8U x,INT8U y);

void  StartTask(void *data);
void  MyTask(void *data);                  
void  YouTask(void *data);

void  main (void)
{
Fun_Semp=OSSemCreate(1); //在主函數(shù)中創(chuàng)建信號量,返回值為創(chuàng)建的信號量指針,參數(shù)是信號量的計(jì)數(shù)器的值
//用該參數(shù)對信號量計(jì)數(shù)器OSEventCnt進(jìn)行初始化
//1即代表只創(chuàng)建一個信號量,代表信號量用于對共享資源的訪問(例如,把它當(dāng)做二值信號量使用),詳見P166
    OSInit();                                             
    PC_DOSSaveReturn();                                    
    PC_VectSet(uCOS, OSCtxSw);                             

    OSTaskCreate(StartTask,(void *)0, &StartTaskStk[TASK_STK_SIZE - 1], 0); //創(chuàng)建起始函數(shù)

    OSStart();      
}

void  StartTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3        
    OS_CPU_SR  cpu_sr;
#endif
    INT16S        key;            
    pdata = pdata;        
    OS_ENTER_CRITICAL();
    PC_VectSet(0x08, OSTickISR);                           
    PC_SetTickRate(OS_TICKS_PER_SEC);                     
    OS_EXIT_CRITICAL();
    OSStatInit();                                          

    OSTaskCreate(MyTask,(void *)0, &MyTaskStk[TASK_STK_SIZE - 1], 1); //創(chuàng)建任務(wù)函數(shù)
OSTaskCreate(YouTask,(void *)0, &YouTaskStk[TASK_STK_SIZE - 1], 2); //創(chuàng)建任務(wù)函數(shù)

for (;;)
    {
     //如果恩下ESC鍵,則退出UC/OS-II
        if (PC_GetKey(&key) == TRUE)
         {                     
            if (key == 0x1B)
            {                             
                PC_DOSReturn();                           
            }
        }
        OSTimeDlyHMSM(0,0,3,0);                        
    }
}

//MyTask的函數(shù)代碼
void  MyTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3        
    OS_CPU_SR  cpu_sr;
#endif

    pdata = pdata;   
    for (;;)
    {
     OSSemPend(Fun_Semp,0,&err);   //請求信號量,參數(shù)Fun_Semp是信號量指針,0那一項(xiàng)是等待時限timeout,0表示無限等待
     //err表示錯誤信息

PC_DispStr(0,++y,s1,DISP_BGND_BLACK+DISP_FGND_WHITE);  //顯示MyTask字符串

Fun(7,y);  //調(diào)用Fun函數(shù)

OSSemPost(Fun_Semp);    //發(fā)送信號量 釋放信號量,函數(shù)的參數(shù)Fun_Semp代表信號量的指針
        OSTimeDlyHMSM(0,0,1,0);  
    }
}

void  YouTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3        //Allocate storage for CPU status register
    OS_CPU_SR  cpu_sr;
#endif

pdata=pdata;
for (;;)
{
OSSemPend(Fun_Semp,0,&err);    //請求信號量
PC_DispStr(0,++y,s2,DISP_BGND_BLACK+DISP_FGND_WHITE);
Fun(7,y);   //調(diào)用FUN函數(shù)
OSSemPost(Fun_Semp);   //釋放信號量

        OSTimeDlyHMSM(0,0,2,0);    //等待2s               
    }
}

//公共的函數(shù)Fun的代碼
void Fun(INT8U x,INT8U y)
{
PC_DispStr(x,y,"  Calling FUN()",DISP_BGND_BLACK+DISP_FGND_WHITE); //顯示字符串,表示調(diào)用了Fun函數(shù)
}
//創(chuàng)建信號量時,用的參數(shù)為1,即Fun_Semp=OSSemCreate(1); ,只創(chuàng)建了一個信號量,這種情況一般是信號量用于對
//共享資源的訪問(例如,可以把它當(dāng)做二值信號量使用)
//在上面的程序中,當(dāng)MyTask運(yùn)行時,先請求獲得了信號量,對共享資源Fun函數(shù)進(jìn)行訪問,由于只創(chuàng)建了一個信號量,
//所以在MyTask的訪問期間,即使任務(wù)YouTask也進(jìn)行申請信號量,此時OSEventCnt是值已經(jīng)為0了,所以會把任務(wù)
//YouTask列入任務(wù)等代表OSEventTbl[]中,使任務(wù)處于等待狀態(tài)。
//只有等MyTask對Fun函數(shù)訪問完成了,調(diào)用OSSemPost(Fun_Semp);釋放了信號量,該釋放信號量的函數(shù)會先檢查任務(wù)等待
//表中是否還有等待信號量的任務(wù),如果有,則使任務(wù)進(jìn)入就緒態(tài)后,調(diào)用調(diào)度器OS_Sched()引發(fā)一次任務(wù)調(diào)度,去運(yùn)行等待
//任務(wù)列表中優(yōu)先級最高的任務(wù)。如果沒有,則就把信號量計(jì)數(shù)器OSSemCnt加1.
//所以任務(wù)YouTask要想訪問Fun()函數(shù),必須等到任務(wù)MyTask對Fun訪問完畢,釋放了信號量之后,才能訪問,反之亦然
//所以由上面可以看出,只創(chuàng)建一個信號量,即OSSemCreate(1);,作用就相當(dāng)于使用一個二值信號量,標(biāo)志共享資源是否正在
//被訪問
//看懂了上面的分析,也就可以解釋實(shí)驗(yàn)現(xiàn)象了,由于YouTask等待2s,MyTask等待1s,所以有可能在MyTask訪問Fan函數(shù)期間,YouTask
//也來訪問(也有可能是反過來),但是由于信號量已經(jīng)被MyTask占用了,所YouTask只好等待,MyTask使用完了,釋放了信號量,YouTask才能正常使用Fun函數(shù)
//這樣也就解決了多任務(wù)對共享資源的使用的問題,使任務(wù)之間得到了同步
//要仔細(xì)分析信號量工作的原理,把上面的內(nèi)容看懂了,基本上也就可以使用信號量了






分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表