当前位置: 首页 > news >正文

14_FreeRTOS二值信号量

目录

信号量的简介

队列与信号量的对比

二值信号量

二值信号量相关API函数

实验源码


信号量的简介

信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问

假设有一个人需要在停车场停车

1.首先判断停车场是否还有空车位(判断信号量是否有资源)

2.停车场正好有空车位(信号量有资源),那么就可以直接将车开入空车位进行停车(获取信号量成功) ;

3.停车场已经没有空车位了(信号量没有资源) ,那么这个人可以选择不停车(获取信号量失败) ;也可以选择等待(任务阻塞)其他人将车开出停车场(释放信号量资源),然后再将车停入空车位。

空车位:可以理解为信号量资源数(计数值)

让出占用车位:释放信号量(计数值++)

占用车位:获取信号量(计数值--)

当计数值大于0,代表有信号量资源

当释放信号量,信号量计数值(资源数)加一

当获取信号量,信号量计数值(资源数)减一

信号量:用于传递状态

信号量的计数值都有限制:限定最大值。

如果最大值被限定为1,那么它就是二值信号量;

如果最大值不是1,它就是计数型信号量。

队列与信号量的对比

 

 

二值信号量

二值信号量的本质是一个队列长度为1的队列,该队列就只有空和满两种情况,这就是二值。

二值信号量通常用于互斥访问或任务同步,与互斥信号量比较类似,但是二值信号量有可能会导致优先级翻转的问题,所以二值信号量更适合用于同步!

二值信号量相关API函数

使用二值信号量的过程:创建二值信号量→释放二值信号量→获取二值信号量

 

创建二值信号量函数: SemaphoreHandle_t  xSemaphoreCreateBinary(void)
#define xSemaphoreCreateBinary()xQueueGenericCreate(1,semSEMAPHORE_QUEUE_ITEM_LENGTH,queueQUEUE_TYPE_BINARY_SEMAPHORE) #define semSEMAPHORE_QUEUE_ITEM_LENGTH ((uint8_t) 0U)#define queueQUEUE_TYPE_BASE  		((uint8_t) 0U)		 /*队列*/
#define queueQUEUE_TYPE_SET		((uint8_t) 0U)		 /*队列集*/
#define queueQUEUE_TYPE_MUTEX		((uint8_t) 1U)		/*互斥信号量*/
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE 	 ((uint8_t) 2U)	 /*计数型信号量*/
#define queueQUEUE_TYPE_BINARY_SEMAPHORE 	 ((uint8_t) 3U) /*二值信号量*/
#define queueQUEUE_TYPE_RECURSIVE_MUTEX		((uint8_t) 4U) 	/*递归互斥信号量*/

 

释放二值信号量函数:BaseType_t xSemaphoreGive(xSemaphore)#define xSemaphoreGive ( xSemaphore )xQueueGenericSend( (QueueHandle_t) (xSemaphore), NULL , 
semGIVE_BLOCK_TIME , queueSEND_TO_BACK)#define semGIVE_BLOCK_TIME((TickType_t) 0U)

 

 

获取二值信号量函数: BaseType_t xSemaphoreTake(xSemaphore, xBlockTime)

 

 

实验源码

将设计三个任务:start_task、task1、task2

start_task:用来创建task1和task2任务

Task1:用于按键扫描,当检测到按键KEY0被按下时,释放二值信号量

task2:获取二值信号量,当成功获取后打印提示信息

/********************************************************************************* @file           : user_mian.h* @brief          : V1.00******************************************************************************* @attention********************************************************************************//* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdbool.h>
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "user_key.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/*二值信号量句柄*/
QueueHandle_t semphore_handle;
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*///任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define TASK1_PRIO			2
//任务堆栈大小	
#define TASK1_STK_SIZE 		100  
//任务句柄
TaskHandle_t Task1_Handler;
//任务函数
void task1(void *pvParameters);//任务优先级
#define TASK2_PRIO			3
//任务堆栈大小	
#define TASK2_STK_SIZE 		100  
//任务句柄
TaskHandle_t Task2_Handler;
//任务函数
void task2(void *pvParameters);int main(void){	/*配置系统中断分组为4位抢占*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/*延时函数初始化*/delay_init();/*RCC配置*/Rcc_config();/*GPIO初始化*/ Gpio_Init();/*USART1初始化*/Uart1_Init(9600);/*创建二值信号量*/semphore_handle = xSemaphoreCreateBinary(); if(semphore_handle == NULL){printf("二值信号量创建不成功\r\n\r\n");}else{printf("二值信号量创建成功\r\n\r\n");}/*创建开始任务*/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();          //开启任务调度}/*!\brief		开始任务函数\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建任务1xTaskCreate((TaskFunction_t )task1,     	(const char*    )"task1",   	(uint16_t       )TASK1_STK_SIZE, (void*          )NULL,				(UBaseType_t    )TASK1_PRIO,	(TaskHandle_t*  )&Task1_Handler);   //创建任务2xTaskCreate((TaskFunction_t )task2,     (const char*    )"task2",   (uint16_t       )TASK2_STK_SIZE, (void*          )NULL,(UBaseType_t    )TASK2_PRIO,(TaskHandle_t*  )&Task2_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}/*!\brief		task1释放二值信号量\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void task1(void *pvParameters)
{uint8_t key = 0;BaseType_t err;while(1){	/*获取按键值*/key = Key_Scan(0);if(key == KEY0_PRES){if(semphore_handle != NULL){	err = xSemaphoreGive(semphore_handle);if(err == pdPASS){printf("信号量释放成功\r\n\r\n");}else{printf("信号量释放失败\r\n\r\n");}}		}vTaskDelay(100);}
} /*!\brief		task2获取二值信号量\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void task2(void *pvParameters)
{while(1){/*获取信号量死等,进入阻塞态*/xSemaphoreTake(semphore_handle,portMAX_DELAY);printf("获取信号量成功!!!\r\n\r\n");}
}/************************************************************** END OF FILE ****/

 

http://www.lryc.cn/news/9389.html

相关文章:

  • JavaScript随手笔记---轮播图(点击切换)
  • 机器人学 markdown数学公式常用语法
  • 如何使用 Python 语言来编码和解码 JSON 对象
  • 【蓝桥云课】求正整数的约数个数
  • 刷题记录: wannafly25 E 牛客NC19469 01串 [线段树维护动态dp]
  • 懂九转大肠的微软New Bing 内测申请教程
  • WRAN翻译
  • ROS学习笔记——第二章 ROS通信机制
  • MacOS Pytorch 机器学习环境搭建
  • 项目——博客系统
  • PHP(14)会话技术
  • 对JAVA 中“指针“理解
  • 功率放大器在MEMS微结构模态测试研究中的应用
  • 【算法基础】字典树(Trie树)
  • MyBatis 插件 + 注解轻松实现数据脱敏
  • MySQL优化篇-MySQL压力测试
  • CF43A Football 题解
  • Nginx常用命令及具体应用(Linux系统)
  • 从零实现Web服务器(三):日志优化,压力测试,实战接收HTTP请求,实战响应HTTP请求
  • MFC入门
  • 1、H5+CSS面试题
  • 亚马逊云科技重磅发布《亚马逊云科技汽车行业解决方案》
  • Springboot扩展点之FactoryBean
  • 新库上线 | CnOpenDataA股上市公司交易所监管措施数据
  • 同步辐射XAFS表征方法的应用场景分析
  • 06 antdesign react Anchor 不同页面之间实现锚点
  • mysql调优-内存缓冲池
  • 【LeetCode】每日一题(5)
  • 输入任意多个整数, 把这些数据保存到文件data.txt中.(按ctrl + z)
  • Mysql数据库的时间(3)一如何用函数插入时间