1.开发背景
FreeRTOS 基于上一篇了解了二值信号量后,如果需要设计需要累计信号量的次数就不行了,所以有了计数信号量,可以设置计数的最大值。同样,可以理解二值信号量是计数信号量的一种特例,即二值信号量是计数信号量最大计数为1时的特例。
2.开发需求
设计实验:
1)接收线程一直等待信号量唤醒;
2)发送线程发送多个信号量,信号量个数大于计数信号量的最大值;
3)按键中断发送信号量;
3.开发环境
window10 + MDK + STM32F429 + FreeRTOS10.3.1
4.实现步骤
4.1 实现编码
#include "appTest.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mspDwt.h"
#include "mspGpio.h"
#include "mspExti.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "appLog.h"
typedef struct
{
/* 信号量 */
SemaphoreHandle_t signal; // 队列句柄
/* 创建任务 */
TaskHandle_t taskRx; // 接收线程
TaskHandle_t taskTx; // 发送线程
}Ctrl_t;
/* 文件指针 */
static Ctrl_t s_ctrl = {0};
static Ctrl_t *p = &s_ctrl;
static void TaskRx(void *pvParameters);
static void TaskTx(void *pvParameters);
/* 接收线程 */
static void TaskRx(void *pvParameters)
{
vTaskDelay(1000);
unsigned int count = 0;
for ( ; ; )
{
xSemaphoreTake(p->signal, portMAX_DELAY);
Log_Debug("%s <== 线程接收信号量[%d]\r\n", __func__, count++);
}
}
/* 发送线程 */
static void TaskTx(void *pvParameters)
{
vTaskDelay(100);
for (int i = 0; i < 10; i++)
{
xSemaphoreGive(p->signal);
Log_Debug("%s ==> 线程发送信号量[%d]\r\n", __func__, i);
}
for ( ; ; )
{
vTaskDelay(1000);
}
}
/* 测试初始化 */
void aTest_Init(void)
{
/* 创建计数信号量 */
UBaseType_t uxMaxCount = 5; // 最大计数 5
UBaseType_t uxInitialCount = 0; // 初始值 0
p->signal = xSemaphoreCreateCounting(uxMaxCount, uxInitialCount);
/* 创建动态任务 */
xTaskCreate(TaskRx, "TaskRx", 500, NULL, 5, &p->taskRx);
xTaskCreate(TaskTx, "TaskTx", 500, NULL, 5, &p->taskTx);
}
/* Key2 PC13 Key0 PH3 Key1 PH2 */
void Exti13_TriggerInterrupt(void)
{
mspExti_Close(13);
if (mspGpio_GetInput("PC13") == 0)
{
/* 队列发送数据 */
BaseType_t xHigherPriorityTaskWoken;
xSemaphoreGiveFromISR(p->signal, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
Log_Debug("%s ==> 中断发送信号量\r\n", __func__);
}
}
4.2 结果显示
4.3 结果分析
由上图和代码可以分析,本实验设置最大信号量值为5,发送的信号量次数为10,实际上计数信号量累计到最大计数值就不会继续累计了。