UCOSIII 信号量 的使用和区别
1. 一般信号量 共享资源 同时访问
定义 : OS_SEM MY_SEM
创建 :OSSemCreate( (OS_SEM *) &MY_SEM,
(CPU_CHAR*) "MY_SEM",
(OS_SEM_CTR)1, // 重要 创建1个信号量 0 的话必须先发送一个信号量 才能请求
(OS_ERR* )&err);
使用 :OSSemPend("信号量地址",“超时tick 默认是5ms的倍数”,OS_OPT_PEND_BLOCKING (没请求到信号量任务挂起),0(时间戳),&err)
OS_OPT_PEND_NON_BLOCKING (没请求到信号量任务不挂起)
OS_OPT_PEND_BLOCKING (没请求到信号量任务挂起)
释放信号量 OSSemPost (&MY_SEM,OS_OPT_POST_1,&err); //发送信号量
* OS_OPT_POST_1 POST and ready only the highest priority task waiting on semaphore (if tasks are waiting). 仅等待的最高级别的一个任务
* OS_OPT_POST_ALL POST to ALL tasks that are waiting on the semaphore 所有等待该信号量的任务
* OS_OPT_POST_NO_SCHED Do not call the scheduler 不引起任务调度
* Note(s): 1) OS_OPT_POST_NO_SCHED can be added with one of the other options.
2,任务同步信号量
创建 :OSSemCreate( (OS_SEM *) &MY_SEM,
(CPU_CHAR*) "MY_SEM",
(OS_SEM_CTR)0, // 重要
(OS_ERR* )&err);
发送 信号量 :-----》OSSemPost(&SYNC_SEM,OS_OPT_POST_1,&err); //发送信号量
等待的任务 --------》OSSemPend(&SYNC_SEM,0,OS_OPT_PEND_BLOCKING,0,&err); //请求信号量
接收到信号量 开始工作 创建的 默认信号量是0 所以一般 工作信号量 超时都是 0 就是 没有发送信号量就阻塞 在这里
3 互斥信号量
解决 优先级反转 的问题 (只能 发一个信号量) 多个信号 要创建多个 对象 (低优先级在执行时候被打断 ,在其他需要使用信号量的 高优先级的任务在使用信号量时候会自动提升 低优先级的任务 执行完 释放信号量,高优先级的会继续执行)
OS_MUTEX TEST_MUTEX; //定义一个互斥信号量
//创建一个互斥信号量
OSMutexCreate((OS_MUTEX* )&TEST_MUTEX,
(CPU_CHAR* )"TEST_MUTEX",
(OS_ERR* )&err);
使用 //请求互斥信号量
OSMutexPend (&TEST_MUTEX,0,OS_OPT_PEND_BLOCKING,0,&err); //超时是0 没请求到会一直等待
{ 任务1 。。。}
//释放互斥信号量
OSMutexPost(&TEST_MUTEX,OS_OPT_POST_NONE,&err);
4.任务内嵌 信号量
task 创建的任务自带的 不用创建 直接 发送和请求 就行
当前任务只能 请求自己的信号量 ,可以给其他任务发送信号量
//任务2的任务函数
void task2_task(void *p_arg)
{
u8 num;
OS_ERR err;
while(1)
{
OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,0,&err); //请求任务内建的信号量 只能是自己的
num++;
LCD_ShowxNum(150,111,Task2_TaskTCB.SemCtr,3,16,0); //显示任务内建信号量值
LCD_Fill(6,131,233,313,lcd_discolor[num%14]); //刷屏
LED1=!LED1;
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
}
}
//任务1的任务函数 void task1_task(void *p_arg) { u8 key; u8 num; OS_ERR err; while(1) { key = KEY_Scan(0); //扫描按键 if(key==WKUP_PRES) { OSTaskSemPost(&Task2_TaskTCB,OS_OPT_POST_NONE,&err);//使用系统内建信号量向任务task2发送信号量 LCD_ShowxNum(150,111,Task2_TaskTCB.SemCtr,3,16,0); //显示信号量值 } num++; if(num==50) { num=0; LED0=!LED0; } OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err); //延时10ms } }