浅谈OSSemPost()和OSSemPend()



在ucos-II中,为了实现任务之间的同步,用到的同步机制有:信号量,邮箱和消息队列。其中这里我主要说下对信号量的使用经验。信号量在创建时,      调用OSSemCreate(INT16U cnt)函数。cnt为信号量的初始值。对cnt赋予不同的值,所起到的作用不同。如果Semp = OSSemCreate(0), 该信号量表示等待一个事件或者多个事件的发生。

      如果我们想对一个公共资源进行互斥访问,例如:如果我们想让两个任务Task1和Task2都可以调用Fun()函数,但不能同时调用,最好定义Semp = OSSemCreate(1),同理在各自的任务中都需要调用OSSemPend(Semp,0,&err)请求此信号量,如果可用,则调用Fun(),然后再调用OSSemPost(Semp)释放该信号量。这里就实现了一个资源的互斥访问。(注:初始化OSSemCreate(1),那么一个任务中有OSSemPend,那么可以执行,执行之后cnt==0,其他任务的OSSemPend无法获得sem,只能等待,除非任务一有OSSemPost,使其cnt++,这样其他任务的Pend可以执行。)同理,如果一个任务要等待n个事件发生后才能执行,则应定义为Semp = OSSemCreate(n)。然后在这n个任务分别运行时调用OSSemPost(Semp),直到这n个事件均发生后,这个任务才能运行。

OSSemCreate(cnt)赋初始值cnt,OSSemPend一次,cnt-- 一次,OSSemPost一次,cnt++一次。

1、OSSemCreate (0);

......

OS_EVENT *Fun_Semp;

......

Fun_Semp = OSSemCreate (0);

......

void  MyTask (void *pdata)
{

.....
    for (;;) 
                                             
        OSSemPend(Fun_Semp,0,&err); //请求信号量
   PC_DispStr(0,++y,  s1,  DISP_BGND_BLACK+DISP_FGND_WHITE );
        OSTimeDlyHMSM(0, 0, 1, 0);    //等待1秒
    }
}

......

void  YouTask (void *pdata)
{

......
    for (;;) 
             
  PC_DispStr(0,++y,  s2,  DISP_BGND_BLACK+DISP_FGND_WHITE );
  if(YouTaskRun==5)
       OSSemPost(Fun_Semp);  //发送信号量
  YouTaskRun++;            
        OSTimeDlyHMSM(0, 0, 2, 0);    //等待2秒
    }
}

在上例中,MyTask 一直在等待信号量,在信号量没有到来之前无法执行。只有在YouTask 运行了5次,YouTaskRun==5之后,OSSemPost(Fun_Semp);  //发送信号量,MyTask 才得以执行。如果按上例所示,MyTask 只能执行一次,因为YouTask 以后再也不可能使得YouTaskRun==5了。MyTask 也就因为无法得到信号量而不能运行。

2、OSSemCreate (1);

.....

OS_EVENT *Fun_Semp;

.....

Fun_Semp = OSSemCreate (1);

.....

void  MyTask (void *pdata)
{

..... 
    for (;;) 
                                             
        OSSemPend(Fun_Semp,0,&err); //请求信号量
   PC_DispStr(0,++y,  s1,  DISP_BGND_BLACK+DISP_FGND_WHITE );
   OSSemPost(Fun_Semp);  //发送信号量
        OSTimeDlyHMSM(0, 0, 1, 0);    //等待1秒
    }
}

void  YouTask (void *pdata)
{

    for (;;) 
                                             
        OSSemPend(Fun_Semp,0,&err); //请求信号量
   PC_DispStr(0,++y,  s2,  DISP_BGND_BLACK+DISP_FGND_WHITE );

   OSSemPost(Fun_Semp);  //发送信号量            
        OSTimeDlyHMSM(0, 0, 2, 0);    //等待2秒
    }
}

在上例中,MyTask、YouTask 都在 等待信号量,由于MyTask优先级高,首先得到信号量开始执行。此时YouTask 还在等待信号量。MyTask 执行完毕,OSSemPost(Fun_Semp);  //发送信号量。YouTask 得到信号量运行后发送信号量,如此反复

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include"..\ucos-ii\includes.h" /* uC/OS interface */ #include "..\ucos-ii\add\osaddition.h" #include "..\inc\drv.h" #include <string.h> #include <math.h> #pragma import(__use_no_semihosting_swi) // ensure no functions that use semihosting ///******************任务定义***************/// OS_STK Main_Stack[STACKSIZE*8]={0, }; //Main_Test_Task堆栈 void Main_Task(void *Id); //Main_Test_Task #define Main_Task_Prio 12 /**************已经定义的OS任务************* tcp监控任务 11 以太网物理层监控任务 8 触摸屏任务 9 键盘任务 10 lcd刷新任务 59 系统任务 1 *****************************************************/ ///*****************事件定义*****************/// OS_EVENT *Nand_Rw_Sem; //Nand_Flash读写控制权旗语 //and you can use it as folloeing: // Nand_Rw_Sem=OSSemCreate(1); //创建Nand-Flash读写控制权旗语,初值为1满足互斥条件// // OSSemPend(Nand_Rw_Sem,0,&err); // OSSemPost(Nand_Rw_Sem); OS_EVENT *Uart_Rw_Sem; //Uart读写控制权旗语 //and you can use it as folloeing: // Uart_Rw_Sem=OSSemCreate(1); //创建Uart读写控制权旗语,初值为1满足互斥条件// // OSSemPend(Uart_Rw_Sem,0,&err); // OSSemPost(Uart_Rw_Sem); ////////////////////////////////////////////////////////// void initOSGUI() //初始化操作系统的图形界面 { initOSMessage(); initOSList(); initOSDC(); initOSCtrl(); initOSFile(); } ///////////////////////////////////////////////////// // Main function. // ////////////////////////////////////////////////////

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值