FreeRTOS之二值信号量与计数信号量

FreeRTOS之二值信号量与计数信号量

声明:本人按照正点原子的FreeRTOS例程进行学习的,欢迎各位大佬指责和批评,谢谢!

  1. 二值信号量
#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 "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "malloc.h"
#include "semphr.h"


#define START_TASK_PRIO				1			//任务优先级
#define START_STK_SIZE 				256  		//任务堆栈大小
TaskHandle_t StartTask_Handler;					//任务句柄
void start_task(void *pvParameters);		    //任务函数

#define LED_TASK_PRIO     		2			    //任务优先级
#define LED_STK_SIZE 	        128  		    //任务堆栈大小
TaskHandle_t LedTask_Handler;			        //任务句柄
void led_task(void *pvParameters);		        //任务函数

#define TASK1_TASK_PRIO				3			//任务优先级
#define TASK1_STK_SIZE 				256  		//任务堆栈大小
TaskHandle_t Task1Task_Handler;					//任务句柄
void task1_task(void *pvParameters);			//任务函数

#define TASK2_TASK_PRIO				4			//任务优先级
#define TASK2_STK_SIZE 				128  		//任务堆栈大小
TaskHandle_t Task2Task_Handler;					//任务句柄
void task2_task(void *pvParameters);			//任务函数

SemaphoreHandle_t BinarySemaphore = NULL;	//二值信号量句柄
/**
*二值信号量:其实更偏向应用于同步功能,发送信号量与接收信号量之间进行同步,传递的量值不是1就是0.
             当信号量的共享区域满了就是1,不满就是0,可以是这么理解。
             此实验,实现的是:
                                任务1中,当按键按下,发送信号量
                                任务2中,获取信号量,串口调试助手显示结果。
*/
//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 STM32F407");	
	LCD_ShowString(30,30,200,16,16,"FreeRTOS 测试");
	LCD_ShowString(30,50,200,16,16,"任务状态查询");
	
	//创建开始任务
    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();           //进入临界区

    //创建二值信号量
	BinarySemaphore = xSemaphoreCreateBinary();
    if(BinarySemaphore != NULL)
        printf("创建二值信号量成功\r\n");
    //创建LED任务
    xTaskCreate((TaskFunction_t )led_task,             
                (const char*    )"led_task",           
                (uint16_t       )LED_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )LED_TASK_PRIO,        
                (TaskHandle_t*  )&LedTask_Handler);   
    //创建TASK1任务
    xTaskCreate((TaskFunction_t )task1_task,     
                (const char*    )"task1_task",   
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_TASK_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler); 
    //创建TASK2任务
    xTaskCreate((TaskFunction_t )task2_task,     
                (const char*    )"task2_task",   
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_TASK_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler); 
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//led0任务函数
void led_task(void *pvParameters)
{	
    while(1)
    {
        LED0=!LED0;
        vTaskDelay(500);             	//延时500ms,也就是500个时钟节拍	
    }									
}
//task1任务函数
void task1_task(void *pvParameters)
{   
    BaseType_t xreturn = pdPASS;
    while(1)
    {
        if(KEY_Scan(1) == KEY1_PRES)
        {/*KEY1按下*/
            xreturn = xSemaphoreGive(BinarySemaphore);
            if(xreturn == pdTRUE)
            {
                printf("发送信号量成功\r\n");
            }
        }
    }
}
//task2任务函数
void task2_task(void *pvParameters)
{
    BaseType_t err=pdTRUE;
    while(1)
    {
        err = xSemaphoreTake(BinarySemaphore,portMAX_DELAY);//BinarySemaphore:传入的信号量 portMAX_DELAY :最大阻塞的时间,一直阻塞
        if(err == pdTRUE)
        {
            printf("获取信号量成功\r\n");
        }    
        else
        {
            printf("获取信号量失败\r\n");
            vTaskDelay(10);
        }
            
    }
}
  1. 计数信号量
#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 "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "malloc.h"
#include "semphr.h"


#define START_TASK_PRIO				1			//任务优先级
#define START_STK_SIZE 				256  		//任务堆栈大小
TaskHandle_t StartTask_Handler;					//任务句柄
void start_task(void *pvParameters);		    //任务函数

#define LED_TASK_PRIO     		2			    //任务优先级
#define LED_STK_SIZE 	        128  		    //任务堆栈大小
TaskHandle_t LedTask_Handler;			        //任务句柄
void led_task(void *pvParameters);		        //任务函数

#define TASK1_TASK_PRIO				3			//任务优先级
#define TASK1_STK_SIZE 				256  		//任务堆栈大小
TaskHandle_t Task1Task_Handler;					//任务句柄
void task1_task(void *pvParameters);			//任务函数

#define TASK2_TASK_PRIO				4			//任务优先级
#define TASK2_STK_SIZE 				128  		//任务堆栈大小
TaskHandle_t Task2Task_Handler;					//任务句柄
void task2_task(void *pvParameters);			//任务函数

SemaphoreHandle_t CountSemaphore = NULL;	//计数信号量句柄
/**
*计数信号量

*/
//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 STM32F407");	
	LCD_ShowString(30,30,200,16,16,"FreeRTOS 测试");
	LCD_ShowString(30,50,200,16,16,"任务状态查询");
	
	//创建开始任务
    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();           //进入临界区

    //创建二值信号量
	CountSemaphore = xSemaphoreCreateCounting(5,5); //
    if(CountSemaphore != NULL)
        printf("创建计数信号量成功\r\n");
    //创建LED任务
    xTaskCreate((TaskFunction_t )led_task,             
                (const char*    )"led_task",           
                (uint16_t       )LED_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )LED_TASK_PRIO,        
                (TaskHandle_t*  )&LedTask_Handler);   
    //创建TASK1任务
    xTaskCreate((TaskFunction_t )task1_task,     
                (const char*    )"task1_task",   
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_TASK_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler); 
    //创建TASK2任务
    xTaskCreate((TaskFunction_t )task2_task,     
                (const char*    )"task2_task",   
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_TASK_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler); 
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//led0任务函数
void led_task(void *pvParameters)
{	
    while(1)
    {
        LED0=!LED0;
        vTaskDelay(500);             	//延时500ms,也就是500个时钟节拍	
    }									
}
//task1任务函数
void task1_task(void *pvParameters)
{   /*按键,KEY0按下就获取,KEY1按下就释放*/
    
    BaseType_t xreturn = pdPASS;
    while(1)
    {
        if(KEY_Scan(1) == KEY0_PRES)
        {/*KEY0按下*/
            xreturn = xSemaphoreTake(CountSemaphore,0);//获取
            if(xreturn == pdTRUE)
                printf("按键0被按下,获取到一个停车位\r\n");
            else
                printf("按键0被按下,不好意思,停车位已满\r\n");
        }
        vTaskDelay(20);
    }
}
//task2任务函数
void task2_task(void *pvParameters)
{
    /*按键,KEY0按下就获取,KEY1按下就释放*/
    
    BaseType_t xreturn = pdPASS;
    while(1)
    {
        if(KEY_Scan(1) == KEY1_PRES)
        {/*KEY1按下*/
            xreturn = xSemaphoreGive(CountSemaphore);//释放
            if(xreturn == pdTRUE)
                printf("KEY1按下,释放一个停车位\r\n");
            else
                printf("KEY1按下,但已无车位可以释放\r\n");
        }
        
        vTaskDelay(20);
    }
}

下面在串口调试助手查看打印的结果:
在这里插入图片描述

结束

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值