24 freertos信号量-二值信号量-中断方式

二十四、freertos信号量-二值信号量-中断方式

源码:

main.c

/**
1. 学习FreeRTOS的二值信号量(中断方式)
2. 使用二值信号量实现任务同步功能
**/
#include 
#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) /**/
/***************************************************************/
static void TIM_CallBack1(void);



#include "FreeRTOSConfig.h"
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"//事件头文件
#include "queue.h"//队列头文件
#include "semphr.h"//信号量头文件


#define TASK_STACK_SIZE 32
/**************************** 任务句柄 ********************************/
/* 
 * 任务句柄是一个指针,用于指向一个任务。
 */

static TaskHandle_t LED1_Task_Handle= NULL;	
static xTaskHandle KEY_Task_Handle = NULL;	
static xSemaphoreHandle BinarySem_Handle = NULL;



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

	SystemCoreClockUpdate();

	DEBUGINIT();
	led_Init() ;	
	Key_INIT();
	MRT_Init();

	Board_UARTPutSTR("build date: " __DATE__ " build time: " __TIME__ "\n");

}

/*
*********************************************************************************************************
*	函 数 名: vKEY_task
*	功能说明: 按键任务
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
*********************************************************************************************************
*/
static void vKEY_task(void* pvParameters)
{

	uint8_t pcWriteBuffer[200];


​	 
	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("=================================================\r\n");
					printf("任务名      任务状态 优先级   剩余栈 任务序号\r\n");
					vTaskList((char *)&pcWriteBuffer);
					printf("%s\r\n", pcWriteBuffer);
				 
				}break;
				case 2:
				{
					printf("K2键按下,启动单次定时器中断,100ms后在定时器中断给任务vTaskMsgPro发送消息\r\n");
					bsp_HardTimer(2,(void *)TIM_CallBack1);
	
				}break;
				case 3:
				{


 					
				}break;
				default:break;
			}
			key2=0;
		}}
}

/**********************************************************************
  * @ 函数名  : vLED_Task0
  * @ 功能说明: LED_Task任务主体,接收任务 vKEY_task 发送的消息队列数据(xQueue2)
  * @ 参数    :   
  * @ 返回值  : 无
    ********************************************************************/

static void vLED1_Task (void *pvParameters)
{
	
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = 500;
	/* 获取当前的系统时间 */
	xLastWakeTime = xTaskGetTickCount();
	 
	while (1) {
		
		Board_LED_Toggle(0);
		vTaskDelayUntil(&xLastWakeTime, xFrequency);
	
	}

}

/*
*********************************************************************************************************
*	函 数 名: vTaskMsgPro
*	功能说明: 使用函数 xQueueReceive 接收任务 vKEY_task 发送的消息队列数据(xQueue1)
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 3  
*********************************************************************************************************
*/
static void vTaskMsgPro(void *pvParameters)
{
	BaseType_t xResult;
	const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300); /* 设置最大等待时间为300ms */
	
    while(1)
    {
    	/* 获取K2按键按下的信号 */
    	xResult = xSemaphoreTake(BinarySem_Handle,xMaxBlockTime); 
    	/* 成功接收,并通过串口将数据打印出来 */
    	if(xResult == pdTRUE)
    	{
    		/* 接收到同步信号 */
    		printf("接收到同步信号\r\n");
    		Board_LED_Toggle(1);
    	}
    	else
    	{
    		/* 超时 */
    		
    	}
    	
    }
}

/*
*********************************************************************************************************
*	函 数 名: AppObjCreate
*	功能说明: 创建任务通信机制
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void AppObjCreate (void)
{
	/* 创建二值信号量,首次创建信号量计数值是0 */
	BinarySem_Handle = xSemaphoreCreateBinary();
	if(NULL == BinarySem_Handle)
 	{
		/* 没有创建成功*/
		DEBUGSTR("二值信号量创建失败\n");
	}
	
	
}
/***********************************************************************
  * @ 函数名  : AppTaskCreate
  * @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
  * @ 参数    : 无  
  * @ 返回值  : 无
    **********************************************************************/
	static void AppTaskCreate()
	{
	BaseType_t xReturn=pdPASS;/*定义任务返回值*/
	
	taskENTER_CRITICAL();//进入临界区,禁止中断打断


	xReturn=xTaskCreate(vLED1_Task, 
						"vLED1_Task",
						TASK_STACK_SIZE*2, 
						NULL, 
						(tskIDLE_PRIORITY + 1UL),
						(TaskHandle_t *) &LED1_Task_Handle);
	
	xReturn=xTaskCreate(vKEY_task, 
						"vKEY_Task",
						TASK_STACK_SIZE*4, 
						NULL, 
						(tskIDLE_PRIORITY + 1UL),
						(TaskHandle_t *) &KEY_Task_Handle);
	
	xReturn=xTaskCreate(vTaskMsgPro, 
						"vTaskMsgPro",
						TASK_STACK_SIZE*5, 
						NULL, 
						(tskIDLE_PRIORITY + 3UL),
						NULL);
				
	if(pdPASS==xReturn)
	{
		printf("创建LED_Task任务成功\r\n");
	}taskEXIT_CRITICAL(); //退出临界区


}

/**
 * @brief	main routine for blinky example
 * @return	Function should not exit.
 */
	int main(void)
	{
	
	prvSetupHardware();
	Board_UARTPutSTR("LPC824 FreeRTOS 任务管理\n\r");
	printf("Key按下中断中发送信号量\r\n");

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

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

 	}}


/*
*********************************************************************************************************
*	函 数 名: TIM_CallBack1和TIM_CallBack2
*	功能说明: 定时器中断的回调函数,此函数被bsp_HardTimer所调用。		  			  
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void TIM_CallBack1(void)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	
	

	/* 发送同步信号 */
	xSemaphoreGiveFromISR(BinarySem_Handle, &xHigherPriorityTaskWoken);/* 如果xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);					  


}

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, void * _pCallBack);

#endif

tim_mrt.c

/*
 * 	注意,MRT定时器有4个独立通道,但共用中断号10。
 */
#include "board.h"
#include "tim_mrt.h"
/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/

/* 保存 TIM定时中断到后执行的回调函数指针 */
static void (*s_TIM_CallBack0)(void);
static void (*s_TIM_CallBack1)(void);
static void (*s_TIM_CallBack2)(void);
static void (*s_TIM_CallBack3)(void);

 

/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

 
 
/* Interrupt fire reference counters for t0/1, t2, and t3 */
//bool Ms500;
//static uint32_t t01 , t3;
//static uint32_t t2;

/*****************************************************************************
 * Private functions
 ****************************************************************************/

/*  设置定时器

参数:
ch :定时器通道(0,1,2,3)
mode :模式(单次或者循环)
rate :速率,数字越小,间隔越长。
	--	1 表示 1Hz,即1s。
	--	2 表示 2Hz,即500ms。
	--	100表示100Hz,即10ms。
*/
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);
	/* Clear pending interrupt and enable timer */
	Chip_MRT_IntClear(pMRT); 
	Chip_MRT_SetEnabled(pMRT); 
}

/*****************************************************************************
 * Public functions
 ****************************************************************************/

/**
 * @brief	MRT example main function
 * @return	Status (This function will not return)
 */
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); //10ms循环
//	setupMRT(3, MRT_MODE_ONESHOT, 2); //单次,中断只发生一次,需要再次赋值。
//	setupMRT(3, MRT_MODE_REPEAT, 1); //1s循环


}

/**
 * @brief	Handle interrupt from MRT
 * @return	Nothing
 */
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();

	}
}

/*
*********************************************************************************************************
*	函 数 名: bsp_HardTimer
*	功能说明: 定时时间到后执行回调函数。
*	形    参: 
			ch: 多速率定时器通道(0,1,2,3)
*             _pCallBack : 定时时间到后,被执行的函数
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_HardTimer(u8 ch,void * _pCallBack)
{
	
	switch(ch)
	{
		case 0:	{}break;
		case 1:{}break;
		case 2:
		{
			//因为函数指针赋值后才能正常运行,所以必须在调用时再初始化。
			setupMRT(2, MRT_MODE_ONESHOT, 100); //100ms单次
			s_TIM_CallBack2=(void (*)(void))_pCallBack;
		}break;
		case 3:
		{
			setupMRT(3, MRT_MODE_ONESHOT, 1); //1s单次
			s_TIM_CallBack3=(void (*)(void))_pCallBack;
		}break;
		default:break;
	}
	 
	
}
/**
*END_TMI
*/

你可能感兴趣的:(FreeRTOS,单片机,stm32,c语言,嵌入式硬件)