上次看到一位博主写信号量可以作为二值信号输出,如果仅用已有的函数去实现,有点令人费解。他的意思是想把信号量的用法发扬光大,但怎么实现,他没有说。
为了一个0和1,用了那么多变量参与,uCOSii也有它自己的道理,它就是想实现模块化程序设计,可以将任务分工细化,多人合作开发。浪费一点存储空间是值得的。
uCOSii信号量用作0和1输出时,需要在信号量的基础上,再创建两个函数,才可以实现二值信号输出。
1、直接设置信号量计数值实现0和1输出
//函数功能:设置信号量计数器
INT16U SetSemaphoreCounter(OS_EVENT *pevent,u8 x)
{
INT16U cnt;
#if OS_CRITICAL_METHOD == 3u
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0)
{//信号量事件指针为0
return (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM)
{//事件类型不是信号量事件类型
return (0u);
}
OS_ENTER_CRITICAL(); //进入临界区(无法被中断打断),需要定义cpu_sr变量
pevent->OSEventCnt=x; //设置计数器值
cnt=pevent->OSEventCnt;//读取当前信号量的计数器值
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
return (cnt);/*返回信号量计数值,Return semaphore count*/
}
2、直接读取信号量计数器值
//函数功能:读取信号量计数器
INT16U GetSemaphoreCounter(OS_EVENT *pevent)
{
INT16U cnt;
#if OS_CRITICAL_METHOD == 3u
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0)
{//信号量事件指针为0
return (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM)
{//事件类型不是信号量事件类型
return (0u);
}
OS_ENTER_CRITICAL(); //进入临界区(无法被中断打断),需要定义cpu_sr变量
cnt = pevent->OSEventCnt;//读取信号量的计数器值
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
return (cnt);/*返回信号量计数值,Return semaphore count*/
}
3、应用举例
#include "SendSemaphore_Task.h"
#include "delay.h"
#include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "My_Task_Priority.h"
const char SendSemaphore_Task_rn_REG[]="\r\n";
const char SendSemaphore_Task1_REG[]="SendSemaphore_Task:1";
const char SendSemaphore_Task0_REG[]="SendSemaphore_Task:0";
void SendSemaphore_Task(void *pdata);
INT16U SetSemaphoreCounter(OS_EVENT *pevent,u8 x);
INT16U GetSemaphoreCounter(OS_EVENT *pevent);
//函数功能:读取信号量计数器
INT16U GetSemaphoreCounter(OS_EVENT *pevent)
{
INT16U cnt;
#if OS_CRITICAL_METHOD == 3u
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0)
{//信号量事件指针为0
return (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM)
{//事件类型不是信号量事件类型
return (0u);
}
OS_ENTER_CRITICAL(); //进入临界区(无法被中断打断),需要定义cpu_sr变量
cnt = pevent->OSEventCnt;//读取信号量的计数器值
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
return (cnt);/*返回信号量计数值,Return semaphore count*/
}
//函数功能:设置信号量计数器
INT16U SetSemaphoreCounter(OS_EVENT *pevent,u8 x)
{
INT16U cnt;
#if OS_CRITICAL_METHOD == 3u
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0)
{//信号量事件指针为0
return (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM)
{//事件类型不是信号量事件类型
return (0u);
}
OS_ENTER_CRITICAL(); //进入临界区(无法被中断打断),需要定义cpu_sr变量
pevent->OSEventCnt=x; //设置计数器值
cnt=pevent->OSEventCnt;//读取当前信号量的计数器值
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
return (cnt);/*返回信号量计数值,Return semaphore count*/
}
//SendSemaphore_Task任务
void SendSemaphore_Task(void *pdata)
{
while(1)
{
OSTimeDlyHMSM(0,0,0,1000);//延时1000ms
SetSemaphoreCounter(SemaphoreEventPointer,1);//信号量置1输出
printf("%s",SendSemaphore_Task_rn_REG);
printf("%s",SendSemaphore_Task1_REG);
OSTimeDlyHMSM(0,0,0,1000);//延时1000ms
SetSemaphoreCounter(SemaphoreEventPointer,0);//信号量置0输出
printf("%s",SendSemaphore_Task_rn_REG);
printf("%s",SendSemaphore_Task0_REG);
}
}
#include "ReceiveSemaphore_Task.h"
#include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "SendSemaphore_Task.h"
#include "My_Task_Priority.h"
void ReceiveSemaphore_Task(void *pdata);
const char ReceiveSemaphore_Task_rn_REG[]="\r\n";
const char ReceiveSemaphore_Task_REG[]="ReceiveSemaphore_Task:";
//ReceiveSemaphore_Task任务
void ReceiveSemaphore_Task(void *pdata)
{
u16 cnt;
while(1)
{
接收信号量开始
cnt=GetSemaphoreCounter(SemaphoreEventPointer);
// cnt=OSSemAccept(SemaphoreEventPointer);
//接收信号量,返回值大于0,表示收到信号量
if(cnt)//读到信号量
{
printf("%s",ReceiveSemaphore_Task_rn_REG);
printf("%s",ReceiveSemaphore_Task_REG);
printf("%u",cnt );//打印信号计数器值
printf("%s",ReceiveSemaphore_Task_rn_REG);
}
else
{
printf("%s",ReceiveSemaphore_Task_rn_REG);
printf("%s",ReceiveSemaphore_Task_REG);
printf("%u",cnt );//打印信号计数器值
printf("%s",ReceiveSemaphore_Task_rn_REG);
}
接收信号量结束
OSTimeDlyHMSM(0,0,0,1000);//延时1000ms
}
}