【STM32】FreeRTOS消息队列和信号量学习

这篇具有很好参考价值的文章主要介绍了【STM32】FreeRTOS消息队列和信号量学习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、消息队列(queue)

队列是一种用于实现任务与任务之间,任务与中断之间消息交流的机制。

注意:1.数据的操作是FIFO模式。

2.队列需要明确数据的大小和队列的长度。

3.写和读都会出现堵塞。

实验:创建一个消息队列,两个发送任务,一个接收任务。

其中任务一任务三的等待时间为0,任务二的等待时间为portMAX_DELAY(死等)。

实现:在前一个项目的基础上进行更改【STM32】利用CubeMX对FreeRTOS用按键控制任务

【STM32】FreeRTOS消息队列和信号量学习,stm32,学习,嵌入式硬件

void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* Create the semaphores(s) */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the queue(s) */
  /* definition and creation of myQueue01 */
  osMessageQDef(myQueue01, 2, uint32_t);
  myQueue01Handle = osMessageCreate(osMessageQ(myQueue01), NULL);

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of Task1 */
  osThreadDef(Task1, StartDefaultTask, osPriorityNormal, 0, 128);
  Task1Handle = osThreadCreate(osThread(Task1), NULL);

  /* definition and creation of Task2 */
  osThreadDef(Task2, StartTask02, osPriorityIdle, 0, 128);
  Task2Handle = osThreadCreate(osThread(Task2), NULL);

  /* definition and creation of Task3 */
  osThreadDef(Task3, StartTask03, osPriorityIdle, 0, 128);
  Task3Handle = osThreadCreate(osThread(Task3), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the Task1 thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
	BaseType_t xStatus;
	uint32_t Buf=10086;
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)
			{
				xStatus=xQueueSendToBack(myQueue01Handle,&Buf,0);
				if(xStatus!=pdTRUE)
				{
					printf("NO1\r\n");osDelay(500);
				}
				else
				{
					printf("YES1%u\r\n",Buf);osDelay(500);
				}
			}
		}
    
  }
  /* USER CODE END StartDefaultTask */
}

/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
	BaseType_t xStatus;
	uint32_t Buf=66666;
  for(;;)
  {		
    if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)
			{
				xStatus=xQueueSendToBack(myQueue01Handle,&Buf,portMAX_DELAY);
				if(xStatus!=pdTRUE)
				{
					printf("NO2\r\n");osDelay(500);
				}
				else
				{
					printf("YES2%u\r\n",Buf);osDelay(500);
				}
			}
		}
  }
  /* USER CODE END StartTask02 */
}

/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the Task3 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */
	//BaseType_t xStatus;
	uint32_t Buf=0;
  for(;;)
  {
    if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0)
			{
				printf("当前%u\r\n",Buf);
				//xStatus=xQueueReceive(myQueue01Handle,&Buf,portMAX_DELAY);
				if(xQueueReceive(myQueue01Handle,&Buf,portMAX_DELAY)!=pdTRUE)
				{
					printf("NO3\r\n");
				}
				else
				{
					printf("YES3%u\r\n",Buf);
				}
			}
		}
  }
  /* USER CODE END StartTask03 */
}

现象:队列满了以后,任务一无法发送,任务二会死等,队列空闲以后完成发送。

二、信号量

消息队列用于传输多个数据,占用时间也相对较长,但有时只需要传输状态,因此引入信号量。信号量也是队列的一种。信号量有两种,如果它的量只有0(被拿走的状态)和1(被填入的状态)两种状态,就称为二进制的信号量;当量的状态大于两种,就称为计数型信号量。

1.二值信号量

实验:任务一:按键采集数据;任务二:拿走以后串口发送信息

实现:

【STM32】FreeRTOS消息队列和信号量学习,stm32,学习,嵌入式硬件

void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* Create the semaphores(s) */
  /* definition and creation of myBinarySem01 */
  osSemaphoreDef(myBinarySem01);
  myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the queue(s) */
  /* definition and creation of myQueue01 */
  osMessageQDef(myQueue01, 2, uint32_t);
  myQueue01Handle = osMessageCreate(osMessageQ(myQueue01), NULL);

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of Task1 */
  osThreadDef(Task1, StartDefaultTask, osPriorityNormal, 0, 128);
  Task1Handle = osThreadCreate(osThread(Task1), NULL);

  /* definition and creation of Task2 */
  osThreadDef(Task2, StartTask02, osPriorityNormal, 0, 128);
  Task2Handle = osThreadCreate(osThread(Task2), NULL);

  /* definition and creation of Task3 */
  osThreadDef(Task3, StartTask03, osPriorityNormal, 0, 128);
  Task3Handle = osThreadCreate(osThread(Task3), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the Task1 thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
	BaseType_t xStatus;
	uint32_t Buf=10086;
  for(;;)
	{
//  {
		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)
			{
//				xStatus=xQueueSendToBack(myQueue01Handle,&Buf,0);
				if(xSemaphoreGive(myBinarySem01Handle)==pdTRUE)
				{
					printf("NO1\r\n");
				}
				else
				{
					printf("YES1%u\r\n",Buf);
				}
			}
		}
    
  }
  /* USER CODE END StartDefaultTask */
}

/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the Task3 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */	
	uint32_t Buf=0;
  for(;;)
  {
    if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0)
			{				
				if(xSemaphoreTake(myBinarySem01Handle,0)==pdTRUE)
				{
					printf("YES3\r\n");
				}
				else
				{
					printf("NO3%u\r\n",Buf);
				}
			}
		}
  }
  /* USER CODE END StartTask03 */
}

 现象:当按键释放了信号量,串口才能成功发送信息。

2.记数型信号量

实验:任务一 :按键一记录人进来;按键二记录人出去;(最多有10个人)

任务二:串口每隔3S打印人数。

实现:

【STM32】FreeRTOS消息队列和信号量学习,stm32,学习,嵌入式硬件

【STM32】FreeRTOS消息队列和信号量学习,stm32,学习,嵌入式硬件

void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* Create the semaphores(s) */
  /* definition and creation of myBinarySem01 */
  osSemaphoreDef(myBinarySem01);
  myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);

  /* definition and creation of myCountingSem01 */
  osSemaphoreDef(myCountingSem01);
  myCountingSem01Handle = osSemaphoreCreate(osSemaphore(myCountingSem01), 10);

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the queue(s) */
  /* definition and creation of myQueue01 */
  osMessageQDef(myQueue01, 2, uint32_t);
  myQueue01Handle = osMessageCreate(osMessageQ(myQueue01), NULL);

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of Task1 */
  osThreadDef(Task1, StartDefaultTask, osPriorityNormal, 0, 128);
  Task1Handle = osThreadCreate(osThread(Task1), NULL);

  /* definition and creation of Task2 */
  osThreadDef(Task2, StartTask02, osPriorityNormal, 0, 128);
  Task2Handle = osThreadCreate(osThread(Task2), NULL);

  /* definition and creation of Task3 */
  osThreadDef(Task3, StartTask03, osPriorityNormal, 0, 128);
  Task3Handle = osThreadCreate(osThread(Task3), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the Task1 thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)
			{
				
				if(xSemaphoreGive(myCountingSem01Handle)!=pdTRUE)
				{
					printf("NO1\r\n");
				}
				else
				{
					printf("YES1\r\n");
				}
			}
			
		}
		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)
			{
				
				if(xSemaphoreTake(myCountingSem01Handle,0)!=pdTRUE)
				{
					printf("NO2\r\n");
				}
				else
				{
					printf("YES2\r\n");
				}
			}
			
		}
    
  }
  /* USER CODE END StartDefaultTask */
}

/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
	
  for(;;)
  {
    
  }
  /* USER CODE END StartTask02 */
}

/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the Task3 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */

  for(;;)
  {
		printf("possess %d people\r\n",(uint16_t)uxSemaphoreGetCount(myCountingSem01Handle));
		osDelay(3000);
  }
  /* USER CODE END StartTask03 */
}

 因为用了函数

myCountingSem01Handle = osSemaphoreCreate(osSemaphore(myCountingSem01), 10);

默认当前计数值为满值。如果设置为0,使用下面的函数:

myCountingSem01Handle=xSemaphoreCreateCounting(10,0);

现象:通过按键一和二实现记录人数,并串口打印了当前人数。文章来源地址https://www.toymoban.com/news/detail-644024.html

到了这里,关于【STM32】FreeRTOS消息队列和信号量学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【linux】进行间通信——共享内存+消息队列+信号量

    进程间通信方式目前我们已经学了匿名管道,命名管道。让两个独立的进程通信,前提是看到同一份资源。匿名管道适用于血缘关系的进程,一个打开写端一个打开读端实现的。命名管道适用于完全独立的进程,打开同一份文件实现的。 接下来我们看看剩下的实现进程间通信

    2024年02月05日
    浏览(36)
  • 【Linux】System V 共享内存、消息队列、信号量

    🍎 作者: 阿润菜菜 📖 专栏: Linux系统编程 System V 共享内存是一种进程间通信的机制,它允许多个进程 共享一块物理内存区域 (称为“段”)。System V 共享内存的优点是效率高,因为进程之间不需要复制数据;缺点是 需要进程之间进行同步,以避免数据的不一致性 。 共

    2024年02月04日
    浏览(40)
  • 【Linux】进程间通信之共享内存/消息队列/信号量

    共享内存是通过让不同的进程看到同一个内存块的方式。 我们知道,每一个进程都会有对应的PCB-task_struct ,独立的进程地址空间,然后通过页表将地址映射到物理内存中。此时我们就可以让OS在内存中申请一块空间,然后将创建好的内存空间映射到进程的地址空间中,两个需

    2024年02月05日
    浏览(40)
  • 【Linux】进程间通信 --- 管道 共享内存 消息队列 信号量

    等明年国庆去西藏洗涤灵魂,laozi不伺候这无聊的生活了 1. 通过之前的学习我们知道,每个进程都有自己独立的内核数据结构,例如PCB,页表,物理内存块,mm_struct,所以具有独立性的进程之间如果想要通信的话,成本一定是不低的。 2. a.数据传输:一个进程需要将它的数据

    2023年04月17日
    浏览(36)
  • 【Linux】进程间通信——system V共享内存 | 消息队列 | 信号量

    共享内存是一种在多个进程之间进行进程间通信的机制。它允许多个进程访问相同的物理内存区域,从而实现高效的数据交换和通信。 因为 进程具有独立性(隔离性) ,内核数据结构包括对应的代码、数据与页表都是独立的。OS系统为了让进程间进行通信,必须让不同的进

    2024年02月15日
    浏览(41)
  • Linux之进程间通信——system V(共享内存、消息队列、信号量等)

    本文介绍了另一种进程间通信——system V,主要介绍了共享内存,消息队列、信号量,当然消息队列了信号量并非重点,简单了解即可。 共享内存 :不同的进程为了进行通信看到的同一个内存块,该内存块被称为共享内存。 进程具有独立性,它的内核数据结构包括对应的代

    2024年02月08日
    浏览(47)
  • FreeRTOS教程5 信号量

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) Keil µVision5 IDE(MDK-Arm) 野火DAP仿真器 XCOM V2.6串口助手 一个滑动变阻器 本文主要学习 FreeRTOS 信号量的相关知识, 包括创建/删除信号量、释放信号量、获取信号量等知识 信号量是进程间用于通信的一种手段,其是

    2024年03月15日
    浏览(35)
  • FreeRTOS源码分析-10 互斥信号量

    目录   1 事件标志组概念及其应用 1.1 事件标志组定义 1.2 FreeRTOS事件标志组介绍 1.3 FreeRTOS事件标志组工作原理 2 事件标志组应用 2.1 功能需求 2.2 API  2.3 功能实现 3 事件标志组原理 3.1 事件标志组控制块 3.2 事件标志组获取标志位 3.3 等待事件标志触发 3.4 事件标志组设置标志

    2024年02月14日
    浏览(25)
  • FreeRTOS源码分析-9 互斥信号量

    目录 1 优先级翻转问题 2 互斥信号量概念及其应用 2.2FreeRTOS互斥信号量介绍 2.3FreeRTOS互斥信号量工作原理 3 互斥信号量函数应用 3.1功能分析 3.2API详解 3.3功能实现 4 递归互斥信号量函数应用 4.1死锁现象 ​编辑 4.2API详解 4.3解决死锁 5 互斥信号量实现原理 5.1互斥信号量创建

    2024年02月14日
    浏览(33)
  • 【Linux学习】多线程——信号量 | 基于环形队列的生产者消费者模型 | 自旋锁 | 读写锁

    🐱作者:一只大喵咪1201 🐱专栏:《Linux学习》 🔥格言: 你只管努力,剩下的交给时间! 之前在学习进程间通信的时候,本喵简单的介绍过一下信号量,今天在这里进行详细的介绍。 这是之前写的基于阻塞队列的生产者消费者模型中向阻塞队列中push任务的代码。 上面代码

    2024年02月07日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包