源码:
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
*/