物联操作技术应用 9_第1页
物联操作技术应用 9_第2页
物联操作技术应用 9_第3页
物联操作技术应用 9_第4页
物联操作技术应用 9_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章事件

Chapter7Event《物联网操作系统技术与应用》制作人张亚军

前面我们学习了信号量、互斥锁。本章将学习LiteOS提供的另一种任务间通信的机制——事件。可以使用事件进行同步并实现阻塞机制,信号量用作与单个任务进行同步,事件可以实现一对多,多对多的同步处理。前言010302学习目标能够描述事件的基本概念能够说出事件的运行机制能够熟练使用LiteOS事件的相关函数目录CONTENTS事件基本概念事件控制块事件运行机制 事件常用函数7.17.27.37.4事件基本概念7.1BasicConceptofEvent7.1事件基本概念事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能是事件类型的通信,无数据传输。在事件机制中,任务可以等待特定的事件发生后继续执行,而在此之前会一直处于阻塞状态。一个任务可以等待一个事件的发生,也可以等待任意多个事件的发生。任务等待多个事件时,其中任何一个事件发生,任务即被同步唤醒,这种同步机制称为“或”同步(独立型同步);所有事件都发生时,任务才被同步唤醒,这种同步机制称为“与”同步(关联型同步)。多个任务也可以等待一个或多个事件的触发,实现多对多的同步。事件控制块EventControlBlock7.27.2事件控制块

事件控制块存储了一个事件的相关信息,系统都是通过事件控制块对事件进行操作的,事件控制块中包含了一个32位的uwEventID变量,其变量的各个位表示一个事件,此外,还存在一个事件链表stEventList,用于记录所有在等待此事件的任务,事件控制块代码结构如下:typedefstructtagEvent{UINT32uwEventID;LOS_DL_LISTstEventList;}EVENT_CB_S,*PEVENT_CB_S;

事件控制块中包含信息的说明如下:(1)uwEventID:标识发生的事件类型位,每一位代表一种事件类型,第25位保留,一共31种事件类型。初始化为0表示没有事件发生,当有事件发生时,对应的事件标志位置1。(2)stEventList:读取事件任务链表,也就是等待事件阻塞队列,当有任务需要等待事件发生时会被阻塞进入该队列。事件运行机制EventRunningMechanism7.37.3事件运行机制事件控制块中32位的变量uwEventID,也可以称之为事件集合,如图7-1所示。任务/中断可以写入指定的事件类型(事件掩码),设置事件集合的某些位为1,表示有事件发生。系统支持写入多个事件类型,写事件成功可能会触发任务调度。图7-132位的变量uwEventID

任务可以根据事件类型(事件掩码)uwEventMask读取单个或者多个事件,事件读取成功后,如果读取模式设置为LOS_WAITMODE_CLR则会清除已读取到的事件类型,反之不会清除已读到的事件类型。用户可以选择读取事件的模式,读取事件类型中的所有事件或者是任意事件。如果没有事件发生,读取任务将进入阻塞态,若等待的事件发生了,则任务被唤醒。清除事件时,根据事件控制块指针和待清除的事件类型,对事件对应位进行清0操作。7.3事件运行机制

例如,任务1对事件1或事件2感兴趣(逻辑或LOS_WAITMODE_OR,假设在读事件函数中设置了清除事件位LOS_WAITMODE_CLR,当任务被唤醒后,系统会把事件1位清零),当发生其中的某一个事件都会被唤醒,并且执行相应操作,过程如图7-2所示;而任务2对事件1与事件2感兴趣(逻辑与LOS_WAITMODE_AND),当且仅当事件1与事件2都发生的时候,任务2才会被唤醒,如果只有其中一个事件发生,那么任务2还是会继续等待事件发生,过程如图7-3所示。图7-2逻辑或事件唤醒任务的过程图7-3逻辑与事件唤醒任务的过程事件常用函数CommonFunctionsofEvent7.47.4事件常用函数

HuaweiLiteOS中事件相关的常用函数及功能如表7-1所示。表7-1事件相关的常用函数及功能功能分类函数名功能初始化事件LOS_EventInit初始化一个事件控制块读/写事件LOS_EventRead读取指定事件类型,超时时间为相对时间:单位为TickLOS_EventWrite写指定的事件类型清除事件LOS_EventClear清除指定的事件类型校验事件掩码LOS_EventPoll根据用户传入的事件ID、事件掩码及读取模式,返回用户传入的事件是否符合预期销毁事件LOS_EventDestroy销毁指定的事件控制块7.4事件常用函数7.4.1事件初始化函数LOS_EventInit()表7-2LOS_EventInit()函数语法要点

函数LOS_EventInit()用于初始化事件标志组,在使用之前需要用户定义一个事件控制块结构,然后将事件控制块的地址通过pstEventCB参数传递到该函数中。LOS_EventInit()函数语法要点如表7-2所示。函数原型LITE_OS_SEC_TEXT_INITUINT32LOS_EventInit(PEVENT_CB_SpstEventCB)函数传入值pstEventCB:指向要初始化的事件控制块的指针函数返回值LOS_OK:事件控制块成功初始化错误代码:出错7.4事件常用函数

7.4.2事件销毁函数LOS_EventDestory()表7-3LOS_EventDestory()函数语法要点在实际应用中,事件可能只需要使用一次,当不需要使用的时候,可销毁事件。LiteOS提供的销毁事件的函数为LOS_EventDestory(),其语法要点如表7-3所示。函数原型LITE_OS_SEC_TEXT_INITUINT32LOS_EventDestory(PEVENT_CB_SpstEventCB)函数传入值pstEventCB:指向要销毁的事件控制块的指针函数返回值LOS_OK:事件已成功清除错误代码:出错7.4事件常用函数

7.4.3写指定事件函数LOS_EventWrite()表7-4LOS_EventWrite()函数语法要点

函数LOS_EventWrite()用于写入事件中指定的位,当某一类型的事件发生时,将该事件发生的标识填入相应的标识位,被置位之后,阻塞在该位上的任务将会被解锁。多次填入同一个标识位相当于只填入了一次,即该事件在没有被清除的状况下,多次发生相当于只发生了一次。

当有多个事件发生时,使用LOS_EventWrite()函数为每个事件设置对应的标志位,然后遍历阻塞在事件列表上的任务,判断是否满足任务唤醒条件,如果满足,则唤醒该任务。需要注意的是,uwEventID的第25位是LiteOS保留出来的,用于区别读事件函数LOS_EventRead()返回的是事件还是错误代码。

如果想要记录一个事件的发生,这个事件在事件集合的位置是bit0,当事件还未发生时,事件集合bit0位中为0,当它发生时,只需要往事件集合bit0位中写入1,就表示该事件已经发生了。LOS_EventWrite()函数语法要点如表7-4所示。函数原型LITE_OS_SEC_TEXTUINT32LOS_EventWrite(PEVENT_CB_SpstEventCB,UINT32uwEvents)函数传入值pstEventCB:指向要写入事件的事件控制块的指针。此参数必须指向有效内存uwEvents:要写入的事件掩码函数返回值LOS_OK:成功写入事件错误代码:出错7.4事件常用函数7.4.4读指定事件函数LOS_EventRead()表7-5LOS_EventRead()函数语法要点LiteOS提供的读取指定事件的函数为LOS_EventRead(),用于读取事件集合中的哪一位,哪一个事件发生了,然后可以通过“逻辑与”、“逻辑或”等操作,判断是否发生用户预期的事件。只有任务等待的事件发生时,任务才能读取到事件信息。如果事件一直没发生,该任务将保持阻塞状态,以等待事件的发生。当其他任务或中断服务程序往任务等待的事件设置对应的标志位时,并且满足读取事件的条件,该任务将自动由阻塞态转为就绪态。当任务阻塞时间超时,即使事件还未发生,任务也会自动恢复为就绪态。如果正确读取事件,则返回非零值,由用户判断再做处理,因为在读取事件时可能会返回不确定的值,如果阻塞时间超时将返回错误代码。LOS_EventRead()函数语法要点如表7-5所示。函数原型LITE_OS_SEC_TEXTUINT32LOS_EventRead(PEVENT_CB_SpstEventCB,UINT32uwEventMask,UINT32uwMode,UINT32uwTimeOut)函数传入值pstEventCB:指向要检查的事件控制块的指针。此参数必须指向有效内存uwEventMask:用户要读取的事件掩码,要与uwEventID中所设置的相匹配uwMode:事件读取模式,可选值如下:(1)所有事件(LOS_WAITMODE_AND):读取掩码中所有事件类型,只有读取的所有事件类型都发生了,才能读取成功;(2)任一事件(LOS_WAITMODE_OR):读取掩码中任一事件类型,读取的事件中任意一种事件类型发生了,就可以读取成功;(3)清除事件(LOS_WAITMODE_CLR):LOS_WAITMODE_AND|LOS_WAITMODE_CLR或LOS_WAITMODE_OR|LOS_WAITMODE_CLR时表示读取成功后,对应事件类型位会自动清除。如果模式没有设置为自动清除的话,那么需要手动显式清除。uwTimeout:读取超时时间函数返回值0:预期的事件未发生非0:发生用户预期的事件错误代码:出错7.4事件常用函数7.4.5清除指定事件函数LOS_EventClear()表7-6LOS_EventClear()函数语法要点假如使用LOS_EventRead()函数获取事件的时候,在参数uwMode中没有设置LOS_WAITMODE_CLR,即没有将对应的标志位清除,那就需要调用LOS_EventClear()函数手动显式清除事件标志。LOS_EventClear()函数语法要点如表7-6所示。函数原型LITE_OS_SEC_TEXT_MINORUINT32LOS_EventClear(PEVENT_CB_SpstEventCB,UINT32uwEvents)函数传入值pstEventCB:指向要清除的事件控制块的指针uwEvents:要清除的事件掩码函数返回值LOS_OK:成功清除事件错误代码:出错

任务描述

在LiteOS中创建两个任务LED_Task和Key_Task,LED_Task是一个读事件任务,Key_Task是一个写事件任务。写事件任务通过检测KEY1按键和KEY2按键的按下情况,写入相应事件,读事件任务则读取事件标志位,并判断事件是否发生了,如果是KEY1按键写入的事件发生,则LED1灯翻转,如果是KEY2按键写入的事件发生,则LED2灯翻转,并在串口输出相应信息。

任务7-1发送和接收事件 谢谢观看THANKYOUFORWATCHING任务7-1发送和接收事件Task7-1SendingandReceivingEvents《物联网操作系统技术与应用》制作人张亚军

任务描述

在LiteOS中创建两个任务LED_Task和Key_Task,LED_Task是一个读事件任务,Key_Task是一个写事件任务。写事件任务通过检测KEY1按键和KEY2按键的按下情况,写入相应事件,读事件任务则读取事件标志位,并判断事件是否发生了,如果是KEY1按键写入的事件发生,则LED1灯翻转,如果是KEY2按键写入的事件发生,则LED2灯翻转,并在串口输出相应信息。

任务实现

1.打开第2章中移植好LiteOS的裸机工程TEST,修改main.c文件,添加头文件。任务7-1发送和接收事件 26

/*USERCODEBEGINIncludes*/27

/*LiteOS头文件*/28#include"los_sys.h"29#include"los_task.ph"30

/*USERCODEENDIncludes*/2.定义任务ID变量、定义事件标志组的控制块、定义事件掩码。任务7-1发送和接收事件 59/*USERCODEBEGIN0*/60/*定义任务ID*/61UINT32LED_Task_Handle;62UINT32Key_Task_Handle;63

/*定义事件标志组的控制块*/64

staticEVENT_CB_SEventGroup_CB;65

/******************宏定义*********************/66#defineKEY1_EVENT(0x01

<<

0)//设置事件掩码的位067#defineKEY2_EVENT(0x01

<<

1)//设置事件掩码的位13.创建和管理任务LED_Task、任务Key_Task。1)定义任务实现函数LED_Task()、Key_Task()。68

/***********************************************************69*@函数名

:LED_Task70*@功能说明:LED_Task任务实现71*@参数

:NULL72*@返回值

:NULL73***********************************************************/74

static

voidLED_Task(void)75

{76

//定义一个事件接收变量77UINT32uwRet;

78

/*任务都是一个无限循环,不能返回

*/任务7-1发送和接收事件 79

while(1)80

{81

/*等待事件标志组*/82uwRet=LOS_EventRead(

&EventGroup_CB,

//事件标志组对象83KEY1_EVENT|KEY2_EVENT,

//等待任务感兴趣的事件84LOS_WAITMODE_OR,

//等待两位均被置位85LOS_WAIT_FOREVER);

//无期限等待86printf(

"uwRet=%x\n",uwRet);87

if(uwRet==KEY1_EVENT)

88

{89

/*如果接收完成并且正确*/90printf(

"KEY1按下,LED1翻转\n");91HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_5);

//LED1翻转92LOS_EventClear(&EventGroup_CB,

~KEY1_EVENT);//清除事件标志

93

}94

if(uwRet==KEY2_EVENT)

95

{96

/*如果接收完成并且正确*/97printf(

"KEY2按下,LED2翻转\n");98HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_4);

//LED2翻转99LOS_EventClear(&EventGroup_CB,

~KEY2_EVENT);//清除事件标志

100

}101

}102}103/************************************************************104*@函数名

:Key_Task105*@功能说明:Key_Task任务实现106*@参数

:NULL107*@返回值

:NULL108***********************************************************/109static

voidKey_Task(void)110{111

//定义一个返回类型变量,初始化为LOS_OK112UINT32uwRet=LOS_OK;

113

/*任务都是一个无限循环,不能返回*/114

while(1)115

{116

/*KEY1被按下*/117

if(

!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4))

//读取KEY1按键引脚,低电平表示按下118

{119printf(

"KEY1被按下\n"

);120LOS_TaskDelay(500);

//等待松手,延时防松手抖动121

/*触发一个事件1*/122LOS_EventWrite(&EventGroup_CB,KEY1_EVENT);

123

}124

/*KEY2被按下*/125

if(

!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_5))

126

{127printf(

"KEY2被按下\n"

);

128LOS_TaskDelay(500);

//等待松手,延时防松手抖动129

/*触发一个事件2*/130LOS_EventWrite(&EventGroup_CB,KEY2_EVENT);

131

}132LOS_TaskDelay(20);

//每20ms扫描一次

133

}134}2)定义任务创建函数Creat_LED_Task()、Creat_Key_Task()。任务7-1发送和接收事件 135/************************************************************136*@函数名

:Creat_LED_Task137*@功能说明:

创建LED_Task任务138*@参数

139*@返回值

无140***********************************************************/141staticUINT32Creat_LED_Task()142{143

//定义一个返回类型变量,初始化为LOS_OK144UINT32uwRet=LOS_OK;

145

//定义一个用于创建任务的参数结构体146TSK_INIT_PARAM_Stask_init_param;

147task_init_param.usTaskPrio=

5;

/*任务优先级,数值越小,优先级越高*/148task_init_param.pcName=

"LED_Task";/*任务名*/149task_init_param.pfnTaskEntry=

(TSK_ENTRY_FUNC)LED_Task;/*任务函数入口*/150task_init_param.uwStackSize=

1024;

/*堆栈大小*/151uwRet=LOS_TaskCreate(&LED_Task_Handle,

&task_init_param);/*创建任务*/152

returnuwRet;153}任务7-1发送和接收事件 154/*************************************************************155*@函数名

:Creat_Key_Task156*@功能说明:

创建Key_Task任务157*@参数

158*@返回值

无159************************************************************/160staticUINT32Creat_Key_Task()161{162

//定义一个返回类型变量,初始化为LOS_OK163UINT32uwRet=LOS_OK;

164TSK_INIT_PARAM_Stask_init_param;165task_init_param.usTaskPrio=

4;

/*任务优先级,数值越小,优先级越高*/166task_init_param.pcName=

"Key_Task";

/*任务名*/167task_init_param.pfnTaskEntry=

(TSK_ENTRY_FUNC)Key_Task;/*任务函数入口*/168task_init_param.uwStackSize=

1024;

/*堆栈大小*/

169uwRet=LOS_TaskCreate(&Key_Task_Handle,

&task_init_param);/*创建任务*/170

returnuwRet;171}3)定义任务管理函数AppTaskCreate()。任务7-1发送和接收事件 178static

UINT32AppTaskCreate(void)179{180

/*定义一个返回类型变量,初始化为LOS_OK*/181UINT32uwRet=LOS_OK;

182

/*创建一个事件标志组*/183uwRet=LOS_EventInit(&EventGroup_CB);184

if

(uwRet!=LOS_OK)185

{186printf("EventGroup_CB事件标志组创建失败!失败代码0x%X\n",uwRet);187

}

188uwRet=Creat_LED_Task();189

if

(uwRet!=LOS_OK)190

{191printf("LED_Task任务创建失败!失败代码0x%X\n",uwRet);192

returnuwRet;193

}

194uwRet=Creat_Key_Task();195

if

(uwRet!=LOS_OK)196

{197printf("Key_Task任务创建失败!失败代码0x%X\n",uwRet);198

returnuwRet;199

}200

returnLOS_OK;201}202/*USERCODEEND0*/4.在主函数中修改代码。任务7-1发送和接收事件 208intmain(void)209{210

/*USERCODEBEGIN1*/211UINT32uwRet=LOS_OK;

//定义一个返回类型变量,初始化为LOS_OK212

/*USERCODEEND1*/213

/*MCUConfiguration-------------------------------------*/214

/*Resetofallperipherals,Initializest

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论