main.c:
#include#include //标准C库文件,定义了各种类型的范围 #include "board.h" #include "led.h" #include "key.h" #include "uart.h" #include "tim_mrt.h" const uint32_t OscRateIn = MAIN_OSC_XTAL_FREQ_HZ; const uint32_t ExtRateIn = EXT_CLOCK_IN_FREQ_HZ; //系统复位 #define System_restart (LPC_SWM->PINENABLE0 = 0xffffffffUL) static void TIM_CallBack1(void); static void TIM_CallBack2(void); #include "FreeRTOSConfig.h" #include "FreeRTOS.h" #include "task.h" #include "event_groups.h"//事件头文件 #include "queue.h"//队列头文件 #include "semphr.h"//信号量头文件 #include "timers.h"//软件定时器头文件 static xTaskHandle LED_TaskHandle=NULL; static xTaskHandle KEY_TaskHandle=NULL; #define TASK_STACK_SIZE 32//每个任务的栈大小 static void prvSetupHardware(void) { SystemCoreClockUpdate(); DEBUGINIT(); led_Init() ; Key_INIT(); MRT_Init(); DEBUGOUT("%u MHzn",SystemCoreClock/1000000); Board_UARTPutSTR("build date: " __DATE__ " build time: " __TIME__ "n"); } static void LED_Task(void* parameter) { baseType_t xReturn=pdTRUE; u32 r_event=0;//接收事件 const TickType_t xMaxBlockTime = pdMS_TO_TICKS(500); while(1) { xReturn=xTaskNotifyWait(0x0,//进入函数的时候不清除任务 bit 0xFFFFFFFF,//退出函数的时候清除所有的 bitR &r_event,// 保存 ulNotifiedValue 到变量 xMaxBlockTime); if(pdTRUE ==xReturn) { printf("接收到消息邮箱数据 ulValue = %drn", r_event); } else Board_LED_Toggle(1); // vTaskDelay(200); } } static void KEY_Task(void* parameter) { // baseType_t xReturn =pdPASS; u8 key2=0; while(1) { u8 key=0; if(Scan_Key()) vTaskDelay(20); else continue; if(!Scan_Key())continue; else { key=Scan_Key(); key2=key; } while(Scan_Key()){};//等按键抬起 if(key2) { switch(key2) { case 1: { // printf ( "KEY1 被按下n" ); printf("K1键按下,启动单次定时器中断,100ms后在定时器中断给任务 LED_Task 发送消息邮箱数据 覆盖rn"); bsp_HardTimer(3,10, (void*)TIM_CallBack1); Board_LED_Toggle(6); }break; case 2: { // printf ( "KEY2 被按下n" ); printf("K2键按下,启动单次定时器中断,500ms后在定时器中断给任务 LED_Task 发送消息邮箱数据 非覆盖rn"); bsp_HardTimer(2, 2,(void*)TIM_CallBack2); Board_LED_Toggle(5); }break; case 3: { }break; default:break; } key2=0; } } } static void AppTaskCreate(void) { baseType_t xReturn = pdPASS; taskENTER_CRITICAL();//进入临界区,禁止中断打断 xReturn = xTaskCreate( LED_Task, "LED_Task", TASK_STACK_SIZE*6, NULL, 2, &LED_TaskHandle); if (pdPASS == xReturn) printf("创建 Receive1_Task 任务成功!rn"); xReturn = xTaskCreate( KEY_Task, "KEY_Task", TASK_STACK_SIZE*6, NULL, 1, &KEY_TaskHandle); if (pdPASS == xReturn) printf("创建 Send_Task 任务成功!rn"); taskEXIT_CRITICAL(); //退出临界区 } int main(void) { prvSetupHardware(); Board_UARTPutSTR("LPC824 FreeRTOS 任务通知任务间通信 n"); AppTaskCreate(); vTaskStartScheduler();//任务调度 while (1) { printf("FreeRTOS 运行失败nr"); } } static uint32_t g_uiCount = 0; static void TIM_CallBack1(void) { baseType_t xHigherPriorityTaskWoken = pdFALSE; xTaskNotifyFromISR(LED_TaskHandle,//这里是句柄,不是函数名,不然会进入硬件错误 g_uiCount++, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); if(pdTRUE ==xHigherPriorityTaskWoken) portYIELD_FROM_ISR(xHigherPriorityTaskWoken); Board_LED_Toggle(3); } static void TIM_CallBack2(void) { baseType_t xHigherPriorityTaskWoken = pdFALSE; xTaskNotifyFromISR(LED_TaskHandle,//这里是句柄,不是函数名,不然会进入硬件错误 g_uiCount++, eSetValueWithoutOverwrite, &xHigherPriorityTaskWoken); if(pdTRUE ==xHigherPriorityTaskWoken) portYIELD_FROM_ISR(xHigherPriorityTaskWoken); Board_LED_Toggle(4); } void HardFault_Handler(void) { printf("硬件错误中断n"); while(1) { } }
tim_mrt.h:
#ifndef _TIM_MRT_H_ #define _TIM_MRT_H_ void MRT_Init(void); void setupMRT(uint8_t ch, MRT_MODE_T mode, uint32_t rate); void bsp_HardTimer(u8 ch,uint32_t frequency_Hz, void * _pCallBack); #endif
tim_mrt.c:
#include "board.h" #include "tim_mrt.h" static void (*s_TIM_CallBack0)(void); static void (*s_TIM_CallBack1)(void); static void (*s_TIM_CallBack2)(void); static void (*s_TIM_CallBack3)(void); //bool Ms500; //static uint32_t t01 , t3; //static uint32_t t2; void setupMRT(uint8_t ch, MRT_MODE_T mode, uint32_t rate) { LPC_MRT_CH_T *pMRT; pMRT = Chip_MRT_GetRegPtr(ch); //返回定时器的指针 //12MHz Chip_MRT_SetInterval(pMRT, (Chip_Clock_GetSystemClockRate() / rate) | MRT_INTVAL_LOAD);//立即加载 Chip_MRT_SetMode(pMRT, mode); Chip_MRT_IntClear(pMRT); Chip_MRT_SetEnabled(pMRT); } void MRT_Init(void) { Chip_MRT_Init();//启用MRT时钟,复位MET Chip_MRT_SetDisabled(Chip_MRT_GetRegPtr(3));//禁用定时器通道3 Chip_MRT_SetDisabled(Chip_MRT_GetRegPtr(2));//禁用定时器通道2 NVIC_EnableIRQ(MRT_IRQn); //启用定时器外设中断 //通道初始化 // setupMRT(2, MRT_MODE_REPEAT, 100); //100Hz,10ms循环 // setupMRT(3, MRT_MODE_ONESHOT, 2); //2Hz单次,中断只发生一次,需要再次赋值。 // setupMRT(3, MRT_MODE_REPEAT, 1); //1Hz,1s循环 } void MRT_IRQHandler(void) { uint32_t int_pend; int_pend = Chip_MRT_GetIntPending(); Chip_MRT_ClearIntPending(int_pend); //判断中断通道0和1 if (int_pend & (MRTn_INTFLAG(0) | MRTn_INTFLAG(1))) { Board_LED_Set(4, true); s_TIM_CallBack0(); s_TIM_CallBack1(); } //判断中断通道2 if (int_pend & (MRTn_INTFLAG(2))) { s_TIM_CallBack2(); // t2++; } //判断中断通道3 if (int_pend & (MRTn_INTFLAG(3))) { s_TIM_CallBack3(); } } void bsp_HardTimer(u8 ch,uint32_t frequency_Hz, void * _pCallBack) { switch(ch) { case 0: {}break; case 1:{}break; case 2: { //因为函数指针赋值后才能正常运行,所以必须在调用时再初始化。 s_TIM_CallBack2=(void (*)(void))_pCallBack; setupMRT(2, MRT_MODE_ONESHOT, frequency_Hz); //单次 }break; case 3: { s_TIM_CallBack3=(void (*)(void))_pCallBack; // setupMRT(3, MRT_MODE_REPEAT, frequency_Hz); //循环 setupMRT(3, MRT_MODE_ONESHOT, frequency_Hz); //单次 }break; default:break; } }
验通过函数xTaskNotifyFromISR和xTaskNotifyWait实现消息邮箱的中断方式功能。
K1键按下,启动单次定时器中断,100ms后在定时器中断给任务LED_Task发送消息邮箱数据。
K2键按下,启动单次定时器中断,500ms后在定时器中断给任务LED_Task发送消息邮箱数据。实验现象:
key按键任务里面,当KEY1和KEY2按下后,LED任务打印出通知值。
使用函数:
发送 xTaskNotifyFromISR();
接收 xTaskNotifyWait();
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)