7、uCOS-Ⅱ 信号量

时光怂恿深爱的人放手 提交于 2020-03-05 23:06:06

1、“信号量”为操作系统用于处理临界区问题和实现进程间同步提供了一种有效的机制。

在很多操作系统原理书中都提到了信号量的概念,常用P操作与V操作来表明信号量的行为。

PV操作的伪代码如下:

设s为一整数型变量: P操作:while( s==0); s--;

V操作:s++

 

 

2、例程代码

  1 /*****************************************************************************************************************************
  2 *
  3 *  文件名称:main.c
  4 *  文件功能:主函数
  5 *  文件说明:无
  6 *
  7 *****************************************************************************************************************************/
  8 /**********************************************************
  9 *
 10 *  头文件声明
 11 *  
 12 **********************************************************/
 13 
 14 #include "pbdata.h"
 15 
 16 
 17 
 18 
 19 
 20 
 21 /**********************************************************
 22 *
 23 *  调用函数声明
 24 *  
 25 **********************************************************/
 26 void RCC_Configuration(void);//时钟配置函数
 27 
 28 void  start_task(void *pdata);//开始任务函数
 29 
 30 
 31 
 32 
 33 
 34 /**********************************************************
 35 *
 36 *  主函数
 37 *  
 38 **********************************************************/
 39 int main(void)
 40 {
 41     Delay_Init();//延时函数初始化
 42     
 43     RCC_Configuration();//时钟配置
 44     
 45     LED_GPIO();//LED的GPIO引脚配置
 46     
 47     KEY_GPIO();//KEY的GPIO引脚配置
 48     
 49     
 50 /*操作系统的处理*/
 51     OSInit();//初始化UCOS操作系统
 52     led1_SEM=OSSemCreate(0);//建立LED1的信号量
 53     OSTaskCreate(
 54               start_task,  //指向任务代码的指针
 55               (void *)0,    //任务开始执行时,传递给任务参数的指针
 56               (OS_STK *) & START_TASK_STK[START_STK_SIZE-1],//分配给任务堆栈的栈顶指针
 57               START_TASK_PRIO//分配给任务的优先级
 58              );
 59     OSStart();//启动OS操作系统
 60     
 61     
 62     
 63     
 64 }
 65 
 66 
 67 
 68 /**********************************************************
 69 *
 70 *  函数名称:RCC_Configuration(void)
 71 *  函数功能:时钟配置
 72 *  输入参数:无
 73 *  输出参数:无
 74 *  函数说明:无
 75 *  
 76 **********************************************************/
 77 void  RCC_Configuration(void)
 78 {
 79     SystemInit();//系统初始化
 80     
 81     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//LED1对应GPIO时钟使能
 82     
 83     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//按键对应GPIO时钟使能
 84 }
 85 
 86 
 87 
 88 
 89 
 90 
 91 /**********************************************************
 92 *
 93 *  函数名称:start_task(void *pdata)
 94 *  函数功能:开始任务
 95 *  输入参数:*pdata
 96 *  输出参数:无
 97 *  函数说明:无
 98 *  
 99 **********************************************************/
100 void  start_task(void *pdata)
101 {
102    OS_CPU_SR  cpu_sr=0;
103     
104    pdata=pdata;//防止编译器报错
105     
106    OSStatInit();//初始化统计任务
107     
108    OS_ENTER_CRITICAL();//进入临界区,中断无法打断
109     
110 /*创建任务*/ 
111    /*LED1任务*/    
112    OSTaskCreate(
113               led1_task,  //指向任务代码的指针
114               (void *)0,    //任务开始执行时,传递给任务参数的指针
115               (OS_STK *) & LED1_TASK_STK[LED1_STK_SIZE-1],//分配给任务堆栈的栈顶指针
116               LED1_TASK_PRIO//分配给任务的优先级
117              );
118 
119     /*key任务*/    
120    OSTaskCreate(
121               key_task,  //指向任务代码的指针
122               (void *)0,    //任务开始执行时,传递给任务参数的指针
123               (OS_STK *) & KEY_TASK_STK[KEY_STK_SIZE-1],//分配给任务堆栈的栈顶指针
124               KEY_TASK_PRIO//分配给任务的优先级
125              );
126 
127    OSTaskSuspend(START_TASK_PRIO);//挂起开始任务
128     
129    OS_EXIT_CRITICAL();//退出临界区,可以被中断打断
130 
131 }
View Code
  1 /*****************************************************************************************************************************
  2 *
  3 *  文件名称:pbdata.c
  4 *  文件功能:自定义函数
  5 *  文件说明:无
  6 *
  7 *****************************************************************************************************************************/
  8 
  9 
 10 
 11 #include "pbdata.h"
 12 
 13 u8 dt=0;
 14 static u8  fac_us=0;//us延时倍乘数
 15 static u16 fac_ms=0;//ms延时倍乘数
 16 
 17 OS_EVENT* led1_SEM;
 18 
 19 /**********************************************************
 20 *
 21 *  函数名称:Delay_Init(void)    
 22 *  函数功能:初始化延时函数
 23 *  输入参数:无
 24 *  输出参数:无
 25 *  函数说明:当使用ucos的时候,此函数会初始化ucos的时钟节拍
 26 *            SYSTICK的时钟固定为HCLK时钟的1/8
 27 *            SYSCLK:系统时钟
 28 *  
 29 **********************************************************/
 30 void Delay_Init(void)     
 31 {
 32     u32 reload;
 33     SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);    //选择外部时钟,HCLK/8
 34     fac_us=SystemCoreClock/8000000;    //为系统时钟的1/8
 35      
 36     reload=SystemCoreClock/8000000;    //每秒钟的计数次数,单位为K   
 37     reload*=1000000/OS_TICKS_PER_SEC;//根据OS_TICKS_PER_SEC设定溢出事件,reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右
 38                                 
 39     fac_ms=1000/OS_TICKS_PER_SEC;// 代表ucos可以延时的最少单位
 40     SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;       //开启SYSTICK中断
 41     SysTick->LOAD=reload;     //每1/OS_TICKS_PER_SEC秒中断一次
 42     SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;       //开启SYSTICK    
 43 }                                    
 44 
 45 
 46 
 47 
 48 
 49 /**********************************************************
 50 *
 51 *  函数名称:delay_us(u32 nus)
 52 *  函数功能:延时微秒子程序
 53 *  输入参数:nus,  延时微秒数
 54 *  输出参数:无
 55 *  函数说明:无
 56 *            
 57 **********************************************************/
 58 void delay_us(u32 nus)
 59 {        
 60     u32 ticks;
 61     u32 told,tnow,tcnt=0;
 62     u32 reload=SysTick->LOAD;    //LOAD的值      
 63     ticks=nus*fac_us;             //需要的节拍数         
 64     tcnt=0;
 65     told=SysTick->VAL;            //刚进入时的计数器值
 66     while(1)
 67     {
 68         tnow=SysTick->VAL;    
 69         if(tnow!=told)
 70         {        
 71             if(tnow<told)tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了
 72             else tcnt+=reload-tnow+told;        
 73             told=tnow;
 74             if(tcnt>=ticks)break;//时间超过/等于要延时的事件,则退出
 75         }  
 76     };                                         
 77 }
 78 
 79 
 80 
 81 
 82 
 83 
 84 /**********************************************************
 85 *
 86 *  函数名称:delay_ms(u16 nms)
 87 *  函数功能:延时毫秒子程序
 88 *  输入参数:nms,  延时微秒数
 89 *  输出参数:无
 90 *  函数说明:无
 91 *            
 92 **********************************************************/
 93 void delay_ms(u16 nms)
 94 {    
 95     if(OSRunning==TRUE)//如果os已经在跑了   
 96     {          
 97         if(nms>=fac_ms)//延时的事件大于ucos的最少时间周期
 98         {
 99                OSTimeDly(nms/fac_ms);//ucos延时
100         }
101         nms%=fac_ms;                //ucos已经无法提供这么小的延时了,采用普通方式延时    
102     }
103     delay_us((u32)(nms*1000));    //普通方式延时,此时ucos无法启动调度
104 }
105 
106 
107 
108 
109 /**********************************************************
110 *
111 *  函数名称:delay(u32 nCount)
112 *  函数功能:普通不精确延时
113 *  输入参数:nCount,  延时时间长短
114 *  输出参数:无
115 *  函数说明:无
116 *            
117 **********************************************************/
118 void delay(u32 nCount)
119 {
120     for(;nCount!=0;nCount--);
121 }
View Code
 1 /*****************************************************************************************************************************
 2 *
 3 *  文件名称:pbdata.h
 4 *  文件功能:自定义函数的头文件声明
 5 *  文件说明:无
 6 *
 7 *****************************************************************************************************************************/
 8 
 9 
10 #ifndef _pbdata_H
11 #define _pbdata_H
12 
13 
14 
15 
16 
17 
18 /**********************************************************
19 *
20 *  需要引入的头文件
21 *  
22 **********************************************************/
23 #include "stm32f10x.h"
24 #include "includes.h"
25 #include "misc.h"
26 
27 #include "led.h"//LED相关头文件
28 #include "key.h"//key相关头文件
29 
30 
31 /**********************************************************
32 *
33 *  任务相关设置
34 *  
35 **********************************************************/
36 /*开始任务*/
37     #define  START_TASK_PRIO   9  //设置任务优先级
38     #define  START_STK_SIZE    64  //空间大小=64*4(字节)
39     static OS_STK  START_TASK_STK[START_STK_SIZE];//创建任务堆栈空间
40 
41 
42 /*LED1任务*/
43     #define  LED1_TASK_PRIO   6  //设置任务优先级
44     #define  LED1_STK_SIZE    64  //空间大小=64*4(字节)
45     static OS_STK   LED1_TASK_STK[LED1_STK_SIZE];//创建任务堆栈空间
46 
47 
48 /*key任务*/
49     #define  KEY_TASK_PRIO   5  //设置任务优先级
50     #define  KEY_STK_SIZE    64  //空间大小=64*4(字节)
51     static OS_STK   KEY_TASK_STK[KEY_STK_SIZE];//创建任务堆栈空间
52 
53 
54 
55 
56 
57 /**********************************************************
58 *
59 *  外部变量声明
60 *  
61 **********************************************************/
62 extern OS_EVENT* led1_SEM;
63 
64 
65 
66 /**********************************************************
67 *
68 *  子函数程序声明
69 *  
70 **********************************************************/
71 void delay(u32 nCount);//普通不精确延时
72 void Delay_Init(void);//延时函数初始化
73 void delay_us(u32 nus);//微秒延时
74 void delay_ms(u16 nms);//毫秒延时
75 
76 
77 
78 
79 #endif
View Code
 1 /*****************************************************************************************************************************
 2 *
 3 *  文件名称:led.c
 4 *  文件功能:led相关函数
 5 *  文件说明:无
 6 *
 7 *****************************************************************************************************************************/
 8 
 9 
10 
11 
12 #include "pbdata.h"
13 
14 
15 
16 /**********************************************************
17 *
18 *  函数名称:LED_GPIO(void)
19 *  函数功能:LED的GPIO配置
20 *  输入参数:无
21 *  输出参数:无
22 *  函数说明:无
23 *  
24 **********************************************************/
25 
26 void LED_GPIO(void)//GPIO初始化函数
27 {
28     GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO设置的结构体变量 
29     
30 /*LED1配置*/
31     /*结构体变量赋值*/
32     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;////引脚配置
33     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置频率
34     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
35 /*对应的GPIO初始化*/
36   GPIO_Init(GPIOB,&GPIO_InitStructure);
37 }
38 
39 
40 
41 
42 
43 
44 
45 /**********************************************************
46 *
47 *  函数名称:led1_task(void *pdata)
48 *  函数功能:led1任务处理函数
49 *  输入参数:*pdata
50 *  输出参数:无
51 *  函数说明:无
52 *  
53 **********************************************************/
54 
55 void  led1_task(void *pdata)
56 {
57      INT8U  err;
58     
59    pdata=pdata;//防止编译器报错
60 
61    while(1)
62    {
63          
64         OSSemPend(led1_SEM,0,&err);//等待LED1的信号量
65 
66     GPIO_SetBits(GPIOB,GPIO_Pin_5);//指定端口设置为高电平
67     
68     delay_ms(1000);//1s,delay,公共函数库中自己定义
69  
70     GPIO_ResetBits(GPIOB,GPIO_Pin_5);//指定端口设置低电平
71 
72     delay_ms(1000);//1s,delay,公共函数库中自己定义
73          
74     }
75 }
View Code
 1 /*****************************************************************************************************************************
 2 *
 3 *  文件名称:led.h
 4 *  文件功能:led相关函数的头文件
 5 *  文件说明:无
 6 *
 7 *****************************************************************************************************************************/
 8 
 9 
10 #ifndef _LED_H
11 #define _LED_H
12 
13 #include "pbdata.h"
14 
15 
16 void LED_GPIO(void);//LED的GIPO引脚配置
17 
18 void  led1_task(void *pdata);//LED1任务
19 
20 
21 
22 
23 #endif
View Code
 1 /*****************************************************************************************************************************
 2 *
 3 *  文件名称:key.c
 4 *  文件功能:按键处理函数头文件
 5 *  文件说明:无
 6 *
 7 *****************************************************************************************************************************/
 8 
 9 #include "pbdata.h"
10 
11 
12 
13 
14 
15 /**********************************************************
16 *
17 *  函数名称:KEY_GPIO(void)
18 *  函数功能:KEY的GPIO配置
19 *  输入参数:无
20 *  输出参数:无
21 *  函数说明:无
22 *  
23 **********************************************************/
24 void KEY_GPIO(void)//GPIO初始化函数
25 {
26     GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO设置的结构体变量 
27     
28 /*key配置*/
29     /*结构体变量赋值*/
30     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;////引脚配置
31     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置频率
32     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//上拉输入
33 /*对应的GPIO初始化*/
34 GPIO_Init(GPIOC,&GPIO_InitStructure);
35     
36 }
37 
38 
39 
40 /**********************************************************
41 *
42 *  函数名称:key_task(void *pdata)
43 *  函数功能:key任务处理函数
44 *  输入参数:*pdata
45 *  输出参数:无
46 *  函数说明: 不断查询4个按键,当查询到某个按键时,
47 *  
48 **********************************************************/
49 void  key_task(void *pdata)
50 {
51    pdata=pdata;//防止编译器报错
52 
53    while(1)
54    {
55 /*k1按下*/
56             if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==Bit_RESET)//如果按键K1按下
57             {
58                 delay_ms(20);//延时消抖
59                 if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==Bit_RESET)//如果按键K1确实按下
60                 {
61                     OSSemPost(led1_SEM);//发送led1信号量
62                 }
63             }
64             delay_ms(100);
65         }
66 }
View Code
 1 /*****************************************************************************************************************************
 2 *
 3 *  文件名称:key.h
 4 *  文件功能:按键处理函数头文件
 5 *  文件说明:无
 6 *
 7 *****************************************************************************************************************************/
 8 
 9 
10 #ifndef  _KEY_H
11 #define  _KEY_H
12 
13 #include "pbdata.h"
14 
15 
16 
17 void KEY_GPIO(void);//key的GPIO初始化
18 
19 void  key_task(void *pdata);//key的任务处理函数
20 
21 
22 #endif
View Code

 

 

 

3、例程工程下载:

 http://download.csdn.net/detail/a1181803348/8832369

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!