FreeRTOS——信号量知识点总结及二值信号量实战

发布时间:2024年01月03日

1信号量概念信号量

1)信号量的计数值都有限制:限定最大值。
如果最大值被限定为1,那么它就是二值信号量;
如果最大值不是1,它就是计数型信号量。
2)当计数值大于0,代表有信号量资源
当释放信号量,信号量计数值(资源数)加一
当获取信号量,信号量计数值(资源数)减一
3)信号量用于传递状态

2 队列与信号量对比

在这里插入图片描述

3 二值信号量概念

二值信号量的本质是一个队列长度为 1 的队列 ,该队列就只有空和满两种情况
合用于任务同步,即按序列访问。
在这里插入图片描述

4 二值信号量API函数

使用二值信号量的过程:创建二值信号量 ->释放二值信号量 -> 获取二值信号量
在这里插入图片描述
1)创建信号量
#define xSemaphoreCreateBinary( )
xQueueGenericCreate( 1 ,
semSEMAPHORE_QUEUE_ITEM_LENGTH ,
queueQUEUE_TYPE_BINARY_SEMAPHORE )
返回值 : NULL 创建失败
其他值 创建成功,返回二值信号量句柄
2)释放信号量
#define xSemaphoreGive ( xSemaphore )
xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ) ,
NULL ,
semGIVE_BLOCK_TIME ,
queueSEND_TO_BACK )

形参: xSemaphore 要释放信号量句柄
返回值:pdPASS 释放成功
errQUEUE_FULL 释放失败
3)获取信号量
BaseType_t xSemaphoreTake( xSemaphore, xBlockTime )
形参: xSemaphore 要获取信号量句柄
xBlockTime 阻塞时间
返回值:pdPASS 获取成功
errQUEUE_FULL 获取失败

5 二值信号量实战

在这里插入图片描述

5.1 freertos_demo.c

#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

//FreeRTOS配置
//1.任务配置
//1.1 START_TASK 任务 配置

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

//1.2 TASK1 任务 配置

#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

//1.2 TASK2 任务 配置

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

//1.3 二值信号量句柄定义
SemaphoreHandle_t        binarySemaphore;  

//2.在freertos_demo函数中创建start_task任务
void freertos_demo(void)
{

    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();
}

//3.在start_task函数中创建task1、task2任务
void start_task(void *pvParameters)
{
    
    //进入临界区
    taskENTER_CRITICAL();
    //创建二值信号量
     binarySemaphore = xSemaphoreCreateBinary(); 
    if(binarySemaphore != NULL)
    {
        printf("二值信号量创建成功!!!\r\n");
    }
    
    //创建任务1
      xTaskCreate((TaskFunction_t )task1,            /* 任务函数 */
                (const char*    )"task1",          /* 任务名称 */
                (uint16_t       )TASK1_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )TASK1_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&Task1Task_Handler);   /* 任务句柄 */
     //创建任务2          
     xTaskCreate((TaskFunction_t )task2,            /* 任务函数 */
                (const char*    )"task2",          /* 任务名称 */
                (uint16_t       )TASK2_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )TASK2_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&Task1Task_Handler);   /* 任务句柄*/
                
      //删除开始任务        
      vTaskDelete(StartTask_Handler);   
                
     //退出临界区
     taskEXIT_CRITICAL();
}


//4.在task1函数中释放二值信号量
void task1(void *pvParameters)
{
    uint8_t key = 0;
    BaseType_t err = 0;
    
    while (1)
    {
        //按键KEY0控制二值信号释放
        key = key_scan(0);
        switch (key)
        {
            case KEY0_PRES:
            {
                //如果二值信号量创建成功
                if(binarySemaphore != NULL)
                {
                     err = xSemaphoreGive(binarySemaphore);                //二值释放信号量
                    if(err == pdPASS)
                    {
                       printf("binarySemaphore释放成功\r\n");
                    }
                    else
                    {
                        printf("binarySemaphore释放失败\r\n");
                    }
               
                }
                 break;
               
            }
            default:
            {
                break;
            }
        }
        vTaskDelay(10);
    }
}

//5.在task2函数中获取二值信号量
void task2(void *pvParameters)
{
    BaseType_t err = 0;
    while(1)
    {
         err = xSemaphoreTake(binarySemaphore,portMAX_DELAY);
        if(err == pdPASS)
        {
            printf("binarySemaphore获取成功\r\n");
        }
        else printf("binarySemaphore获取失败\r\n");
    
    }
   
}


文章来源:https://blog.csdn.net/m0_73502349/article/details/135369671
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。