完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本章节为大家讲解FreeRTOS事件标志组的另一种实现方式----基于任务通知(Task Notifications)的事件标志组,这里我们将这种方式实现的事件标志组称之为任务事件标志组。这种方式实现的事件标志组效率更高,需要的RAM空间更小。当然,缺点也是有的,它没有第18章介绍的事件标志组实现的功能全面。 本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407以及F429。 26.1 任务通知(TaskNotifications)介绍 26.2 任务事件标志组 26.3 任务事件标志组API函数 26.4 实验例程说明(任务间通信) 26.5 实验例程说明(中断方式) 26.6 总结 26.1 任务通知(TaskNotifications)介绍 (说明:第24,25,26和27章这部分基础知识是相同的) FreeRTOS每个已经创建的任务都有一个任务控制块(task control block),任务控制块就是一个结构体变量,用于记录任务的相关信息。结构体变量中有一个32位的变量成员ulNotifiedValue是专门用于任务通知的。 通过任务通知方式可以实现计数信号量,二值信号量,事件标志组和消息邮箱(消息邮箱就是消息队列长度为1的情况)。使用方法与前面章节讲解的事件标志组和信号量基本相同,只是换了不同的函数来实现。任务通知方式实现的计数信号量,二值信号量,事件标志组和消息邮箱是通过修改变量ulNotifiedValue实现的: (1)设置接收任务控制块中的变量ulNotifiedValue可以实现消息邮箱。 (2)如果接收任务控制块中的变量ulNotifiedValue还没有被其接收到,也可以用新数据覆盖原有数据,这就是覆盖方式的消息邮箱。 (3)设置接收任务控制块中的变量ulNotifiedValue的bit0-bit31数值可以实现事件标志组。 (4)设置接收任务控制块中的变量ulNotifiedValue数值进行加一或者减一操作可以实现计数信号量和二值信号量。 介绍了这么多,那么问题来了,采用这种方式有什么优势呢?根据官方的测试数据,唤醒由于信号量和事件标志组而处于阻塞态的任务,速度提升了45%,而且这种方式需要的RAM空间更小。但这种方式实现的信号量和事件标志组也有它的局限性,主要表现在以下两个方面: (1)任务通知方式仅可以用在只有一个任务等待信号量,消息邮箱或者事件标志组的情况,不过实际项目项目中这种情况也是最多的。 (2)使用任务通知方式实现的消息邮箱替代前面章节讲解的消息队列时,发送消息的任务不支持超时等待,即消息队列中的数据已经满了,可以等待消息队列有空间可以存新的数据,而任务通知方式实现的消息邮箱不支持超时等待。 |
|
相关推荐
|
|
26.2 任务事件标志组
前面第18章,我们对事件标志组进行了讲解。本章节讲解的任务事件标志组与第18章讲解的事件标志组要实现的功能是一样的,不同的是调用的函数和支持的事件标志个数,任务事件标志组支持32个事件标志设置,而第18章中介绍的事件标志组,每创建一个支持24个事件标志设置: (1)任务事件标志组的事件标志位是通过任务控制块中的一个32位变量ulNotifiedValue实现。第18章讲解的事件标志组创建后会有自己可以设置的事件标志位。 (2)任务事件标志组是通过函数xTaskNotifyWait()替代第18章讲解的函数xEventGroupWaitBits ()实现等待事件标志位被设置。 (3)任务事件标志组是通过函数xTaskNotify() 和 xTaskNotifyFromISR()替代第18章讲解的函数xEventGroupSetBits() 和 xEventGroupSetBitsFromISR实现对事件标志位的设置。 (4)第18章中讲解的函数xEventGroupSetBitsFromISR是通过给Daemon任务(定时器任务)发消息,在定时器任务中执行实际的操作,而我们本章节要介绍的函数xTaskNotifyFromISR是直接在中断服务程序里面执行操作,效率要高很多。 具体任务间任务事件标志组的实现过程和中断方式任务事件标志组的实现过程参看第18.1.2小节和18.1.3小节即可。实际项目中,如果使用事件标志组和任务事件标志组都能实现相应功能,强烈建议使用任务事件标志组。 |
|
|
|
|
|
26.3 任务事件标志组API函数
使用如下9个函数可以实现FreeRTOS的任务事件标志组: (1) xTaskNotifyGive() (2) vTaskNotifyGiveFromISR() (3) ulTaskNotifyTake() (4) xTaskNotify() (5) xTaskNotifyAndQuery() (6) xTaskNotifyAndQueryFromISR() (7) xTaskNotifyFromISR() (8) xTaskNotifyWait() (9) xTaskNotifyStateClear() 关于这9个函数的讲解及其使用方法可以看FreeRTOS在线版手册: 这里我们重点的说以下3个函数: (1) xTaskNotify (2) xTaskNotifyFromISR (3) xTaskNotifyWait 因为本章节配套的例子使用的是这3个函数。 |
|
|
|
|
|
26.3.1 函数xTaskNotify
函数原型: [url=]复制代码[/url]
函数描述: 函数xTaskNotify通过设置任务控制块中的变量ulNotifiedValue可以在任务代码中实现任务事件标志组,任务计数信号量,任务消息邮箱和任务二值信号量四种方式的消息通知(见26.1说明)。 (1)第1个参数是任务句柄。 (2)第2个参数是用来更新任务控制块中的32位变量ulNotifiedValue。 (3)第3个参数是任务通知模式设置,支持以下5个参数: (4)返回值,根据上面第3个参数的说明,将其设置为eSetValueWithoutOverwrite,有可能返回pdFALSE,其余所有情况都返回值pdPASS。 |
|
|
|
|
|
26.3.2 函数xTaskNotifyFromISR
函数原型: [url=]复制代码[/url]
函数描述: 函数xTaskNotifyFromISR通过设置任务控制块中的变量ulNotifiedValue可以在中断服务程序中实现任务事件标志组,任务计数信号量,任务消息邮箱和任务二值信号量四种方式的消息通知(见26.1说明)。 (1)第1个参数是任务句柄。 (2)第2个参数是用来更新任务控制块中的32位变量ulNotifiedValue。 (3)第3个参数是任务通知模式设置,支持以下5个参数: (4)第4个参数用于保存是否有高优先级任务准备就绪。如果函数执行完毕后,此参数的数值是pdTRUE,说明有高优先级任务要执行,否则没有。 (5)返回值,根据上面第3个参数的说明,将其设置为eSetValueWithoutOverwrite,有可能返回pdFALSE,其余所有情况都返回值pdPASS。 |
|
|
|
|
|
使用这个函数要注意以下问题:
1. 任务创建后,任务控制块中的变量ulNotifiedValue初始计数值是0。 2. 默认配置此函数可以使用的的宏定义已经在FreeRTOS.h文件中使能: #define configUSE_TASK_NOTIFICATIONS 1 当然,如果用户不需要使用任务通知功能相关的函数,可以在FreeRTOSConfig.h文件中配置此宏定义为0来禁止,这样创建的每个任务可以节省8个字节的需求。 3. 此函数是用于中断服务程序中调用的,故不可以在任务代码中调用此函数,任务代码中使用的是xTaskNotify。 4. 根据FreeRTOS的建议,实现二值信号量和计数信号量时使用函数vTaskNotifyGiveFromISR ()替代此函数xTaskNotifyFromISR()。 使用举例: 复制代码 static TaskHandle_t xHandleTaskMsgPro = NULL;/* 任务句柄,操作此句柄前一定要保证相应任务已经创建 */ /* ********************************************************************************************************* * 函 数 名: TIM2_IRQHandler * 功能说明: 定时器中断。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void TIM2_IRQHandler (void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; /* 中断消息处理,此处省略 */ …… xTaskNotifyFromISR(xHandleTaskMsgPro, /* 目标任务 */ BIT_0, /* 设置目标任务事件标志位bit0 */ eSetBits, /* 将目标任务的事件标志位与BIT_0进行或操作, 将结果赋值给事件标志位 */ &xHigherPriorityTaskWoken); /* 如果xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */ portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } |
|
|
|
|
|
26.3.3 函数xTaskNotifyWait
函数原型: 复制代码 BaseType_t xTaskNotifyWait( /* 设置函数执行前清零任务控制块中变量ulNotifiedValue那些位 */ uint32_t ulBitsToClearOnEntry, /*设置函数退出前清零任务控制块中变量ulNotifiedValue那些位 */ uint32_t ulBitsToClearOnExit, /* 保存任务控制块中的变量ulNotifiedValue到指针变量pulNotifiedValue所指向的存储单元 */ uint32_t *pulNotificationValue, /* 等待消息通知的最大等待时间 */ TickType_t xTicksToWait ); 函数描述: 函数xTaskNotifyWait可以在任务代码中实现任务事件标志组,任务计数信号量,任务消息邮箱和任务二值信号量四种方式的消息获取(见26.1说明)。 (1)第1个参数ulBitsToClearOnEntry用于函数执行之前,将任务控制块中的变量ulNotifiedValue进行如下操作 : ulNotifiedValue&= ~ulBitsToClearOnEntry 简单的说就是参数ulBitsToClearOnEntry哪个位是1,那么变量ulNotifiedValue的那个位就会被清零。比如ulBitsToClearOnEntry = 0x01表示将变量ulNotifiedValue的bit0清零,又比如ulBitsToClearOnEntry = 0xffffffff表示将变量ulNotifiedValue的所有位清零。 (2)第2个参数 ulBitsToClearOnExit用于函数退出前,将任务控制块中的变量ulNotifiedValue进行如下操作 : ulNotifiedValue&= ~ ulBitsToClearOnExit 简单的说就是参数ulBitsToClearOnExit哪个位是1,那么变量ulNotifiedValue的那个位就会被清零。比如ulBitsToClearOnExit= 0x01表示将变量ulNotifiedValue的bit0清零,又比如ulBitsToClearOnExit= 0xffffffff表示将变量ulNotifiedValue的所有位清零。 (3)第3个参数用于将任务控制块中的变量ulNotifiedValue保存到此参数指针所指向的存储单元。如果此参数没有用上,可以将其设置为NULL。 (4)第4个参数是没有消息时,等待消息的最大等待时间,单位系统时钟节拍。 (5)返回值,如果成功接收到消息返回pdTRUE,否则返回pdFALSE,比如在设置的超时时间内没有收到消息。 |
|
|
|
|
|
使用这个函数要注意以下问题:
1. 任务创建后,任务控制块中的变量ulNotifiedValue初始计数值是0。 2. 默认配置此函数可以使用的的宏定义已经在FreeRTOS.h文件中使能: #define configUSE_TASK_NOTIFICATIONS 1 当然,如果用户不需要使用任务通知功能相关的函数,可以在FreeRTOSConfig.h文件中配置此宏定义为0来禁止,这样创建的每个任务可以节省8个字节的需求。 3. 如果用户将FreeRTOSConfig.h文件中的宏定义INCLUDE_vTaskSuspend配置为1且第2个参数配置为portMAX_DELAY,那么此函数会永久等待直到消息可用。 4. 根据FreeRTOS的建议,实现二值信号量和计数信号量时使用函数ulTaskNotifyTake ()替代此函数xTaskNotifyWait ()。 |
|
|
|
|
|
使用举例:
复制代码 /* ********************************************************************************************************* * 函 数 名: vTaskMsgPro * 功能说明: 使用函数xTaskNotifyWait接收任务vTaskTaskUserIF发送的事件标志位设置 * 形 参: pvParameters 是在创建该任务时传递的形参 * 返 回 值: 无 * 优 先 级: 3 ********************************************************************************************************* */ static void vTaskMsgPro(void *pvParameters) { BaseType_t xResult; const TickType_t xMaxBlockTime = pdMS_TO_TICKS(500); /* 设置最大等待时间为500ms */ uint32_t ulValue; while(1) { /* 第一个参数 ulBitsToClearOnEntry的作用(函数执行前): ulNotifiedValue &= ~ulBitsToClearOnEntry 简单的说就是参数ulBitsToClearOnEntry那个位是1,那么ulNotifiedValue 的那个位就会被清零。 这里ulBitsToClearOnEntry = 0x00000000就是函数执行前保留所有位。 第二个参数 ulBitsToClearOnExit的作用(函数退出前): ulNotifiedValue &= ~ulBitsToClearOnExit 简单的说就是参数ulBitsToClearOnEntry那个位是1,那么ulNotifiedValue 的那个位就会被清零。 这里ulBitsToClearOnExi = 0xFFFFFFFF就是函数退出前清楚所有位。 注:ulNotifiedValue表示任务vTaskMsgPro的任务控制块里面的变量。 */ xResult = xTaskNotifyWait(0x00000000, 0xFFFFFFFF, &ulValue, /* 保存ulNotifiedValue到变量ulValue中 */ xMaxBlockTime); /* 最大允许延迟时间 */ if( xResult == pdPASS ) { /* 接收到消息,检测那个位被按下 */ if((ulValue & BIT_0) != 0) { printf("接收到K2按键按下消息, ulNotifiedValue = 0x%08xrn", ulValue); } if((ulValue & BIT_1) != 0) { printf("接收到K3按键按下消息, ulNotifiedValue = 0x%08xrn", ulValue); } } else { /* 超时 */ bsp_LedToggle(1); bsp_LedToggle(4); } } } |
|
|
|
|
|
26.4 实验例程说明(任务间通信)
26.4.1 STM32F103开发板实验 配套例子: V4-329_FreeRTOS实验_任务事件标注组 实验目的: 1. 学习FreeRTOS的任务通知实现事件标志组。 实验内容: 1. K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。 2. K2键按下,直接发送事件标志设置给任务vTaskMsgPro,置位bit0。 3. K3键按下,直接发送事件标志设置给任务vTaskMsgPro,置位bit1。 4. 各个任务实现的功能如下: vTaskUserIF任务 :按键消息处理。 vTaskLED任务 :LED闪烁。 vTaskMsgPro任务:使用函数xTaskNotifyWait接收任务vTaskTaskUserIF发送的事件标志位设置。 vTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。 |
|
|
|
|
|
FreeRTOS的配置:
FreeRTOSConfig.h文件中的配置如下: 复制代码 /* Ensure stdint is only used by the compiler, and not the assembler. */ #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) #include extern volatile uint32_t ulHighFrequencyTimerTicks; #endif #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 ) #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) #define configMAX_PRIORITIES ( 5 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 16 ) #define configUSE_TRACE_FACILITY 1 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 /* Run time and task stats gathering related definitions. */ #define configGENERATE_RUN_TIME_STATS 1 #define configUSE_STATS_FORMATTING_FUNCTIONS 1 #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() (ulHighFrequencyTimerTicks = 0ul) #define portGET_RUN_TIME_COUNTER_VALUE() ulHighFrequencyTimerTicks //#define portALT_GET_RUN_TIME_COUNTER_VALUE 1 /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) /* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */ #define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_uxTaskPriorityGet 1 #define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskCleanUpResources 0 #define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelay 1 /* Cortex-M specific definitions. */ #ifdef __NVIC_PRIO_BITS /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ #define configPRIO_BITS __NVIC_PRIO_BITS #else #define configPRIO_BITS 4 /* 15 priority levels */ #endif /* The lowest interrupt priority that can be used in a call to a "set priority" function. */ #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f /* The highest interrupt priority that can be used by any interrupt service routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER PRIORITY THAN THIS! (higher priorities are lower numeric values. */ #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01 |
|
|
|
|
|
几个重要选项说明:
1、#define configUSE_PREEMPTION 1 使能抢占式调度器 2、#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 ) 系统主频72MHz。 3、#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) 系统时钟节拍1KHz,即1ms。 4、#define configMAX_PRIORITIES ( 5 ) 定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。 5、#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ) 定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。 6、configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01 定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下: (1)使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。 (2)对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为0到15,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。 (3)这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为0x01表示用户可以在抢占式优先级为1到15的中断里面调用FreeRTOS的API函数,抢占式优先级为0的中断里面是不允许调用的。 |
|
|
|
|
|
FreeRTOS任务调试信息(按K1按键,串口打印):
上面截图中打印出来的任务状态字母B, R, D, S对应如下含义: #definetskBLOCKED_CHAR ( 'B' ) 任务阻塞 #definetskREADY_CHAR ( 'R' ) 任务就绪 #definetskDELETED_CHAR ( 'D' ) 任务删除 #definetskSUSPENDED_CHAR ( 'S' ) 任务挂起 |
|
|
|
|
|
程序设计:
任务栈大小分配: vTaskUserIF任务 :2048字节 vTaskLED任务 :2048字节 vTaskMsgPro任务 :2048字节 vTaskStart任务 :2048字节 任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的 #defineconfigTOTAL_HEAP_SIZE ( ( size_t )( 17 * 1024 ) ) 系统栈大小分配: |
|
|
|
|
|
FreeROTS初始化:
复制代码 /* ********************************************************************************************************* * 函 数 名: main * 功能说明: 标准c程序入口。 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ int main(void) { /* 在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。 这样做的好处是: 1. 防止执行的中断服务程序中有FreeRTOS的API函数。 2. 保证系统正常启动,不受别的中断影响。 3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。 在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1) 和cpsie i是等效的。 */ __set_PRIMASK(1); /* 硬件初始化 */ bsp_Init(); /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项 目中不要使用,因为这个功能比较影响系统实时性。 2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。 */ vSetupSysInfoTest(); /* 创建任务 */ AppTaskCreate(); /* 启动调度,开始执行任务 */ vTaskStartScheduler(); /* 如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的 heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小: #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ) */ while(1); } |
|
|
|
|
|
硬件外设初始化
硬件外设的初始化是在bsp.c文件实现: 复制代码 /* ********************************************************************************************************* * 函 数 名: bsp_Init * 功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。 * 全局变量。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void bsp_Init(void) { /* 由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。 启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。 系统时钟缺省配置为72MHz,如果需要更改,可以修改 system_stm32f10x.c 文件 */ /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); bsp_InitUart(); /* 初始化串口 */ bsp_InitLed(); /* 初始LED指示灯端口 */ bsp_InitKey(); /* 初始化按键 */ } |
|
|
|
|
|
FreeRTOS任务创建:
复制代码 /* ********************************************************************************************************* * 函 数 名: AppTaskCreate * 功能说明: 创建应用任务 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ static void AppTaskCreate (void) { xTaskCreate( vTaskTaskUserIF, /* 任务函数 */ "vTaskUserIF", /* 任务名 */ 512, /* 任务栈大小,单位word,也就是4字节 */ NULL, /* 任务参数 */ 1, /* 任务优先级*/ &xHandleTaskUserIF ); /* 任务句柄 */ xTaskCreate( vTaskLED, /* 任务函数 */ "vTaskLED", /* 任务名 */ 512, /* 任务栈大小,单位word,也就是4字节 */ NULL, /* 任务参数 */ 2, /* 任务优先级*/ &xHandleTaskLED ); /* 任务句柄 */ xTaskCreate( vTaskMsgPro, /* 任务函数 */ "vTaskMsgPro", /* 任务名 */ 512, /* 任务栈大小,单位word,也就是4字节 */ NULL, /* 任务参数 */ 3, /* 任务优先级*/ &xHandleTaskMsgPro ); /* 任务句柄 */ xTaskCreate( vTaskStart, /* 任务函数 */ "vTaskStart", /* 任务名 */ 512, /* 任务栈大小,单位word,也就是4字节 */ NULL, /* 任务参数 */ 4, /* 任务优先级*/ &xHandleTaskStart ); /* 任务句柄 */ } |
|
|
|
|
|
26.4.2 STM32F407开发板实验
配套例子: V5-329_FreeRTOS实验_任务事件标注组 实验目的: 1. 学习FreeRTOS的任务通知实现事件标志组。 实验内容: 1. K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。 2. K2键按下,直接发送事件标志设置给任务vTaskMsgPro,置位bit0。 3. K3键按下,直接发送事件标志设置给任务vTaskMsgPro,置位bit1。 4. 各个任务实现的功能如下: vTaskUserIF任务 :按键消息处理。 vTaskLED任务 :LED闪烁。 vTaskMsgPro任务:使用函数xTaskNotifyWait接收任务vTaskTaskUserIF发送的事件标志位设置。 vTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。 |
|
|
|
|
|
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-LCD显示图片编程示例之介绍mmap
238 浏览 0 评论
《DNESP32S3使用指南-IDF版_V1.6》第二章 常用的C语言知识点
629 浏览 0 评论
【RA-Eco-RA2E1-48PIN-V1.0开发板试用】(第三篇)ADC采集+PWM输出
552 浏览 0 评论
《DNK210使用指南 -CanMV版 V1.0》第四十五章 人脸识别实验
552 浏览 0 评论
1074 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11763 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 20:52 , Processed in 0.753674 second(s), Total 71, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号