FreeRTOS信号量---二值信号量

信号量可以用来进行资源管理和任务同步,FreeRTOS中信号量又分为二值信号量、计算型信号量、互斥信号量和递归互斥信号量。

0x01 二值信号量

二值信号量其实就是一个只有一个队列项的队列,这个特殊的队列要么是满的,要么是空的,任务和中断不用在乎队列中存的是什么消息,只需要知道这个队列是满的还是空的,可以利用这个机制完成任务与中断之间的同步。

1. 创建二值信号量

在这里插入图片描述
vSemaphoreCreateBinary

vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
  • xSemaphore :保存创建成功的二值信号量
    此函数是老版本FreeRTOS创建二值信号量函数,新版本已经不再使用。

xSemaphoreCreateBinary:

SemaphoreHandle_t xSemaphoreCreateBinary( void )

此函数是新版本FreeRTOS中统一使用此函数来创建二值信号量,使用此函数创建二值信号量的话,信号量所需要的内存是有FreeRTOS的内存管理部分动态分配的,此函数创建好的二值信号量默认是空的,也就是说创建好的二值信号量使用函数xSemaphoreTask是获取不到的。

xSemaphoreCreateBinaryStatic

SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )
  • pxSemaphoreBuffer :保存信号量结构体
    此函数创建二值信号量所需要的内存需要由用户分配
2. 释放信号量

在这里插入图片描述

xSemaphoreGive

xSemaphoreGive( SemaphoreHandle_t xSemaphore )
  • xSemaphore:要释放的信号量句柄
    此函数用于释放二值信号量、计数型信号量或互斥信号量

xSemaphoreGiveFromISR

 xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken)
  • xSemaphore:要释放的信号量句柄
  • BaseType_t *pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换,此值为pdTRUE的时候在退出中断之前一定要进行一次任务切换

此函数只能用来释放二值信号量和计数型信号量

3. 获取信号量

在这里插入图片描述
xSemaphoreTake

xSemaphoreTake(*                   SemaphoreHandle_t xSemaphore,*                   TickType_t xBlockTime*               )
  • SemaphoreHandle_t xSemaphore:要获取信号量的句柄
  • TickType_t xBlockTime:阻塞时间
    此函数用于获取二值信号量、计数型信号量或互斥信号量

xSemaphoreTakeFromISR

 xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken)
  • SemaphoreHandle_t xSemaphore:要获取信号量的句柄
  • BaseType_t *pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换,等于pdTURE一定进行任务切换
4. 验证

设计一个通过串口发送指定的指令来控制开发版上的LED1和BEEP开关的实验。指令如下:
LED1ON:打开LED1
LED1OFF:关闭LED1
BEEFON:打开BEEF
BEEFOFF:关闭BEEF
设计三个任务,功能如下:
start_task:用来创建其他2个任务
task1_task:控制LED0闪烁,提示系统正在运行
DataProcess_task:指令处理任务,根据接收到的指令来控制不同的外设
实验中还创建一个二值信号量BinarySemaphore用于完成串口中断和任务DataProcess_task之间的同步。

DataProcess_task函数

void DataProcess_task(void *pvParameters)
{u8 len = 0;u8 CommandValue = COMMANDERR;BaseType_t err = pdFALSE;u8 *CommandStr;POINT_COLOR = BLUE;while(1){if(BinarySemaphore!=NULL){err=xSemaphoreTake(BinarySemaphore,portMAX_DELAY);	//获取信号量if(err==pdTRUE)										//获取信号量成功{len=USART_RX_STA&0x3fff;						//得到此次接收到的数据长度CommandStr=mymalloc(SRAMIN,len+1);				//申请内存sprintf((char*)CommandStr,"%s",USART_RX_BUF);CommandStr[len]='\0';							//加上字符串结尾符号LowerToCap(CommandStr,len);						//将字符串转换为大写		CommandValue=CommandProcess(CommandStr);		//命令解析if(CommandValue!=COMMANDERR){LCD_Fill(10,90,210,110,WHITE);				//清除显示区域LCD_ShowString(10,90,200,16,16,CommandStr);	//在LCD上显示命令printf("命令为:%s\r\n",CommandStr);switch(CommandValue)						//处理命令{case LED1ON: LED1=0;break;case LED1OFF:LED1=1;break;case BEEPON:BEEP=0;break;case BEEPOFF:BEEP=1;break;}}else{printf("无效的命令,请重新输入!!\r\n");}USART_RX_STA=0;memset(USART_RX_BUF,0,USART_REC_LEN);			//串口接收缓冲区清零myfree(SRAMIN,CommandStr);						//释放内存}}else if(err==pdFALSE){vTaskDelay(10);      //延时10ms,也就是10个时钟节拍	}}
}

DataProcess_task是用来申请获取信号量,如果申请到了,就往下执行,如果没事申请到,就会一直阻塞,申请到之后,对数据做处理,然后做出相应的回应。

串口1中断服务程序

//串口1中断服务程序
void USART1_IRQHandler(void)                	
{ u32 timeout=0;u32 maxDelay=0x1FFFF;BaseType_t xHigherPriorityTaskWoken;HAL_UART_IRQHandler(&UART1_Handler);	//调用HAL库中断处理公用函数timeout=0;while (HAL_UART_GetState(&UART1_Handler) != HAL_UART_STATE_READY)//等待就绪{timeout++;超时处理if(timeout>maxDelay) break;		}  timeout=0;while(HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1{timeout++; //超时处理if(timeout>maxDelay) break;	}//释放二值信号量if((USART_RX_STA&0x8000)&&(BinarySemaphore!=NULL))//接收到数据,并且二值信号量有效{xSemaphoreGiveFromISR(BinarySemaphore,&xHigherPriorityTaskWoken);	//释放二值信号量portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换}
} 

串口1中断服务程序是用来接收串口发送的数据,如果接收完毕,将会释放二值信号量,DataProcess_task才能往下执行,如果没有接收完数据或者没有接收到数据,DataProcess_task会一直阻塞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/379733.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FreeRTOS软件定时器

软件定时器允许设置一段时间,当设置的时间达到后就执行指定的功能函数,被软件定时器调用的功能函数叫做定时器的回调函数。软件定时器的回调函数是在定时器服务任务中执行的,所以一定不能在回调函数中调用任何阻塞任务的API函数,比…

WP7之Application Bar控件

Microsoft.Phone.Shell命名空间中定义了ApplicationBar及其相关类(ApplicationBarIconButton和ApplicationBarMenuItem),这些类派生自Object,并完全独立于常规Silverlight编程中的DependencyObject,UIElement和FrameworkElement类层次结构。A…

TomCat使用以及端口号被占用的处理方法

一.HTTP协议 什么是HTTP协议 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。 HTTP请求 HTTP响应 2.如何处理端口被占用 方法一&#xff…

FreeRTOS事件标志组

使用信号量来同步的话,任务只能与单个事务或任务进行同步,有时候某个任务可能会需要与多个事件或任务进行同步,此时信号量就无能为力了,FreeRTOS为此提供了一个可选的解决方法,那就是事件标志组。 0x01 事件标志组 事…

FusionCharts等产品简介

以前做柱状图、饼形图等图表都是根据数据绘制出来的静态图,偶然看到别人的一套系统,居然可以让柱状图的柱子动画般的逐个出现,效果还是很不错的。不要跟我抬杠说不就是展现数据嘛,静态图表有什么不好,要知道用户一般可…

Eclipse和Tomcat绑定并且将上传资源到Tomcat上

步骤如下: 创建一个Dynamic Web Project(图一) Target runtime 选择Apache Tomcat v7.0版本(图二) 切记要选择 v7.0 和2.5 (若没有图二选项见图三) 然后,点击window --> Prefer…

FreeRTOS任务通知

从v8.2.0版本开始,FreeRTOS新增了任务通知这个功能,可以使用任务通知来代替信号量、消息队列、事件标志组等这些东西,使用任务通知的话效率会更高。 任务通知在FreeRTOS是一个可选的选项,要使用任务通知的话就需要将宏configUSE_T…

kinect在openni下也能玩抠出人物换背景

之前想了个很拉风的名字《用kinect玩穿越》,但是现在功能还不是很完善,细节处理也不是很好,脸皮没有足够的厚,所以呢还是叫换背景吧。 这里面包含两个技术要点: 一、抠出活动人物 在微软的SDK里深度图像的前3位即0-2位…

Emit学习-基础篇-基本概念介绍

之前的Hello World例子应该已经让我们对Emit有了一个模糊的了解,那么Emit到底是什么样一个东西,他又能实现些什么功能呢?昨天查了点资料,大致总结了下,由于才开始学习肯定有不完善的地方,希望大家能够批评指…

The FreeRTOS Distribution(介绍、移植、类型定义)

1 Understand the FreeRTOS Distribution 1.1 Definition :FreeRTOS Port FreeRTOS目前可以在20种不同的编译器构建,并且可以在30多种不同的处理器架构上运行,每个受支持的编译器和处理器组合被认为是一个单独的FreeRTOS Port。 1.2 Build…

Eclipse项目左上角出现大红色感叹号怎么办?

出现大红色感叹号是因为环境不匹配 解决方法: 右击出现大红色感叹号的项目 点击 Libraries,将有叉号的给Remove掉 然后再点击 Add Library —> JRE System Library —> Next 勾选第二个即可 之后,就不会出现大红色感叹号了。

PCB---STM32最小系统制作过程

PCB 制作过程STM32核心模块连接外部电源晶振OSC_IN(8MHz)OSC32_IN(32.768MHz)复位下载口BOOT模式电源模块添加功能UARTWKUPSTM32核心模块 这里我们以STM32F103C8T6为列,先将芯片的原理图放到原理图中 对于STM32,有几个模块是核心&#xff0…

FreeRTOS---堆内存管理(一)

FreeRTOS的堆内存管理简介动态内存分配及其与 FreeRTOS 的相关性动态内存分配选项内存分配方案Heap_1heap_2Heap_3Heap_4设置heap_4的起始地址Heap_5vPortDefineHeapRegions()堆相关的函数xPortGetFreeHeapSizexPortGetMinimumEverFreeHeapSizeMalloc调用失败的Hook函数这篇文章…

FreeRTOS--堆内存管理(二)

堆内存管理代码具体实现heap_1内存申请函数内存释放函数heap_2内存块内存堆初始化函数内存块插入函数内存申请函数判断是不是第一次申请内存开始分配内存内存释放函数heap_3heap_4内存堆初始化函数内存块插入函数heap_5上一篇文章说了FreeRTOS实现堆内存的原理,这一…

css中的node.js_在Node App中使用基本HTML,CSS和JavaScript

css中的node.jsYou may think this is not important, but it is!. As a beginner in node.js, most coding exercises are always server sided. 您可能认为这并不重要,但确实如此! 作为node.js的初学者,大多数编码练习始终都是服务器端的。…

Binary String Matching(C++)

题目描述: Given two strings A and B, whose alphabet consist only ‘0’ and ‘1’. Your task is only to tell how many times does A appear as a substring of B? For example, the text string B is ‘1001110110’ while the pattern string A is ‘11’, you should…

VisualStudio2019配置OpenCV

VisualStudio2019配置OpenCV配置0x01 准备0x02 配置系统环境0x03 复制文件0x04 配置VisualStudio2019测试配置 0x01 准备 下载opencv,官网地址:https://opencv.org/releases/# 下载之后,自行安装 0x02 配置系统环境 找到高级系统设置 …

Visual Studio进行linux远程开发

目录准备工作创建一个项目配置远程项目准备工作 查看linux IP地址 安装了工具 sudo apt-get install openssh-server g gdb make ninja-build rsync zip开启ssh服务: sudo service ssh startVS2019按装了linux功能,如果没有,找到Visual S…

在给定总和K的二叉树中找到级别

Description: 描述: The article describes how to find the level in a binary tree with given sum K? This is an interview coding problem came in Samsung, Microsoft. 本文介绍了如何在给定总和K下在二叉树中找到级别 ? 这是一个面试编码问题&a…

++i与i++的根本性区别(两个代码对比搞定)

首先来看i 代码如下&#xff1a; #include <stdio.h> #include <stdlib.h> int main() {int i0;int ai;printf("%d\n",a);printf("%d\n\n\n",i);return 0; }输出结果如下&#xff1a; 解释&#xff1a;i其实是两行代码的简写形式&#xff0c…