39 freertos多事件等待

三十九、 freertos多事件等待

/**
**************************************************************************************************/
#include <stdio.h>
#include <limits.h>//标准C库文件,定义了各种类型的范围
#include "board.h"
#include "led.h"
#include "key.h"
#include "uart.h"
#include "tim_mrt.h"

/**********************系统相关和硬件接口**************************************/
/*** System oscillator rate and clock rate on the CLKIN pin  ****/
/**/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) /**/
/**********************End**************************************/

//static void TIM_CallBack1(void);
//static void TIM_CallBack2(void);

/**********************FreeRTOS操作系统头文件**************************************/
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"//事件头文件
#include "queue.h"//队列头文件
#include "semphr.h"//信号量头文件
#include "timers.h"//软件定时器头文件
/**********************End**************************************/

/**************************** 任务句柄 ********************************/

static xTaskHandle LED_TaskHandle=NULL;
static xTaskHandle KEY_TaskHandle=NULL;
static xTaskHandle xHandleTaskMsgPro = NULL;
static xSemaphoreHandle		Semaphore_Handle=NULL;
static xQueueHandle		xQueue1 =NULL;
static xQueueHandle		xQueue2	=NULL;
static xQueueSetHandle	xQueueSet=NULL;

	
/*************************** 宏定义 ************************************/
#define TASK_STACK_SIZE 32//每个任务的栈大小


#define QUEUE_LENGTH_1	10	/*消息队列长度*/
#define	QUEUE_LENGTH_2	10	

#define BINARY_SEMAPHORE_LENGTH		1/*二值信号量*/

#define ITEM_SIZE_QUEUE_1		sizeof(uint32_t)/*每个消息队列占用的字节*/
#define	ITEM_SIZE_QUEUE_2		sizeof(uint8_t)
	
/* 添加到Queue Set的总长度 */
#define COMBINED_LENGTH (QUEUE_LENGTH_1 + QUEUE_LENGTH_2 + BINARY_SEMAPHORE_LENGTH)



/* Sets up system hardware 
**********************************************************************
  * @ 函数名  : BSP_Init
  * @ 功能说明: 板级外设初始化,所有板子上的初始化均可放在这个函数里面
  * @ 参数    :   
  * @ 返回值  : 无
*********************************************************************/
static void prvSetupHardware(void)
{

	SystemCoreClockUpdate();

	DEBUGINIT();
	led_Init() ;	
	Key_INIT();
	MRT_Init();
	DEBUGOUT("%u MHz\n",SystemCoreClock/1000000);
	Board_UARTPutSTR("build date: " __DATE__ " build time: " __TIME__ "\n");

}

/**********************************************************************
 * @ 函数名 :  
 * @ 功能说明:  接收发送通知
 * @ 参数 :
 * @ 返回值 : 无
 ********************************************************************/
static void LED_Task(void* parameter)
{
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = 500;
	/* 获取当前的系统时间 */
    xLastWakeTime = xTaskGetTickCount();
	while(1)
	{

		Board_LED_Toggle(0);
		/* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
		vTaskDelayUntil(&xLastWakeTime, xFrequency);
	}
}


/**********************************************************************
 * @ 函数名 :   
 * @ 功能说明: 发送任务
 * @ 参数 :
 * @ 返回值 : 无
 ********************************************************************/
static void KEY_Task(void* parameter)
{

	uint8_t ulCount = 0;
	u8 ucCount=0;
	
	u8 ucKeyCode=0;
	while(1)
	{
		u8 key=0;
		if(Scan_Key())
			vTaskDelay(20);
		else continue;
		if(!Scan_Key())continue;
		else
		{
			key=Scan_Key();
			ucKeyCode=key;
		}
		while(Scan_Key()){};//等按键抬起
		
		if(ucKeyCode)
		{

			switch(ucKeyCode)
			{
				case 1:
				{
					/* K1键按下 */
//					printf ( "KEY1 被按下\n" );
					Board_LED_Toggle(6);

					printf("K1键按下,直接发送同步信号给任务vTaskMsgPro\r\n");
					xSemaphoreGive(Semaphore_Handle);

				}break;
				case 2:
				{
					 /* K2键按下 */
//					printf ( "k2 被按下\n" );
					Board_LED_Toggle(5);
					ulCount++;
					/* 向消息队列发数据,如果消息队列满了,等待10个时钟节拍 */
					if( xQueueSend(xQueue1,
								   (void *) &ulCount,
								   (TickType_t)10) != pdPASS )
					{
						/* 发送失败,即使等待了10个时钟节拍 */
						printf("K2键按下,向xQueue1发送数据失败,即使等待了10个时钟节拍\r\n");
					}
					else
					{
						/* 发送成功 */
						printf("K2键按下,向xQueue1发送数据成功\r\n");						
					}
					
					
				}break;
				case 3:
				{
					/* K3键按下*/
					ucCount++;
					/* 向消息队列发数据,如果消息队列满了,等待10个时钟节拍 */
					if( xQueueSend(xQueue2,
							   (void *) &ucCount,
							   (TickType_t)10) != pdPASS )
					{
						/* 发送失败,即使等待了10个时钟节拍 */
						printf("K3键按下,向xQueue1发送数据失败,即使等待了10个时钟节拍\r\n");
					}
					else
					{
						/* 发送成功 */
						printf("K3键按下,向xQueue1发送数据成功\r\n");						
					}
				}break;
				default:break;
			}
			ucKeyCode=0;
		}
			
	}
}

/*
*********************************************************************************************************
*	函 数 名: vTaskMsgPro
*	功能说明: 使用函数xQueueSelectFromSet接收任务 发送的多个事件,信号量和消息队列
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 3  
*********************************************************************************************************
*/
static void vTaskMsgPro(void *pvParameters)
{
	QueueSetMemberHandle_t xActivatedMember;
	uint32_t ulQueueMsgValue;
	uint8_t  ucQueueMsgValue;
	const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300); /* 设置最大等待时间为300ms等同300/portTICK_RATE_MS */
	
	while(1)
	{
		xActivatedMember =xQueueSelectFromSet(xQueueSet,xMaxBlockTime);

		 /* 根据xActivatedMember判断接受到的消息类型 */
        if(xActivatedMember == xQueue1)
        {
			/* 消息队列1接收到消息 */
			xQueueReceive(xActivatedMember, &ulQueueMsgValue, 0);
			printf("消息队列1接收到消息 ulQueueMsgValue = %d\r\n", ulQueueMsgValue);
			
		}
		else if(xActivatedMember == xQueue2)
        {
			/* 消息队列2接收到消息 */
			xQueueReceive(xActivatedMember, &ucQueueMsgValue, 0);
			printf("消息队列2接收到消息 ucQueueMsgValue = %d\r\n", ucQueueMsgValue);
			
		}
		else if(xActivatedMember == Semaphore_Handle)
        {
			/* 接收到信号量 */	
			xSemaphoreTake(xActivatedMember, 0);
			printf("接收到信号量\r\n");   
		}
		else
		{
			Board_LED_Toggle(2);
		}
	}
	
}
/***********************************************************************
  * @ 函数名  : AppTaskCreate
  * @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
  * @ 参数    : 无  
  * @ 返回值  : 无
  **********************************************************************/
static void AppTaskCreate(void)
{
	BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
	taskENTER_CRITICAL();//进入临界区,禁止中断打断
	
	xReturn = xTaskCreate(	 LED_Task,
							"LED_Task",
							TASK_STACK_SIZE*2,
							NULL,
							2,
							&LED_TaskHandle);
	if (pdPASS == xReturn)
		printf("创建 Receive1_Task 任务成功!\r\n");
	

	xReturn = xTaskCreate(	 KEY_Task,
							"KEY_Task",
							TASK_STACK_SIZE*4,
							NULL,
							1,
							&KEY_TaskHandle);
	if (pdPASS == xReturn)
		printf("创建 KEY_Task 任务成功!\r\n");
	
	xReturn=xTaskCreate( vTaskMsgPro,     		/* 任务函数  */
                 "vTaskMsgPro",   		/* 任务名    */
                 512,             		/* 任务栈大小,单位word,也就是4字节 */
                 NULL,           		/* 任务参数  */
                 3,               		/* 任务优先级*/
                 &xHandleTaskMsgPro );  /* 任务句柄  */
	if (pdPASS == xReturn)
		printf("创建 vTaskMsgPro 任务成功!\r\n");
	
	taskEXIT_CRITICAL(); //退出临界区	

}
/*
*********************************************************************************************************
*	函 数 名: AppObjCreate
*	功能说明: 创建任务通信机制
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/

static void AppObjCreate (void)
{
	/* 创建二值信号量,首次创建信号量计数值是0 */
	Semaphore_Handle = xSemaphoreCreateBinary();
	if(NULL==Semaphore_Handle)
	{
		DEBUGSTR("创建信号量失败\n");
	}
	
	/* 创建QueuSet */
	xQueueSet =xQueueCreateSet(COMBINED_LENGTH);
	if(NULL==xQueueSet)
	{
		DEBUGSTR("创建QueuSet失败\n");
	}
	
	 /* 创建消息队列 */
    xQueue1 = xQueueCreate(QUEUE_LENGTH_1, ITEM_SIZE_QUEUE_1);
	if(xQueue1 == NULL)
    {
        /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
		DEBUGSTR("创建信号量失败\n");
	}
	xQueue2 = xQueueCreate(QUEUE_LENGTH_2, ITEM_SIZE_QUEUE_2);
	if(xQueue2 == NULL)
    {
        /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
		DEBUGSTR("创建信号量失败\n");
	}
	 /* 添加到queue set时,消息队列和信号量必须为空*/
	/* 添加消息队列和信号量到Queue Set */
	xQueueAddToSet(xQueue1, xQueueSet);
	xQueueAddToSet(xQueue2, xQueueSet);
	xQueueAddToSet(Semaphore_Handle, xQueueSet);
	
}
/**
 * @brief	main routine for blinky example
 * @return	Function should not exit.
 */
int main(void)
{
	
	prvSetupHardware();
	Board_UARTPutSTR("LPC824 FreeRTOS 任务通知任务间通信 \n");
	DEBUGSTR("多事件等待\n");
	

	AppTaskCreate();
	/* 创建任务通信机制 */
	AppObjCreate();
	
	vTaskStartScheduler();//任务调度

	/* Loop forever */
	while (1) {
			printf("FreeRTOS 运行失败\n\r");
 	}
	
	
}

/******************
*函数名 : HardFault_Handler
*功能 	:硬件错误时会跳进这里
*说明 : 
******(1)可能是内存溢出。
******(2)可能是开启了中断,但没有中断函数。
******(3)可能指针赋值错误,最有可能是函数指针赋值错误。
******************/
void HardFault_Handler(void)
{
	printf("硬件错误中断\n");
	while(1)
	{

	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值