CubeMXST32 FreeRTOS 信号量

一、CubeMX工程配置

CubeMXST32 FreeRTOS 信号量_第1张图片

时钟源配置

CubeMXST32 FreeRTOS 信号量_第2张图片

时钟树直接输入最大频率 

CubeMXST32 FreeRTOS 信号量_第3张图片

 LED配置

CubeMXST32 FreeRTOS 信号量_第4张图片

配置串口一

CubeMXST32 FreeRTOS 信号量_第5张图片

 freertos配置

CubeMXST32 FreeRTOS 信号量_第6张图片

 任务创建两个任务

CubeMXST32 FreeRTOS 信号量_第7张图片

生成工程

CubeMXST32 FreeRTOS 信号量_第8张图片 CubeMXST32 FreeRTOS 信号量_第9张图片

二、Keil代码

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

新添加一个任务

CubeMXST32 FreeRTOS 信号量_第10张图片

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每隔一秒闪烁,并且串口会发送接收成功

CubeMXST32 FreeRTOS 信号量_第11张图片

三、计数信号量

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

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

CubeMXST32 FreeRTOS 信号量_第12张图片

 freertos.c

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

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

添加串口重定向函数

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

 CubeMXST32 FreeRTOS 信号量_第13张图片

定义句柄

/* 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 */
}

运行效果 

CubeMXST32 FreeRTOS 信号量_第14张图片

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

你可能感兴趣的:(单片机,嵌入式硬件)