33 freertos任务通知--代替消息队列(任务邮箱)-中断

33 freertos任务通知--代替消息队列(任务邮箱)-中断,第1张

33 freertos任务通知--代替消息队列(任务邮箱)-中断 三十三、LPC824_freertos任务通知–代替消息队列(任务邮箱)-中断

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();

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5702371.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存