ucos-ii学习笔记——信号量的原理及使用

发布者:DreamySerenity最新更新时间:2015-08-18 来源: eefocus关键字:ucos-ii  学习笔记  信号量 手机看文章 扫描二维码
随时随地手机看文章
Created on: 2012-10-7

      Author: zhang bin

 

学习笔记

for ucos-ii  PC

redesigned by zhang bin

2012-10-7

versions:V-0.1

All Rights Reserved

 

 

 

 

#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;   //信号量,互斥信号量 实质上就是一个标志位,是一个全局变量,来标志共享资源的访问情况

//这样,当已经有任务访问共享资源时,其他的任务就不能访问,知道该资源未被访问,其他的任务才可以进行访问

//注意这两个信号量的区别和使用情况

 

 

 

 

OS_STK        StartTaskStk[TASK_STK_SIZE];   //定义任务堆栈区

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); //在主函数中创建信号量 返回值为创建的信号量指针,参数是信号量的计数器的值

//用该参数对信号量计数器OSEventCnt进行初始化

//1即代表只创建一个信号量,代表信号量用于对共享资源的访问(例如,把它当做二值信号量使用),详见P166

 

    OSInit();                                              

    PC_DOSSaveReturn();                                    

    PC_VectSet(uCOS, OSCtxSw);                             

    

    OSTaskCreate(StartTask,(void *)0, &StartTaskStk[TASK_STK_SIZE 1], 0); //创建起始函数

    

    OSStart();      

}

 

void  StartTask(void *pdata)

{

#if OS_CRITICAL_METHOD ==        

    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); //创建任务函数

OSTaskCreate(YouTask,(void *)0, &YouTaskStk[TASK_STK_SIZE 1], 2); //创建任务函数

 

for (;;)

    {

     //如果恩下ESC键,则退出UC/OS-II

        if (PC_GetKey(&key) == TRUE)

                             

            if (key == 0x1B) 

                                        

                PC_DOSReturn();                            

            }

        }

        OSTimeDlyHMSM(0,0,3,0);                         

    }

}

 

//MyTask的函数代码

void  MyTask(void *pdata)

{

#if OS_CRITICAL_METHOD ==        

    OS_CPU_SR  cpu_sr;

#endif

   

    pdata pdata;    

    for (;;)

    {

     OSSemPend(Fun_Semp,0,&err);   //请求信号量 参数Fun_Semp是信号量指针  0那一项是等待时限timeout,0表示无限等待

     //err表示错误信息

    

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

 

Fun(7,y);  //调用Fun函数

 

OSSemPost(Fun_Semp);    //发送信号量 释放信号量,函数的参数Fun_Semp代表信号量的指针

 

        OSTimeDlyHMSM(0,0,1,0);  

    }

}

 

void  YouTask(void *pdata)

{

#if OS_CRITICAL_METHOD ==        //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);   //调用FUN函数

OSSemPost(Fun_Semp);   //释放信号量

 

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

    }

}

 

//公共的函数Fun的代码

void Fun(INT8U x,INT8U y)

{

PC_DispStr(x,y,"  Calling FUN()",DISP_BGND_BLACK+DISP_FGND_WHITE); //显示字符串,表示调用了Fun函数

}

 

//创建信号量时,用的参数为1,即Fun_Semp=OSSemCreate(1); ,只创建了一个信号量,这种情况一般是信号量用于对

//共享资源的访问(例如,可以把它当做二值信号量使用)

 

 

//在上面的程序中,当MyTask运行时,先请求获得了信号量,对共享资源Fun函数进行访问,由于只创建了一个信号量,

//所以在MyTask的访问期间,即使任务YouTask也进行申请信号量,此时OSEventCnt是值已经为0了,所以会把任务

//YouTask列入任务等代表OSEventTbl[]中,使任务处于等待状态。

//只有等MyTask对Fun函数访问完成了,调用OSSemPost(Fun_Semp);释放了信号量,该释放信号量的函数会先检查任务等待

//表中是否还有等待信号量的任务,如果有,则使任务进入就绪态后,调用调度器OS_Sched()引发一次任务调度,去运行等待

//任务列表中优先级最高的任务。如果没有,则就把信号量计数器OSSemCnt加1.

//所以任务YouTask要想访问Fun()函数,必须等到任务MyTask对Fun访问完毕,释放了信号量之后,才能访问,反之亦然

//所以由上面可以看出,只创建一个信号量,即OSSemCreate(1);,作用就相当于使用一个二值信号量,标志共享资源是否正在

//被访问

//看懂了上面的分析,也就可以解释实验现象了,由于YouTask等待2s,MyTask等待1s,所以有可能在MyTask访问Fan函数期间,YouTask

//也来访问(也有可能是反过来),但是由于信号量已经被MyTask占用了,所YouTask只好等待,MyTask使用完了,释放了信号量,YouTask才能正常使用Fun函数

//这样也就解决了多任务对共享资源的使用的问题,使任务之间得到了同步

 

//要仔细分析信号量工作的原理,把上面的内容看懂了,基本上也就可以使用信号量了

关键字:ucos-ii  学习笔记  信号量 引用地址:ucos-ii学习笔记——信号量的原理及使用

上一篇:ucos-ii学习笔记——消息邮箱的原理及使用
下一篇:ucos-ii学习笔记——首个多任务程序的创建

推荐阅读最新更新时间:2024-03-16 14:29

XMEGA128学习笔记6-实时时钟RTC
Xmega128的RTC实际上就是16位定时器,它的框图如图所示。时钟来源有两种:1是32KHZ,2是1KHZ。能够通过10位预分频,进一步得到低速频率。图中Period表示周期,也就是最多计数值。Compare是比较值,匹配时能够触发中断。今天我就用RTC的匹配中断功能,进行1s报警闪烁LED0。 第一步:打开CVARV,新建一个工程,首先使能低级中断: 第二步:设置LED0端口输出。 第三步:选择时钟源,开启RTC比较中断。 第四步:生成代码,编译下载。 在RTC匹配中断函数中加入以下代码: // RTC compare interrupt service routine interrupt voi
[单片机]
XMEGA128<font color='red'>学习</font><font color='red'>笔记</font>6-实时时钟RTC
STM32之GPIO学习笔记
复位后,调试引脚处于复用功能上拉/下拉状态: PA15:JTDI处于上拉状态 PA14:JTCK/SWCLK处于下拉状态 PA13:JTMS/SWDAT处于下拉状态 PB4:NJTRST处于上拉状态 PB3:JTDO处于浮空状态
[单片机]
STM32之GPIO<font color='red'>学习</font><font color='red'>笔记</font>
MSP430F5529学习笔记(一)——点灯|IO输出
开始学习和了解TI公司旗下的一款低功耗MCU芯片——MSP430F5529,根据了解该单片机可用多种方式编写,例如大家常用的IAR,CCS,甚至你可以用KEIL和VScode配置环境进行代码的烧写,当然也有相对无脑的Energia可供选择。 以上分别为部分可编译MSP430F5529的编译器,本次学习我们将在MSP430F5529开发板平台为基础进行,采用CCS作为基础进行学习,想快速上手的朋友可以使用energia(类似arduino的编译方式)。 在所有的单片机学习过程中都逃不过点灯,点灯是基础的IO口电平输出的经典案例,通过它可以了解基本的单片机IO口的输出电平方式,本着万物皆可点灯的理念,首先进行点灯实验。
[单片机]
MSP430F5529<font color='red'>学习</font><font color='red'>笔记</font>(一)——点灯|IO输出
MSP430Ware学习笔记 UART SMCLK 115200-8-N-1
1.初始化UART0之前需要先初始化ACLK、SMCLK和MCLK。示例代码中使用XT1,ACLK为32768,SMCLK和MCLK约为8MHZ。 2.UART的时钟可以参考ACLK或者SMCLK,本例参考SMCLK。波特率提高至115200 3.MSP430波特率的产生有两种模式,低频波特率产生和过采样波特率产生。代码中使用过采样波特率产生。其实,两种模式可以达到相似的效果。 4.代码的开头调用了stdio,在函数中宏重写了putchar函数,定向到UART单字节输出。 5.代码初始化之后输出 Hello MSP430Ware,随后直接反射串口接收到的数据,例如发送123456即返回123456. #include i
[单片机]
ARM Cortex-M3 学习笔记(4-6)
最近在学ARM Cortex-M3,找了本号称很经典的书 An Definitive Guide to The ARM Cortex-M3 在看。这个系列学习笔记其实就是在学习这本书的过程中做的读书笔记。 对内存的互斥访问 Cortex-M3 中提供了三对用于互斥访问的内存的指令,分别是:LDREX/STREX, LDREXH/STREXH, LDREXB/STREXB,这三对指令分别对应于字、半字、字节 的取出与写入。 LDREX 的基本指令格式为: LDREX Rxf, 这条指令与LDR Rxf, 的作用是相同的,唯一的区别是这条指令还会通知内核对它所访问的内存空间特殊关照。如何特殊关照,在STREX 指令执行时显现出
[单片机]
STM32 CAN总线通信学习笔记(一)
一、CAN总线简介 CAN 是控制器局域网络(Controller Area Network, CAN)的简称。CAN采用数据块编码的方式,数据块根据帧的类型,能够让挂载在总线上的不同节点接收到相同的数据,再根据每个节点的配置对信息进行选择性处理(处理or丢弃)。CAN总线具有以下特点: 1. 多主控制 在总线空闲时,所有的单元都可以发送消息;具有CSMA/CA机制,即最先访问总线的单元可获得发送权;多个单元同时发送消息时,优先级高的标志(ID)单元可获得发送权,其中ID并不是发送的目的地址,而是表示访问总线的消息的优先级,仲裁机制会对消息ID的每个位继续比较,仲裁为高优先级的单元可继续发送消息,仲裁失败的单元则停止发送而进行
[单片机]
STM32 CAN总线通信<font color='red'>学习</font><font color='red'>笔记</font>(一)
uC/OS-II在51单片机上的移植1
引言:随着各种应用电子系统的复杂化和系统实时性需求的提高,并伴随应用软件朝着系统化方向发展的加速,在16位/32位单片机中广泛使用了嵌入式实时操作系统。然而实际使用中却存在着大量8位单片机,从经济性考虑,对某些应用场合,在8位MCU上使用操作系统是可行的。从学习操作系统角度,uC/OS-II for 51即简单又全面,学习成本低廉,值得推广。 结语: C/OS-II具有免费、简单、可靠性高、实时性好等优点,但也有缺乏便利开发环境等缺点,尤其不像商用嵌入式系统那样得到广泛使用和持续的研究更新。但开放性又使得开发人员可以自行裁减和添加所需的功能,在许多应用领域发挥着独特的作用。当然,是否在单片机系统中嵌入 C/OS-II应视所开发的项目
[单片机]
142 条 STM32 学习笔记(必收藏)
1、AHB系统总线分为APB1(36MHz)和APB2(72MHz),其中2 1,意思是APB2接高速设备。 2、Stm32f10x.h相当于reg52.h(里面有基本的位操作定义),另一个为stm32f10x_conf.h专门控制外围器件的配置,也就是开关头文件的作用 3、HSE Osc(High Speed External Oscillator)高速外部晶振,一般为8MHz,HSI RC(High Speed InternalRC)高速内部RC,8MHz 4、LSE Osc(Low Speed External Oscillator)低速外部晶振,一般为32.768KHz,LSI RC(Low Speed InternalR
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多精选电路图
换一换 更多 相关热搜器件
更多每日新闻
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved