STM32CubMx+FreeRTOS消息队列(三)

FreeRTOS系统操作

一.简介

我们可以把消息队列比作是一个存放消息的容器,当我们需要使用消息的时候可以取出消息供自己使用。消息队列是分布式系统中重要的组件,使用消息队列主要是为了通过异步处理提高系统性能和削峰、降低系统耦合性。目前使用较多的消息队列有ActiveMQ,RabbitMQ,Kafka,RocketMQ,我们后面会一一对比这些消息队列。

另外,我们知道队列 Queue 是一种先进先出的数据结构,所以消费消息时也是按照顺序来消费的。比如生产者发送消息1,2,3…对于消费者就会按照1,2,3…的顺序来消费。但是偶尔也会出现消息被消费的顺序不对的情况,比如某个消息消费失败又或者一个 queue 多个consumer 也会导致消息被消费的顺序不对,我们一定要保证消息被消费的顺序正确。

除了上面说的消息消费顺序的问题,使用消息队列,我们还要考虑如何保证消息不被重复消费?如何保证消息的可靠性传输(如何处理消息丢失的问题)?…等等问题。所以说使用消息队列也不是十全十美的,使用它也会让系统可用性降低、复杂度提高,另外需要我们保障一致性等问题。

二.测试准备

我们需要一个按键任务,和两个普通的任务,按键操作发出一个消息,来观察其他两个普通任务收到消息的情况,来很好的理解消息队列
在这里插入图片描述

三.代码部分

1.按键KEY

void StartDefaultTask_KEY(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask_KEY */
  /* Infinite loop */
	uint16_t ProducerValue = 0;
	for(;;)
  	{
		if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == 1)
		{
			osDelay(10);
			if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == 1)
			{
				//生产者 按键按下后发送消息 
				if(osMessagePut(myQueue01Handle,ProducerValue,0) != osOK)
				{
					osThreadSuspendAll();  
					printf("发送失败\n");
					osThreadResumeAll();
				}
				else
				{
					++ProducerValue;
					
					osThreadSuspendAll();  
					printf("发送成功\n");
					osThreadResumeAll();
				}
		
				while(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == 1)
				{
					osDelay(10);
				}
			}
		}
    osDelay(1);
  }
  /* USER CODE END StartDefaultTask_KEY */
}

注意

uint16_t ProducerValue = 0;

添加消息的时候 写的是 uint16_t ,所有这里也要定义
默认的数据类型是 uint32_t 没有这句代码 可以到软件修改
在这里插入图片描述
产生消息

osMessagePut(myQueue01Handle,ProducerValue,0)

这个参数 myQueue01Handle 是 操作消息队列的句柄
在这里插入图片描述

2.任务1

void StartTask01(void const * argument)
{
  /* USER CODE BEGIN StartTask01 */
  /* Infinite loop */
	osEvent event;
  for(;;)
  {
		event = osMessageGet(myQueue01Handle,osWaitForever);
		
		if(event.status == osEventMessage)
		{
			
			printf("任务一接收的数据:%d",event.value.v);
			
		}
		
    osDelay(1);
  }
  /* USER CODE END StartTask01 */
}

3.任务2

void StartTask02(void const * argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
  osEvent event;
  for(;;)
  {
		
		event = osMessageGet(myQueue01Handle,osWaitForever); 
		
		if(event.status == osEventMessage)
		{
			
			printf("任务二接收的数据:%d",event.value.v);
			
		}
		
    osDelay(1);
  }
  /* USER CODE END StartTask02 */
}

四.测试结果

这里我添加的两个任务的优先级都是一样的,所以一会是任务一得到消息,一会又是任务二
在这里插入图片描述

如果将任务一的优先级调到,比任务二的优先级高,则只能是任务一收的消息,因为任务一收到消息之后就将消息删除了,所以任务二是永远收不到消息的

如果将 osMessageGet()函数得到数据后删除消息 改为osMessagePeek()函数 得到后不删除消,则会显示任务一和任务二都能得到消息

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值