这一期我们先不讲队列,我们先讲一个简单的内容——二值信号量。但是其实二值信号量它本身也是一个特殊的队列,但是我们这一期不从队列的角度来认识它,而是从“变量”的角度来认识它。
信号量简介
有小伙伴会问,讲了这么久,究竟什么是信号量?按我的理解,信号量就是存储、传递相应信息的一个“匣子”,也可以理解为一个标志量。而且我们平时写代码的时候也经常会用到,比如:我们有时候会定义一个表量来存储0或1来表示相应的事件是否发生,再通过判断这个变量的值来执行相应的语句。这样一个变量其实就是二值信号量。所以我们完全可以从变量的角度了理解它。
二值信号量
刚刚也说了,二值信号量其实是特殊的队列,它是只有两种“满”和“空”状态的队列,我们可以把它看作成一个标志量。
下面是二值信号量的工作步骤:
现在二值信号量是“空”的状态,就是二值信号量刚创建或被获取之后的状态。创建二值信号量我们使用的是xSemaphoreCreateBinary()和xSemaphoreCreateBinaryStatic(),分别的动态创建和静态创建,我们常用的也是动态创建。xSemaphoreCreateBinary()具体创建过程如下:
//定义二值信号量句柄(全局定义)
SemaphoreHandle_t BinarySemaphore;
//创建二值信号量(在临界区创建)
BinarySemaphore=xSemaphoreCreateBinary();
创建完成二值信号量后,我们就可以在某个想要判断事件发生后发送二值信号量,让后面的在等待二值信号量的函数接收到。
释放二值信号量有两个函数,一个是xSemaphoreGive()是任务级信号量释放函数和xSemaphoreGiveFromISR()是中断级信号量释放函数,顾名思义就是一个是在任务函数里使用,一个在中断里使用。下面是这两个函数的定义:
BaseType_t xSemaphoreGive( xSemaphore )
参数:xSemaphore : 要释放的信号量句柄。返回值:pdPASS: 释放信号量成功。errQUEUE_FULL: 释放信号量失败。
BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore,
BaseType_t * pxHigherPriorityTaskWoken)
参数:xSemaphore : 要释放的信号量句柄。pxHigherPriorityTaskWoken :标记退出此函数以后是否进行任务切换,这个变量的值由这 三个函数来设置的,用户不用进行设置,用户只需要提供一 个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退 出中断服务函数之前一定要进行一次任务切换。返回值:pdPASS: 释放信号量成功。errQUEUE_FULL: 释放信号量失败。
发送了二值信号量后就可以获取二值信号量,然后就可以使相应的任务进入运行态执行相应的功能。
获取信号量也是有两个函数xSemaphoreTake()和xSemaphoreTakeFromISR(),同样也是分任务级和中断级。它们的定义如下:
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,
TickType_t xBlockTime)
参数:
xSemaphore:要获取的信号量句柄。
xBlockTime: 阻塞时间。(这里我们可以设置成portMAX_DELAY实现无限等待二值信号量,或者其他具体等待时间)
返回值:pdTRUE: 获取信号量成功。pdFALSE: 超时,获取信号量失败。
BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,
BaseType_t * pxHigherPriorityTaskWoken)
参数:xSemaphore : 要获取的信号量句柄。pxHigherPriorityTaskWoken :标记退出此函数以后是否进行任务切换,这个变量的值由这 三个函数来设置的,用户不用进行设置,用户只需要提供一 个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退 出中断服务函数之前一定要进行一次任务切换。返回值:pdPASS: 获取信号量成功。pdFALSE: 获取信号量失败。
今天的内容就到这里了,具体的实验设计后面会发上来,下去见!