技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152
两个任务之间的同步,咱们一般用信号量,但是
一个任务和多个事件之间的同步可以用或同步,和 与同步.
先看看这个或同步,比如有4个事件,那么只要有一个事件发生,那么对应的任务5就会同步.
这个与同步,意思就是,当所有时间都发生了,才去同步任务5,
下面说的这个标志事件组,就相当于与同步
可以看到他是个无符号的,32位的整形.
这个是什么意思呢?
他的意思是,一共32位,那么每位代表一个事件.
所以最多可以表示32个事件
我们要判断,某个bit位如果是1的时候,说明这个事件发生了.
先看这个OSFlagCreate()这个创建事件标志组.
第一个参数是事件标志组
第二个是事件标志组名字
第三个是:是事件标志组的,32个事件,初始化值,一般就赋值 一个0
如果你有个事件默认就是执行的,可以把某一位设置为1,那么至于
哪一位对应哪个事件,一会会说.
第四个是错误码
再看这个事件标志组的请求,这里
第一个参数是 事件标志组
第二个参数是 要请求哪个事件,比如要请求第0个,和第1个,那么就传入 0x03也就是0000 0011 ,再前面全是0
第三个参数,超时时间
第四个参数是 opt 是选项.
这个opt选项有四个
OS_OPT_PEND_FLAG_CLR_ALL 这个是表示,所有的flag中的32个位都清0了,就说明请求到,标志事件组了
OS_OPT_PEND_FLAG_CLR_ANY 这个是表示,所有的flag中的32个位,只要有一个位清0了,就表示,请求到标志事件组了
OS_OPT_PEND_FLAG_SET_ALL 这个是表示,所有的flag中的32个位,都设置成了1了,就表示,请求到标志事件组了
OS_OPT_PEND_FLAG_SET_ANY 这个表示,,所有的flag中的32个位,只要有一个设置成了1了,就表示,请求到标志事件组了
后面是一个时间戳和一个错误码
然后这里,看看这个
OSFlagPost 这个标志事件组的 释放事件
这里p_grp是,哪个标志事件组
flags这个是,要操作具体的哪个事件,32位中的哪个事件,哪一位是1就选中了哪个事件
然后 opt这个意思是,是要对选中的事件,是置1,还是置0
这个
OS_OPT_POST_FLAG_SET 是置1
然后
OS_OPT_POST_FLAG_CLR这个是清零
然后去看一下这个案例:
首先由三个任务
START_TASK_PRIO这个任务
MAIN_TASK_PRIO这个任务
还有
FLAGSPROCESS_TASK_PRIO这个是按键处理任务
这里定义了这个KEY0_FLAG 0X01就是 0X0000 0001
KEY1_FLAG 0X02 就是0X0000 0010
这两个就分别对应的,事件标志组的,第0位和低1位. 32位中的这两位
然后
KEYFLAGS_VALUE 这个0X00 这个就是设置为0,把默认值
main函数中,创建事件标志组
然后创建两个任务,一个主任务
一个是按键处理任务
再去看看
主任务
主任务中去扫描按键,然后,这里
扫描key0的时候,
可以看到向事件标志组发送EventFlags标志
然后KEY0_FLAG是占用第0位.
然后OS_OPT_POST_FLAG_SET是把上面对应的KEY0位设置为1
然后key可以看到也是这样,是把KEY1对应的位设置为1.
这里是释放事件标志组.
然后
看看事件标志组处理任务
这里,可以看到, 去请求KEY0_FLAG+KEY1_FLAG 去请求key0和key1
然后这里设置,当OS_OPT_PEND_FLAG_SET_ALL也就是,key0和key1都置1的时候
才算是请求成功
那么
OS_OPT_PEND_FLAG_CONSUME这个是什么意思呢
可以看到上面的解释就是,OS_OPT_PEND_FLAG_CONSUME,就是请求完了以后
要对对应的位要清0,这里就是选择清0,请求完以后.
所以这个就是这个事件标志组,
也就是,只有key0和key1,全部按下的时候,才会执行下面的操作
这里这个按键处理任务,就请求了事件标志组,要求
在key0,和key1 都按下的时候才显示填充和显示内容.
LCD
下载到开发版看看
刚启动的时候可以看到EventFlags value是0
然后按下key0的时候可以看到
EventFlags value是1
然后,再按下key1的时候可以看到就有颜色了显示了,并且
EventFlags value是0了,也就是被请求到了,key0,和key1都按下了.
可以看到,屏幕变了颜色以后,可以看到对应的值
也变成0了,也就说
OS_OPT_PEND_FLAG_CONSUME,请求完毕以后要把对应的事件的位都设置为0
看看串口的输出,可以看到按下key0这个值是1
也就0x01 写开 0000 0001
然后按下key1以后,因为key1是0x10写开0000 0010
所以放到一起,就是0x11 写开:0000 0011
也就是3,然后,当按键处理任务请求,事件标志组的时候,请求了以后,接着因为
OS_OPT_PEND_FLAG_CONSUME 这个就把3,又清为0了.
然后再看看,前面咱们说了,信号量,互斥信号量,消息队列和事件标志组
那么实际上是可以实现,
任务同时等待多个信号量和多个消息队列
注意这里只能同时等待多个信号量和多个消息队列
不能同时等待多个事件标志组,或互斥信号量
去看看代码
可以看看,第一个是个数组,也就是,要等待的信号量和消息队列都要放到这里.
,然后tbl_size这个是,上面那个数组的长度
然后timeout是超时时间片
然后选项
然后错误码
看看选项
选项是阻塞还是不阻塞
然后这里主要看一下这个数组是什么东西,
OS_PEND_DATA
咱们通过看案例来说
可以看到这里,这里等待多个内核对象,这里是
等待信号量1,信号量2,消息队列
然后内核对象个数是3也就是上面这个3个
然后消息队列长度是10
然后main函数中,去创建信号量1,信号量2,消息队列
可以看到这里,没有创建等待多个内核对象,这个是不需要创建的.
然后看看task1
可以看到在任务1中发送了信号量1,和发送了信号量2
然后这里任务2中按键扫描,
这里做了发送消息队列.
这里,请求等待多个内核对象
multi_task这个函数中,可以看到,把上面的信号量1,信号量2,
和消息队列,都放到结构体中.
然后通过
OSPendMulti,去等待,多个内核对象
这个等待多个内核对象,就相当于或同步
可以看到这里
下载到开发版以后
开始的时候,显示ObjRdy_NUM:0
这个时候,如果我按下key0,这里就显示1
同时屏幕也刷新了,也就是这里,只要这个三个信号量1,信号量2,
消息队列,只要有一个请求等待多个内核对象,只要有一个执行, 就会被捕获到.
屏幕就会刷新了.,
当然,也可以,比如同时按下信号量1,信号量2,还有消息队列的发送,这样值就会增加了.
这里多按下几次key0比如,也可以,这个值也会增加
ObjRdy_NUM:3