二十五、freertos信号量-计数信号量
/**
**************************************************************************************************/
#include <stdio.h>
#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) /**/
/***************************************************************/
#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; /* LED任务句柄 */
static xTaskHandle KEY_Task_Handle = NULL;
static xSemaphoreHandle CountSem_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");
}
/**********************************************************************
* @ 函数名 : vLED_Task0
* @ 功能说明: LED_Task任务主体,
* @ 参数 :
* @ 返回值 : 无
********************************************************************/
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);
}
}
/*
*********************************************************************************************************
* 函 数 名: vKEY_task
* 功能说明: 按键任务
* 形 参: pvParameters 是在创建该任务时传递的形参
* 返 回 值: 无
* 优 先 级: 1 (数值越小优先级越低,这个跟uCOS相反)
*********************************************************************************************************
*/
static void vKEY_task(void* pvParameters)
{
BaseType_t xReturn = pdTRUE;
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:
{
/* K2键按下 */
printf("K2 键按下,获取信号量\r\n");
xReturn = xSemaphoreTake(CountSem_Handle, /* 计数信号量句柄 */
0); /* 等待时间: 0 */
if ( pdTRUE == xReturn )
{
printf( "获取成功,成功申请到停车位。 \n" );
}
else
{
printf( "获取失败,不好意思,现在停车场已满! \n" );
}
}break;
case 3:
{
/* K3键按下*/
}break;
default:break;
}
key2=0;
}
}
}
/*
*********************************************************************************************************
* 函 数 名: vTaskMsgPro
* 功能说明: 使用函数
* 形 参: pvParameters 是在创建该任务时传递的形参
* 返 回 值: 无
* 优 先 级: 3
*********************************************************************************************************
*/
static void vTaskMsgPro(void *pvParameters)
{
BaseType_t xReturn = pdTRUE;
u8 key;
while(1)
{
if(Scan_Key())
{
key=Scan_Key();
}
while(Scan_Key());
if(3==key)
{
key=0;
printf("K3 键按下,释放信号量\r\n");
xReturn = xSemaphoreGive(CountSem_Handle);//给出计数信号量
if ( pdTRUE == xReturn )
{
printf( "释放成功,释放1个停车位。 \n" );
}
else
{
printf( "释放失败,已无车位可以释放! \n" );
}
}
vTaskDelay(20);
}
}
/*
*********************************************************************************************************
* 函 数 名: AppObjCreate
* 功能说明: 创建任务通信机制
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void AppObjCreate (void)
{
/* 初始化有5个可用资源,当前可用资源为5,*/
CountSem_Handle = xSemaphoreCreateCounting(5,5);
if(NULL != CountSem_Handle)
DEBUGOUT("计数信号量创建成功 \n");
else{}
}
/***********************************************************************
* @ 函数名 : 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 + 1UL),
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("车位默认值为 5 个,按下 KEY1 申请车位,按下 KEY2 释放车位!\r\n");
AppTaskCreate();
/* 创建任务通信机制 */
AppObjCreate();
vTaskStartScheduler();//任务调度
/* Loop forever */
while (1) {
printf("FreeRTOS 运行失败\n\r");
}
}
计数信号量
在创建信号量的时候初始化 5 个可用的信号量,并且创建了两个任务:
一个是获取信号量任务,一个是释放信号量任务,两个任务独立运行,
获取信号量任务是通过
按下 KEY1 按键进行信号量的获取,模拟停车场停车操作,其等待时间是 0,在串口调试助手输出相应信息。
释放信号量任务则是信号量的释放,释放信号量任务也是通过
按下 KEY2 按键进行信号量的释放,模拟停车场取车操作。