原创:我跟你一起学MQX(四):事件
话说我们小区管理处挺给力的,以前大门常开,谁想进就进,想出就出,给把钥匙吧就是个样子!但最近由于大家反映,小区常有陌生人出入,管理处也头大啊,天天盯着陌生人,工作量大多了!于是,管理处发了个通知,增加门禁功能!这回好了,进出小区必须拿卡刷,没卡,不好意思,你进不来!正好我去管理处领卡,碰到一个大妈,他也来拿卡,手上还拎着个菜蓝子!回来的路上我就想啊,这门禁不就是我们系统中的事件吗?
什么是事件呢?
事件是操作系统中的一种触发机制,在特定的时间或者情况下,可以对特定的动作进行触发,它可以应用在不同的任务或者任务与中断函数中进行任务同步!
我就根据小区的事情做个例子,大家一起讨论一下!事件的API函数见MQX中的event.h文件中!
假设,我们小区有三个住户,一个白领,一个是大妈,而另一个呢,比较烦人,做安利的!{:titter:}
现在呢,我先做个门禁的任务,门禁的任务比较简单,就是别人要拿卡开门,它就给开:
void MainTask(uint32_t para)
{
void *event_ptr;
if (_event_create("door") != MQX_OK) //创建个门禁系统(事件)
{
printf("\nMake event failed");
_task_block();
}
if (_event_open("door", &event_ptr) != MQX_OK) //获得门禁系统的控制权(打开事件)
{
printf("\nOpen event failed");
_task_block();
}
/* Create the print tasks */
_task_create(0, WHIT_TASK, 0); //白领搬进小区了
_task_create(0, AUNT_TASK, 0); //大妈搬进小区了
_task_create(0, AMWA_TASK, 0); //安利也搬进小区了
while(1)
{
if (_event_wait_all_ticks(event_ptr, 0x01, 0) != MQX_OK) //等待有人拿卡开门
{
printf("\nEvent Wait failed");
_task_block();
}
printf("The door is open! \n\n");
if (_event_clear(event_ptr,0x01) != MQX_OK) //自动关门
{
printf("\nEvent Clear failed");
_task_block();
}
}
}
有门禁系统了,区民也都搬进来了,我们看看居民一天的交通情况吧:
我们先看白领,白领呢,生活比较有规律,朝9晚6,早上去上班,下午回来。它的任务如下:
void WhiteCollarTask(uint32_t para)
{
void *event_ptr;
if (_event_open("door",&event_ptr) != MQX_OK) //先领到门禁卡(打开事件)
{
printf("\nOpen Event failed");
_task_block();
}
printf("White Collar go to work!\n");
if (_event_set(event_ptr,0x01) != MQX_OK) //上班要出去,开门(设置事件)
{
printf("\nSet Event failed");
_task_block();
}
_time_delay(1000);
printf("White Collar go home!\n");
if (_event_set(event_ptr,0x01) != MQX_OK) //下班要回来,开门(设置事件)
{
printf("\nSet Event failed");
_task_block();
}
}
再看看大妈,大妈的生活也很有规律,就是事稍稍多了点,早上得去买菜,下午还要去跳广场舞:
void AuntTask(uint32_t para)
{
void *event_ptr;
if (_event_open("door",&event_ptr) != MQX_OK) //领到门禁卡,拥有门禁控制权 (打开事件)
{
printf("\nOpen Event failed");
_task_block();
}
printf("Aunt buy food!\n");
if (_event_set(event_ptr,0x01) != MQX_OK) //大妈去买菜,开门 (设置事件)
{
printf("\nSet Event failed");
_task_block();
}
_time_delay(100);
printf("Aunt buy food back!\n");
if (_event_set(event_ptr,0x01) != MQX_OK) //大妈买菜回来了,开门 (设置事件)
{
printf("\nSet Event failed");
_task_block();
}
_time_delay(300);
printf("Aunt go to dance!\n");
if (_event_set(event_ptr,0x01) != MQX_OK) //大妈去跳舞,开门 (设置事件)
{
printf("\nSet Event failed");
_task_block();
}
_time_delay(100);
printf("Aunt dance back!\n");
if (_event_set(event_ptr,0x01) != MQX_OK) //大妈跳舞回来了,开门 (设置事件)
{
printf("\nSet Event failed");
_task_block();
}
}
还有做安利的,这个挺烦人的,进进出出的客户:
void AmwayTask(uint32_t para)
{
void *event_ptr;
int i;
if (_event_open("door",&event_ptr) != MQX_OK) //安利也拿到控制权了
{
printf("\nOpen Event failed");
_task_block();
}
for(i = 0; i < 2; i++) //我让他客户少点,只有两个人
{
printf("Amway customer come!\n");
if (_event_set(event_ptr,0x01) != MQX_OK) //来客户了,开门
{
printf("\nSet Event failed");
_task_block();
}
_time_delay(100);
printf("Amway customer go!\n");
if (_event_set(event_ptr,0x01) != MQX_OK) //客户走了,关门
{
printf("\nSet Event failed");
_task_block();
}
_time_delay(200);
}
}
好吧,现在一切都可以了,还少了Z.F.的安排:
const TASK_TEMPLATE_STRUCTMQX_template_list[] =
{
/* Task Index, Function, Stack,Priority, Name, Attributes, Param, Time Slice */
{ MAIN_TASK, MainTask, 1500, 9, "main",MQX_AUTO_START_TASK,0, 0 },
{ WHIT_TASK, WhiteCollarTask, 1500, 5, "White",MQX_USER_TASK , 0, 0},
{ AUNT_TASK, AuntTask, 1500, 6, "Aunt",MQX_USER_TASK , 0, 0},
{ AMWA_TASK, AmwayTask, 1500, 8, "Amway",MQX_USER_TASK , 0, 0},
{ 0 }
};
这回万事齐备了,整个小区开始了他们一天的生活:
从结果来看,我们可以看到:
早上,白领去上班,大妈去买菜,安利客户来了,三个事件碰到一起了,所以事件只响应了一次,门只打开了一次
再到后来呢,大妈买菜回来了,第一个安利客户走了,两个事件又碰到一起了,所以呢,门也只用打开一次
再后来就大家各自进进出出都没碰到,那门就有点累了,每个事件都响应了一次,每个人到门口都各自打开一次
呵呵!不错,希望我们小区管理处以后能坚持这样管理啊,减少不必要的情况发生!
最后照例是例程:
又一次征服了我,可以在加上,要是他们没按时回来,会是怎么样的一个情况呢。{:lol:} rockyyangyang 发表于 2014-9-11 14:54
又一次征服了我,可以在加上,要是他们没按时回来,会是怎么样的一个情况呢。 ...
把事件撤消掉,让他们进不了门!{:titter:} 通俗易懂,可以考虑出书。”大话XX“之类。 fengyunyu 发表于 2014-9-11 14:59
通俗易懂,可以考虑出书。”大话XX“之类。
谢谢夸奖,呵呵,出书之类的事情就拉倒吧,只是想跟坛子里的朋友一起讨论! 面向对象的写法,还没有怎么接触过。楼主正好给举了个好例子。 彼岸花开@ 发表于 2014-9-11 15:18
面向对象的写法,还没有怎么接触过。楼主正好给举了个好例子。
这个不是面像对像,呵呵,你要学面向对像可以参考一下C++,你要能想明白如何用C实现C++中类的部分功能,基本就可以了 这个不顶下。没有道理。 楼主的学习已经进入到第四篇了,看完这一篇后,我提个疑问。
为什么不联系前面学习的内容来写这一篇?
举个例子:互斥量,而且加入互斥量后会让程序更加合理。
如果A去开门了,那么B同时到来,是接收不到B刷卡开门的信息的。因为你在这里没有进行关门操作。你的开门后到关门这之间是有时间的。
我们在做程序时应该想到实际情况中所有的情况
还是用上面的例子:
//大妈去买菜
//大妈买菜回来
如果上面两个事件在程序中写成组合出现,也就是【大妈去买菜】后,必须执行【大妈买菜回来】事件,那么实际出现出现【大妈买菜回来】和【白领回来】一起,大妈没有刷卡触发事件,那么下次大妈想再执行【大妈去买菜事件】怎么解决。
上面描述的这种情况实际出现在我们平时乘坐地铁时。
所以我们就要去限定到底能不能【大妈买菜回来】和【白领回来】其中任意一个触发事件,导致门开。
知识本身就是一个相互运用的过程,写程序时运用各种知识储备将程序写的更加健壮周密,更加符合实际运用,更加人性化,或者说更加优美,很重要。
如果觉的我说的不对,请拍砖。 学习啦,等板子到手开始跟着学习。 看完之后更糊涂了,究竟什么是事件,这个事件和信号量又有什么不同呢 楼主描述的事件,我不晓得MQX中是不是这样玩的,但UCOS貌似不是这样玩的,难道我记忆有错?事件不是事件标志位吗? kinsno 发表于 2014-9-11 22:07
楼主描述的事件,我不晓得MQX中是不是这样玩的,但UCOS貌似不是这样玩的,难道我记忆有错?事件不是事件标 ...
是标志位啊,置位也是为了解决问题啊! wxfje 发表于 2014-9-11 22:04
看完之后更糊涂了,究竟什么是事件,这个事件和信号量又有什么不同呢
信号量是接收一次处理一次,事件不一样,事件可以有好几个来进行触发 步之道 发表于 2014-9-11 21:18
楼主的学习已经进入到第四篇了,看完这一篇后,我提个疑问。
为什么不联系前面学习的内容来写这一篇?
举个 ...
刚好相反,在ABC三个同时进行触发的时候它并不是没有接收到,而是都接收到了,但它只会执行一次,相当于一个标志位,三个去置位,但是结果是或的关系!在事件清除之前任意触发都无效! 那有关门的命令吗?比如开门到关门30秒,第一个人开了,第二个人29秒的时候来触发一次那门什么时候关?两个事件可以用事件标记,但事件标记是持续变量,还是瞬态变量呢? 事件就类似硬件上的中断 进来学习一下 步之道 发表于 2014-9-12 00:04
那有关门的命令吗?比如开门到关门30秒,第一个人开了,第二个人29秒的时候来触发一次那门什么时候关?两个 ...
事件有清除事件标志,你可以看看程序中开门后有一个清除事件函数,那个是用来清除事件的,另个,事件在创建的时候也可选择自己清除事件,即事件置位后,等等触发,触发后自动清除!
tim 发表于 2014-9-12 00:09
事件就类似硬件上的中断
跟中断不一样,中断是硬件实时的,事件只有等任务切换后才能触发! wangpengcheng 发表于 2014-9-12 10:51
跟中断不一样,中断是硬件实时的,事件只有等任务切换后才能触发!
我的意思是“什么时候发生不确定”这一点类似 tim 发表于 2014-9-12 10:59
我的意思是“什么时候发生不确定”这一点类似
呵呵,有点那个意思! MQZ 事件 mark ~~~ wangpengcheng 发表于 2014-9-12 10:50
事件有清除事件标志,你可以看看程序中开门后有一个清除事件函数,那个是用来清除事件的,另个,事件在创 ...
原来如此,不过你用这个小区门禁的例子来讲解事件,但是又区分了出去和回来,这两个个人觉的不需要被区分,只要定义一个开门事件就可以了,然后通过卡的区分,来定义不同的人的开门事件。这样是否更友好呢。 步之道 发表于 2014-9-12 12:43
原来如此,不过你用这个小区门禁的例子来讲解事件,但是又区分了出去和回来,这两个个人觉的不需要被区分 ...
你说的很对,举例时没想清楚,其实只是需要开门就可以,不用管进出 wangpengcheng 发表于 2014-9-12 14:59
你说的很对,举例时没想清楚,其实只是需要开门就可以,不用管进出
嘿嘿,是的,这样也可以不要用到互斥量了。大家开门是可以同步的,只要将每个人的开门事件记录下来,然后对门状态进行或运算,并以最后一个人的开门时间延时多长时间作为关门动作。其实你举得这个例子肯贴近坐地铁时的情况。 步之道 发表于 2014-9-12 19:04
嘿嘿,是的,这样也可以不要用到互斥量了。大家开门是可以同步的,只要将每个人的开门事件记录下来,然后 ...
三个信号同进到达的原因是其它三个任务的优先级比较高,三个先后完成了置位,触发的任务优先级比较低,在三个置位都完成后才轮到它运行,所以跟你说的那种情况还不一样! 你好 请问你的QQ多少 我想问你一点问题 {:dizzy:} 楼主你太有才了
{:lol:} 寻找钢叉的猹 发表于 2014-9-24 13:01
你好 请问你的QQ多少 我想问你一点问题
可以在帖子中把问题说出来,大家给你看啊! wangpengcheng 发表于 2014-9-24 21:48
可以在帖子中把问题说出来,大家给你看啊!
刚开始搭建环境 问题太多 比较碎有一个TWR-K60D100M现在各种下载资料开始学习的第一天 寻找钢叉的猹 发表于 2014-9-24 21:51
刚开始搭建环境 问题太多 比较碎有一个TWR-K60D100M现在各种下载资料开始学习的第一天...
{:sweat:} 如果你连自己问题在哪都不清楚的话,除了自己深入学习,再没有其它办法啊! {:lol:}我一定会努力的勤能补拙 多逛论坛 寻找钢叉的猹 发表于 2014-9-24 21:52
我一定会努力的勤能补拙 多逛论坛
对的,呵呵,多动手,多逛论坛!主要是动手! 楼主我有TWR-K60D100M 能否和你一起学习MQX?如果可以的话希望能加下你的QQ PS:我的QQ---->1113240207
我刚学4天MQX苦恼于没人和我一起,希望能找个伴 请问楼主,K60 mqx的例程里用到MQX_HAS_TIME_SLICE
#if ! MQX_HAS_TIME_SLICE
#error This application requires MQX_HAS_TIME_SLICE defined non-zero in user_config.h. Please recompile PSP and BSP with this option.
#endif
我在配置文件里定义MQX_HAS_TIME_SLICE为1后,怎么例程里的串口就通信不上了,不知道你有没有遇到过? samhws 发表于 2014-10-29 15:24
请问楼主,K60 mqx的例程里用到MQX_HAS_TIME_SLICE
#if ! MQX_HAS_TIME_SLICE
#error This application req ...
我暂时没用到这个功能!你查一下,看看是不是其它地方影响了串口!这两个不应该有冲突!
页:
[1]