信号量——互斥信号量
互斥信号量
简介
解决了优先级翻转问题。释放信号量和获取信号量与数值信号量和二值信号量一样。
程序
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "lcd.h"
#include "key.h"
#include "beep.h"
#include "string.h"
#include "malloc.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 256
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//ÈÎÎñÓÅÏȼ¶
#define LOW_TASK_PRIO 2
//ÈÎÎñ¶ÑÕ»´óС
#define LOW_STK_SIZE 256
//ÈÎÎñ¾ä±ú
TaskHandle_t LowTask_Handler;
//ÈÎÎñº¯Êý
void low_task(void *pvParameters);
//ÈÎÎñÓÅÏȼ¶
#define MIDDLE_TASK_PRIO 3
//ÈÎÎñ¶ÑÕ»´óС
#define MIDDLE_STK_SIZE 256
//ÈÎÎñ¾ä±ú
TaskHandle_t MiddleTask_Handler;
//ÈÎÎñº¯Êý
void middle_task(void *pvParameters);
//ÈÎÎñÓÅÏȼ¶
#define HIGH_TASK_PRIO 4
//ÈÎÎñ¶ÑÕ»´óС
#define HIGH_STK_SIZE 256
//ÈÎÎñ¾ä±ú
TaskHandle_t HighTask_Handler;
//ÈÎÎñº¯Êý
void high_task(void *pvParameters);
//互斥信号量句柄
SemaphoreHandle_t MutexSemaphore; //»¥³âÐźÅÁ¿
//LCDË¢ÆÁʱʹÓõÄÑÕÉ«
int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED,
GRED, GBLUE, RED, MAGENTA,
GREEN, CYAN, YELLOW,BROWN,
BRRED, GRAY };
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//ÉèÖÃϵͳÖжÏÓÅÏȼ¶·Ö×é4
delay_init(168); //³õʼ»¯ÑÓʱº¯Êý
uart_init(115200); //³õʼ»¯´®¿Ú
LED_Init(); //³õʼ»¯LED¶Ë¿Ú
KEY_Init(); //³õʼ»¯°´¼ü
BEEP_Init(); //³õʼ»¯·äÃùÆ÷
LCD_Init(); //³õʼ»¯LCD
my_mem_init(SRAMIN); //³õʼ»¯ÄÚ²¿ÄÚ´æ³Ø
POINT_COLOR = RED;
LCD_ShowString(30,10,200,16,16,"ATK STM32F103/407");
LCD_ShowString(30,30,200,16,16,"FreeRTOS Examp 14-4");
LCD_ShowString(30,50,200,16,16,"Mutex Semaphore");
LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,90,200,16,16,"2016/11/25");
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //ÈÎÎñº¯Êý
(const char* )"start_task", //ÈÎÎñÃû³Æ
(uint16_t )START_STK_SIZE, //ÈÎÎñ¶ÑÕ»´óС
(void* )NULL, //´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
(UBaseType_t )START_TASK_PRIO, //ÈÎÎñÓÅÏȼ¶
(TaskHandle_t* )&StartTask_Handler); //ÈÎÎñ¾ä±ú
vTaskStartScheduler(); //开启任务调度器
}
//开始任务
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建互斥信号量
MutexSemaphore=xSemaphoreCreateMutex();
xTaskCreate((TaskFunction_t )high_task,
(const char* )"high_task",
(uint16_t )HIGH_STK_SIZE,
(void* )NULL,
(UBaseType_t )HIGH_TASK_PRIO,
(TaskHandle_t* )&HighTask_Handler);
xTaskCreate((TaskFunction_t )middle_task,
(const char* )"middle_task",
(uint16_t )MIDDLE_STK_SIZE,
(void* )NULL,
(UBaseType_t )MIDDLE_TASK_PRIO,
(TaskHandle_t* )&MiddleTask_Handler);
xTaskCreate((TaskFunction_t )low_task,
(const char* )"low_task",
(uint16_t )LOW_STK_SIZE,
(void* )NULL,
(UBaseType_t )LOW_TASK_PRIO,
(TaskHandle_t* )&LowTask_Handler);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL(); //退出临界区
}
//¸高优先级任务
void high_task(void *pvParameters)
{
u8 num;
POINT_COLOR = BLACK;
LCD_DrawRectangle(5,110,115,314);
LCD_DrawLine(5,130,115,130);
POINT_COLOR = BLUE;
LCD_ShowString(6,111,110,16,16,"High Task");
while(1)
{
vTaskDelay(500);
num++;
printf("high task Pend Sem\r\n");
xSemaphoreTake(MutexSemaphore,portMAX_DELAY); //获取互斥信号量
printf("high task Running!\r\n");
LCD_Fill(6,131,114,313,lcd_discolor[num%14]);
LED1=!LED1;
xSemaphoreGive(MutexSemaphore); //释放信号量
vTaskDelay(500);
}
}
//中等优先级任务
void middle_task(void *pvParameters)
{
u8 num;
POINT_COLOR = BLACK;
LCD_DrawRectangle(125,110,234,314);
LCD_DrawLine(125,130,234,130);
POINT_COLOR = BLUE;
LCD_ShowString(126,111,110,16,16,"Middle Task");
while(1)
{
num++;
printf("middle task Running!\r\n");
LCD_Fill(126,131,233,313,lcd_discolor[13-num%14]); //填充区域
LED0=!LED0;
vTaskDelay(1000);
}
}
//低优先级任务
void low_task(void *pvParameters)
{
static u32 times;
while(1)
{
xSemaphoreTake(MutexSemaphore,portMAX_DELAY); //获取互斥信号量
printf("low task Running!\r\n");
for(times=0;times<20000000;times++) //模拟低优先级任务
{
taskYIELD(); //发起任务调度
}
xSemaphoreGive(MutexSemaphore); //释放
vTaskDelay(1000);
}
}