wangpengcheng 发表于 2014-9-11 14:38:44

原创:我跟你一起学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 }
};

这回万事齐备了,整个小区开始了他们一天的生活:


从结果来看,我们可以看到:
早上,白领去上班,大妈去买菜,安利客户来了,三个事件碰到一起了,所以事件只响应了一次,门只打开了一次
再到后来呢,大妈买菜回来了,第一个安利客户走了,两个事件又碰到一起了,所以呢,门也只用打开一次
再后来就大家各自进进出出都没碰到,那门就有点累了,每个事件都响应了一次,每个人到门口都各自打开一次

呵呵!不错,希望我们小区管理处以后能坚持这样管理啊,减少不必要的情况发生!

最后照例是例程:

rockyyangyang 发表于 2014-9-11 14:54:35

又一次征服了我,可以在加上,要是他们没按时回来,会是怎么样的一个情况呢。{:lol:}

wangpengcheng 发表于 2014-9-11 14:56:00

rockyyangyang 发表于 2014-9-11 14:54
又一次征服了我,可以在加上,要是他们没按时回来,会是怎么样的一个情况呢。 ...

把事件撤消掉,让他们进不了门!{:titter:}

fengyunyu 发表于 2014-9-11 14:59:39

通俗易懂,可以考虑出书。”大话XX“之类。

wangpengcheng 发表于 2014-9-11 15:03:13

fengyunyu 发表于 2014-9-11 14:59
通俗易懂,可以考虑出书。”大话XX“之类。

谢谢夸奖,呵呵,出书之类的事情就拉倒吧,只是想跟坛子里的朋友一起讨论!

彼岸花开@ 发表于 2014-9-11 15:18:35

面向对象的写法,还没有怎么接触过。楼主正好给举了个好例子。

wangpengcheng 发表于 2014-9-11 15:39:50

彼岸花开@ 发表于 2014-9-11 15:18
面向对象的写法,还没有怎么接触过。楼主正好给举了个好例子。

这个不是面像对像,呵呵,你要学面向对像可以参考一下C++,你要能想明白如何用C实现C++中类的部分功能,基本就可以了

32MCU 发表于 2014-9-11 16:10:14

这个不顶下。没有道理。

步之道 发表于 2014-9-11 21:18:43

楼主的学习已经进入到第四篇了,看完这一篇后,我提个疑问。
为什么不联系前面学习的内容来写这一篇?
举个例子:互斥量,而且加入互斥量后会让程序更加合理。
如果A去开门了,那么B同时到来,是接收不到B刷卡开门的信息的。因为你在这里没有进行关门操作。你的开门后到关门这之间是有时间的。
我们在做程序时应该想到实际情况中所有的情况
还是用上面的例子:
//大妈去买菜
//大妈买菜回来
如果上面两个事件在程序中写成组合出现,也就是【大妈去买菜】后,必须执行【大妈买菜回来】事件,那么实际出现出现【大妈买菜回来】和【白领回来】一起,大妈没有刷卡触发事件,那么下次大妈想再执行【大妈去买菜事件】怎么解决。
上面描述的这种情况实际出现在我们平时乘坐地铁时。

所以我们就要去限定到底能不能【大妈买菜回来】和【白领回来】其中任意一个触发事件,导致门开。
知识本身就是一个相互运用的过程,写程序时运用各种知识储备将程序写的更加健壮周密,更加符合实际运用,更加人性化,或者说更加优美,很重要。
如果觉的我说的不对,请拍砖。

浪里白条 发表于 2014-9-11 21:53:51

学习啦,等板子到手开始跟着学习。

wxfje 发表于 2014-9-11 22:04:46

看完之后更糊涂了,究竟什么是事件,这个事件和信号量又有什么不同呢

kinsno 发表于 2014-9-11 22:07:16

楼主描述的事件,我不晓得MQX中是不是这样玩的,但UCOS貌似不是这样玩的,难道我记忆有错?事件不是事件标志位吗?

wangpengcheng 发表于 2014-9-11 23:36:57

kinsno 发表于 2014-9-11 22:07
楼主描述的事件,我不晓得MQX中是不是这样玩的,但UCOS貌似不是这样玩的,难道我记忆有错?事件不是事件标 ...

是标志位啊,置位也是为了解决问题啊!

wangpengcheng 发表于 2014-9-11 23:38:02

wxfje 发表于 2014-9-11 22:04
看完之后更糊涂了,究竟什么是事件,这个事件和信号量又有什么不同呢

信号量是接收一次处理一次,事件不一样,事件可以有好几个来进行触发

wangpengcheng 发表于 2014-9-11 23:41:43

步之道 发表于 2014-9-11 21:18
楼主的学习已经进入到第四篇了,看完这一篇后,我提个疑问。
为什么不联系前面学习的内容来写这一篇?
举个 ...

刚好相反,在ABC三个同时进行触发的时候它并不是没有接收到,而是都接收到了,但它只会执行一次,相当于一个标志位,三个去置位,但是结果是或的关系!在事件清除之前任意触发都无效!

步之道 发表于 2014-9-12 00:04:13

那有关门的命令吗?比如开门到关门30秒,第一个人开了,第二个人29秒的时候来触发一次那门什么时候关?两个事件可以用事件标记,但事件标记是持续变量,还是瞬态变量呢?

tim 发表于 2014-9-12 00:09:04

事件就类似硬件上的中断

cslrd 发表于 2014-9-12 00:33:22

进来学习一下

wangpengcheng 发表于 2014-9-12 10:50:38

步之道 发表于 2014-9-12 00:04
那有关门的命令吗?比如开门到关门30秒,第一个人开了,第二个人29秒的时候来触发一次那门什么时候关?两个 ...

事件有清除事件标志,你可以看看程序中开门后有一个清除事件函数,那个是用来清除事件的,另个,事件在创建的时候也可选择自己清除事件,即事件置位后,等等触发,触发后自动清除!

wangpengcheng 发表于 2014-9-12 10:51:20

tim 发表于 2014-9-12 00:09
事件就类似硬件上的中断

跟中断不一样,中断是硬件实时的,事件只有等任务切换后才能触发!

tim 发表于 2014-9-12 10:59:13

wangpengcheng 发表于 2014-9-12 10:51
跟中断不一样,中断是硬件实时的,事件只有等任务切换后才能触发!

我的意思是“什么时候发生不确定”这一点类似

wangpengcheng 发表于 2014-9-12 11:12:29

tim 发表于 2014-9-12 10:59
我的意思是“什么时候发生不确定”这一点类似

呵呵,有点那个意思!

kevinchen026 发表于 2014-9-12 12:23:24

MQZ 事件   

kevinchen026 发表于 2014-9-12 12:23:46

mark ~~~   

步之道 发表于 2014-9-12 12:43:39

wangpengcheng 发表于 2014-9-12 10:50
事件有清除事件标志,你可以看看程序中开门后有一个清除事件函数,那个是用来清除事件的,另个,事件在创 ...

原来如此,不过你用这个小区门禁的例子来讲解事件,但是又区分了出去和回来,这两个个人觉的不需要被区分,只要定义一个开门事件就可以了,然后通过卡的区分,来定义不同的人的开门事件。这样是否更友好呢。

wangpengcheng 发表于 2014-9-12 14:59:50

步之道 发表于 2014-9-12 12:43
原来如此,不过你用这个小区门禁的例子来讲解事件,但是又区分了出去和回来,这两个个人觉的不需要被区分 ...

你说的很对,举例时没想清楚,其实只是需要开门就可以,不用管进出

步之道 发表于 2014-9-12 19:04:12

wangpengcheng 发表于 2014-9-12 14:59
你说的很对,举例时没想清楚,其实只是需要开门就可以,不用管进出

嘿嘿,是的,这样也可以不要用到互斥量了。大家开门是可以同步的,只要将每个人的开门事件记录下来,然后对门状态进行或运算,并以最后一个人的开门时间延时多长时间作为关门动作。其实你举得这个例子肯贴近坐地铁时的情况。

wangpengcheng 发表于 2014-9-12 21:18:31

步之道 发表于 2014-9-12 19:04
嘿嘿,是的,这样也可以不要用到互斥量了。大家开门是可以同步的,只要将每个人的开门事件记录下来,然后 ...

三个信号同进到达的原因是其它三个任务的优先级比较高,三个先后完成了置位,触发的任务优先级比较低,在三个置位都完成后才轮到它运行,所以跟你说的那种情况还不一样!

寻找钢叉的猹 发表于 2014-9-24 13:01:55

你好 请问你的QQ多少 我想问你一点问题 {:dizzy:}

ccrt 发表于 2014-9-24 14:13:27

楼主你太有才了
{:lol:}

wangpengcheng 发表于 2014-9-24 21:48:55

寻找钢叉的猹 发表于 2014-9-24 13:01
你好 请问你的QQ多少 我想问你一点问题

可以在帖子中把问题说出来,大家给你看啊!

寻找钢叉的猹 发表于 2014-9-24 21:51:02

wangpengcheng 发表于 2014-9-24 21:48
可以在帖子中把问题说出来,大家给你看啊!

刚开始搭建环境 问题太多 比较碎有一个TWR-K60D100M现在各种下载资料开始学习的第一天

wangpengcheng 发表于 2014-9-24 21:52:10

寻找钢叉的猹 发表于 2014-9-24 21:51
刚开始搭建环境 问题太多 比较碎有一个TWR-K60D100M现在各种下载资料开始学习的第一天...

{:sweat:} 如果你连自己问题在哪都不清楚的话,除了自己深入学习,再没有其它办法啊!

寻找钢叉的猹 发表于 2014-9-24 21:52:28

{:lol:}我一定会努力的勤能补拙 多逛论坛

wangpengcheng 发表于 2014-9-24 21:53:17

寻找钢叉的猹 发表于 2014-9-24 21:52
我一定会努力的勤能补拙 多逛论坛

对的,呵呵,多动手,多逛论坛!主要是动手!

寻找钢叉的猹 发表于 2014-10-1 21:23:16

楼主我有TWR-K60D100M 能否和你一起学习MQX?如果可以的话希望能加下你的QQ   PS:我的QQ---->1113240207
我刚学4天MQX苦恼于没人和我一起,希望能找个伴

samhws 发表于 2014-10-29 15:24:24

请问楼主,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后,怎么例程里的串口就通信不上了,不知道你有没有遇到过?

wangpengcheng 发表于 2014-10-29 17:33:16

samhws 发表于 2014-10-29 15:24
请问楼主,K60 mqx的例程里用到MQX_HAS_TIME_SLICE
#if ! MQX_HAS_TIME_SLICE
#error This application req ...

我暂时没用到这个功能!你查一下,看看是不是其它地方影响了串口!这两个不应该有冲突!
页: [1]
查看完整版本: 原创:我跟你一起学MQX(四):事件