• FreeRTOS 二值信号量 详解


    目录

    什么是信号量?

    什么是二值信号量?

    二值信号量相关 API 函数

    1. 创建二值信号量

    2. 释放二值信号量

    3. 获取二值信号量

    二值信号量实操


    什么是信号量?

    信号量(Semaphore),是在多任务环境下使用的一种机制,是可以用来保证两个或多个关键代 码段不被并发调用。

    信号量这个名字,我们可以把它拆分来看,信号可以起到通知信号的作用,然后我们的量还可以 用来表示资源的数量,当我们的量只有0和1的时候,它就可以被称作二值信号量,只有两个状 态,当我们的那个量没有限制的时候,它就可以被称作为计数型信号量。

    信号量也是队列的一种。

    什么是二值信号量?

    二值信号量其实就是一个长度为1,大小为零的队列,只有0和1两种状态,通常情况下,我们用 它来进行互斥访问或任务同步。

    互斥访问:比如门跟钥匙,只有获取到钥匙才可以开门

    任务同步:比如录完视频后才能看视频

    二值信号量相关 API 函数

                                          函数                                  描述
    xSemaphoreCreateBinary()使用动态方式创建二值信号量
    xSemaphoreCreateBinaryStatic()使用静态方式创建二值信号量
    xSemaphoreGive()释放信号量
    xSemaphoreGiveFromISR()在中断中释放信号量
    xSemaphoreTake()获取信号量
    xSemaphoreTakeFromISR()在中断中获取信号量

    1. 创建二值信号量

    1. SemaphoreHandle_t xSemaphoreCreateBinary( void )

    参数:

    返回值:

    • 成功,返回对应二值信号量的句柄;
    • 失败,返回 NULL 。

    2. 释放二值信号量

    1. BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore )

    参数:

    • xSemaphore:要释放的信号量句柄

    返回值:

    • 成功,返回 pdPASS ;
    • 失败,返回 errQUEUE_FULL 。

    3. 获取二值信号量

    1. BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore,
    2. TickType_t xTicksToWait );

    参数:

    • xSemaphore:要获取的信号量句柄
    • xTicksToWait:超时时间,0 表示不超时,portMAX_DELAY表示卡死等待;

    返回值:

    • 成功,返回 pdPASS ;
    • 失败,返回 errQUEUE_FULL 。

    二值信号量实操

    实验需求

    创建一个二值信号量,按下 KEY1 则释放信号量,按下 KEY2 获取信号量。

    1.打开CubeMX,将FreeRTOS移植到STM32F103C8T6,具体看我之前写过的文章

    将FreeRTOS移植到STM32F103C8T6

    2.然后创建两个任务用来放入和获取信号量

    3.创建一个二值信号量,然后导出代码

    4.进行代码编写:

    freertos.c

    1. void StartTaskGive(void const * argument)
    2. {
    3. for(;;)
    4. {
    5. if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
    6. {
    7. osDelay(20);
    8. if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
    9. {
    10. if(xSemaphoreGive(myBinarySem01Handle) == pdTRUE)
    11. printf("二值信号量放入成功\r\n");
    12. else
    13. printf("二值信号量放入失败\r\n");
    14. }
    15. while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET);
    16. }
    17. osDelay(10);
    18. }
    19. }
    20. void StartTaskTake(void const * argument)
    21. {
    22. for(;;)
    23. {
    24. if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET)
    25. {
    26. osDelay(20);
    27. if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET)
    28. {
    29. // 0 表示不超时,portMAX_DELAY表示卡死等待
    30. if(xSemaphoreTake(myBinarySem01Handle, portMAX_DELAY ) == pdTRUE)
    31. printf("二值信号量获取成功\r\n");
    32. else
    33. printf("二值信号量获取失败\r\n");
    34. }
    35. while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET);
    36. }
    37. osDelay(10);
    38. }
    39. }

    5.打开串口调试助手,用CubeMX初始化后二值信号量已经先放入成功,所以可以直接获得

  • 相关阅读:
    第二章:String类
    Java 设计模式实战系列—工厂模式
    HTML+CSS-项目:学成在线
    22 VueComponent 响应式处理
    加载SSL证书
    深入理解JavaScript:对象什么时候创建
    【动手学深度学习】RNN浅记
    Dubbo 原理和机制详解 (非常全面)
    RK3568技术笔记 Ubuntu 安装VMware Tools
    【每天一个cmake技巧】简单的cmake demo
  • 原文地址:https://blog.csdn.net/m0_74712453/article/details/133990138