CubeMXST32 FreeRTOS 信号量

简介: CubeMXST32 FreeRTOS 信号量

一、CubeMX工程配置



时钟源配置



时钟树直接输入最大频率



LED配置



配置串口一



freertos配置



任务创建两个任务



生成工程




二、Keil代码

       在嵌入式系统和实时系统中,信号量是一种常用的同步工具,用于协调多个任务之间的访问共享资源。二值信号量是信号量的一种特殊形式,其取值仅为0或1,常被用于二进制的互斥(Mutex)操作。


新添加一个任务



freertos.c

首先添加串口和信号量头文件


/* USER CODE BEGIN Includes */
#include "usart.h"
#include "semphr.h"
/* USER CODE END Includes */


 在 FreeRTOS 中,可以使用 xSemaphoreCreateBinary() 函数来创建一个二值信号量。

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
 
//创建句柄
SemaphoreHandle_t binarySemaphore;
 
/* USER CODE END FunctionPrototypes */


/* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  
   // 创建二值信号量
    binarySemaphore = xSemaphoreCreateBinary();
    if (binarySemaphore == NULL) {
        // 信号量创建失败,进行错误处理
      
        while (1);
    }
  
/* USER CODE END RTOS_SEMAPHORES */


xSemaphoreTake() 用于获取信号量,而 xSemaphoreGive() 用于释放信号量。在二值信号量中,获取操作通常是等待信号量变为可用,而释放操作通常是将信号量设置为可用。

void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  for(;;)
  {
    // 做一些工作
    HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
    osDelay(1000);
        // 发送信号量通知 Task2
        xSemaphoreGive(binarySemaphore);
        // 其他任务代码
 
  }
  /* USER CODE END StartDefaultTask */
}


/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
  for(;;)
  {
    // 等待二值信号量可用
        if (xSemaphoreTake(binarySemaphore, portMAX_DELAY)) {
            // 临界区代码
      HAL_UART_Transmit(&huart1,(uint8_t*)"receive ok",10,0xffff);
 
            // 释放二值信号量
            xSemaphoreGive(binarySemaphore);
      }
         osDelay(1000);
  }
  /* USER CODE END StartTask02 */
}

portMAX_DELAY 是 FreeRTOS 中的一个特殊常量,它用于表示一个无限等待的时间。在 FreeRTOS 中,等待时间通常以时钟节拍(tick)的形式表示,而 portMAX_DELAY 表示任务或线程在调用等待函数时会一直等待,直到事件发生而不超时。


具体来说,portMAX_DELAY 被定义为 0xffffffffUL,即32位无符号整数的最大值。当你将 portMAX_DELAY 作为等待时间传递给 FreeRTOS 的等待函数时,这意味着任务将一直等待,直到事件发生,而不会超时。


运行结果

LED每隔一秒闪烁,并且串口会发送接收成功




三、计数信号量


 计数信号量和二值信号量区别,计数信号量类似于二进制信号量,但是随信号量释放的次数改变而改变。计数信号量是一种在多任务环境中用于同步和资源共享的机制。在 FreeRTOS 中,可以使用计数信号量(Counting Semaphore)来实现任务之间的同步和资源计数。


首先在freertos中选择V2版本,CubeMX V1版本的没有计数信号量



freertos.c

首先添加串口和信号量头文件


/* USER CODE BEGIN Includes */
#include "usart.h"
#include "semphr.h"
/* USER CODE END Includes */

添加串口重定向函数


/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#include <stdio.h>
int fputc(int ch,FILE *f)
{
    HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,0xFFFF);
    return ch;
}
/* USER CODE END PTD */



定义句柄


/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
//计数信号量句柄
SemaphoreHandle_t countingSemaphore;
 
/* USER CODE END FunctionPrototypes */


创建计数信号量


  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  
  // 创建计数信号量,最大计数值为5,初始值为0
    countingSemaphore = xSemaphoreCreateCounting(5, 0);
 
    if (countingSemaphore == NULL) {
        // 信号量创建失败,进行错误处理
        while (1);
    }
  
  /* USER CODE END RTOS_SEMAPHORES */


xSemaphoreGive() 用于增加计数信号量的值,xSemaphoreTake() 用于减小计数信号量的值。计数信号量允许你控制可用资源的数量。


/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  for(;;)
  {
    //获取计数信号量的当前计数值
    uint32_t countValue = uxSemaphoreGetCount(countingSemaphore);
    if(countValue == 0){
      if(osThreadSuspend(myTask02Handle)==osOK){//挂起任务2       
        printf("task2 suspend ok\r\n");
        xSemaphoreGive(countingSemaphore);    // 计数信号量增量
      }
    }
    else if(countValue ==1){    xSemaphoreGive(countingSemaphore);  printf("Task1:%d\r\n",countValue);} // 计数信号量增量
    else if(countValue ==2){    xSemaphoreGive(countingSemaphore);  printf("Task1:%d\r\n",countValue);} // 计数信号量增量
    else if(countValue ==3){    xSemaphoreGive(countingSemaphore);  printf("Task1:%d\r\n",countValue);} // 计数信号量增量 
    else if(countValue ==4){    xSemaphoreGive(countingSemaphore);  printf("Task1:%d\r\n",countValue);} // 计数信号量增量 
    else if(countValue ==5){
      osThreadResume(myTask02Handle);
    }
    
    // 任务1正常工作led
    HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
    osDelay(2000);
  }
  /* USER CODE END StartDefaultTask */
}


/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
  for(;;)
  {
    // 获取计数信号量的当前计数值
    uint32_t countValue = uxSemaphoreGetCount(countingSemaphore);
    osDelay(500);
    if(countValue == 5){
      if(osThreadSuspend(defaultTaskHandle)==osOK){//挂起任务1
        printf("task1 suspend ok\r\n");
        xSemaphoreTake(countingSemaphore, portMAX_DELAY);
        printf("Task2:%d\r\n",countValue);
      }
    }
    else if(countValue ==4){    xSemaphoreTake(countingSemaphore, portMAX_DELAY);   printf("Task2:%d\r\n",countValue);}//计数信号量减量释放
    else if(countValue ==3){    xSemaphoreTake(countingSemaphore, portMAX_DELAY);   printf("Task2:%d\r\n",countValue);}
    else if(countValue ==2){    xSemaphoreTake(countingSemaphore, portMAX_DELAY);   printf("Task2:%d\r\n",countValue);}
    else if(countValue ==1){    xSemaphoreTake(countingSemaphore, portMAX_DELAY);   printf("Task2:%d\r\n",countValue);}
    else if(countValue ==0){
        osThreadResume(defaultTaskHandle);
      }
    osDelay(2000);
  }
  /* USER CODE END StartTask02 */
}

运行效果



链接: https://pan.baidu.com/s/1T-_kplH0PwDPpj3v1AAK5Q?pwd=8dfe 提取码: 8dfe

目录
相关文章
|
3月前
|
API 调度
【FreeRTOS】互斥锁的使用
【FreeRTOS】互斥锁的使用
|
9月前
|
安全
理解信号量
理解信号量
|
3月前
|
API 调度
【FreeRTOS】信号量的使用
【FreeRTOS】信号量的使用
|
3月前
FreeRTOS入门教程(信号量的具体使用)
FreeRTOS入门教程(信号量的具体使用)
89 0
|
9月前
|
算法
信号量(上)
信号量(上)
29 0
|
9月前
|
存储
信号量(下)
信号量(下)
30 0
|
机器学习/深度学习 C语言
信号量
信号量
68 0
|
存储 网络协议 API
4-FreeRTOS队列、互斥、信号量
4-FreeRTOS队列、互斥、信号量