通过LED0、LED1发光二极管的闪烁显示来体现信号量的效果:
已知 设定信号量初值为0,LED0任务请求信号量(信号量+1),LED1发送信号量(信号量-1)
变量定义: OS_EVENT *pSemaphore;
INT8U err;
对应函数: pSemaphore = OSSemCreate(0); //创建信号量,初值为0;
OSSemPost(pSemaphore); //请求信号量
OSSemPend(pSemaphore, 0, &err); //发送信号量
实验一:
LED0:
{ LED0=!LED0; delay_ms(1000); }
LED1:
{ LED1=!LED1; delay_ms(500); }
现象:LED0、LED1同时闪烁,延时1000ms;
解释:
由于当LED1到达500ms延时时,由于信号量值为0,所以发送信号量失败,等到延时达到1000ms时,由于LED0请求信号量致使信号量值为1,此时可以发送信号量,所以在LED0=!LED0时,LED1!=LED1,出现的效果就是同时闪烁。
实验二:
LED0:
{ LED0=!LED0; delay_ms(500); }
LED1:
{ LED1=!LED1; delay_ms(1000); }
现象:LED0闪烁周期为500ms*2;LED1闪烁周期为1000ms*2;信号量不能体现影响。
解释:
当LED0到达500ms延时时,由于LED0为请求信号量,信号量+1,所以请求成功并且信号量值+1,所以当到达1000ms时,LED1发送信号量时初值不为0,所以也可以成功。
附:完整代码(库函数除外)
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "includes.h"
//开始任务
#define START_TASK_PRIO 10 //优先级
#define START_STK_SIZE 64 //任务堆栈大小
OS_STK START_TASK_STK[START_STK_SIZE]; //任务堆栈
void start_task(void *pdata);
//LED0任务
#define LED0_TASK_PRIO 7
#define LED0_STK_SIZE 64
OS_STK LED0_TASK_STK[LED0_STK_SIZE];
void led0_task(void *pdata);
//LED1任务
#define LED1_TASK_PRIO 6
#define LED1_STK_SIZE 64
OS_STK LED1_TASK_STK[LED1_STK_SIZE];
void led1_task(void *pdata);
//变量定义
OS_EVENT *pSemaphore;
INT8U err;
int main(void)
{
Stm32_Clock_Init(9);
delay_init(72);
LED_Init();
LED_Init();
OSInit();
pSemaphore = OSSemCreate(0); //declare
OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO );
OSStart();
}
void start_task(void *pdata)
{
OS_CPU_SR cpu_sr=0;
pdata = pdata;
OS_ENTER_CRITICAL();//进入临界区(避免被中断打断)
OSTaskCreate(led0_task,(void *)0,(OS_STK*)&LED0_TASK_STK[LED0_STK_SIZE-1],LED0_TASK_PRIO);
OSTaskCreate(led1_task,(void *)0,(OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO);
OSTaskSuspend(START_TASK_PRIO);//挂起起始任务
OS_EXIT_CRITICAL(); //退出临界区
}
//LED0
void led0_task(void *pdata)
{
while(1)
{
OSSemPost(pSemaphore);
LED0=!LED0;
delay_ms(1000);
};
}
//LED1
void led1_task(void *pdata)
{
while(1)
{
OSSemPend(pSemaphore, 0, &err);
LED1=!LED1;
delay_ms(500);
};
}