stm32cubemx hal学习记录:FreeRTOS消息队列

一、基本介绍

1、消息队列就是一个像容器一样的东西,我们所有的任务都可以往内部写,然后队列会将我们的消息按顺序存下来,所有的任务也可以按顺序将其读出来。

2、队列需要明确数据的大小以及队列的长度,写队列和读队列都是采用赋值的方式将数据复制过去使用的。

3、数据的操作默认采用先进先出的方式,写数据时放到尾部,读数据时从头部读

二、基本配置

1、配置RCC、USART1、时钟84MHz

2、配置SYS,将Timebase Source修改为除滴答定时器外的其他定时器。

3、初始化LED的两个引脚、两个按键引脚

4、开启FreeRTOS,v1与v2版本不同,一般选用v1即可

5、创建消息队列

Queue Name: 队列名称
Queue Size: 队列能够存储的最大单元数目,即队列深度
Queue Size: 队列中数据单元的长度,以字节为单位
Allocation: 分配方式:Dynamic 动态内存创建
Buffer Name: 缓冲区名称
Buffer Size: 缓冲区大小
Conrol Block Name: 控制块名称

6、创建两个线程,一个接收,一个发送

 7、生成代码

三、API

1、队列ID:osMessageQId

osMessageQId TestQueueHandle;

2、使用动态内存的方式创建一个新的队列:osMessageCreate

  osMessageQDef(TestQueue, 16, uint16_t);
  TestQueueHandle = osMessageCreate(osMessageQ(TestQueue), NULL);

3、队列删除:osMessageDelete

osMessageDelete(TestQueueHandle);

4、向队列尾部发送一个队列消息:osMessagePut

消息以拷贝的形式入队,而不是以引用的形式,可用在中断服务程序中。

osMessagePut(TestQueueHandle,send_data1,0);
三个参数分别为:消息队列的句柄,发送的消息内容,等待时间
void Send_thread_entry(void const * argument)
{
  /* USER CODE BEGIN Send_thread_entry */
  /* Infinite loop */
  osEvent xReturn;
	uint32_t send_data1;
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8)==0)
		{
			printf("send_data1\n");
			xReturn.status=osMessagePut(TestQueueHandle,send_data1,0);
			
			if(osOK!=xReturn.status)
			{
				printf("send fail\n");
			}
		}
		osDelay(100);
  }
  /* USER CODE END Send_thread_entry */
}

5、从一个队列中接收消息并把消息从队列中删除:osMessageGet

接收的消息是以拷贝的形式进行的,所以我们必须提供一个足够大的空间的缓冲区,可以在中断服务中运行。

osMessageGet(TestQueueHandle,osWaitForever);
两个参数分别为:消息队列的句柄,等待时间(此时为一直等待)
void Receive_thread_entry(void const * argument)
{
  /* USER CODE BEGIN Receive_thread_entry */
  /* Infinite loop */
	osEvent event;
  for(;;)
  {
    event=osMessageGet(TestQueueHandle,osWaitForever);
		
		if(osEventMessage==event.status)
		{
			printf("receive data:%d\n",event.value.v);
		}
		else
		{
			printf("error:0x%d\n",event.status);
		}
  }
  /* USER CODE END Receive_thread_entry */
}

6、从队列中接收数据单元,但是并不删除接收到的单元:osMessagePeek

从队列中接收到数据后,不会修改队列中的数据,也不会改变数据在队列中的存储顺序

7、查询队列中当前有校的数据单元个数:osMessageWaiting

uint32_t a=osMessageWaiting(TestQueueHandle);

四、代码解释

这个功能相当于在两个任务之间传递数据,一个发送,一个接收。

1、传输数字

①发送

void Send_thread_entry(void const * argument)
{
  osEvent xReturn;
  uint32_t send_data1;

  for(;;)
  {

	printf("send_data1\n");
	xReturn.status=osMessagePut(TestQueueHandle,send_data1,0);
			
	if(osOK!=xReturn.status)
	{
		printf("send fail\n");
	}
		
	osDelay(100);
  }
}

②接收

void Receive_thread_entry(void const * argument)
{
  osEvent event;
  for(;;)
  {
    event=osMessageGet(TestQueueHandle,osWaitForever);
		
	if(osEventMessage==event.status)
	{
		printf("receive data:%d\n",event.value.v);
	}
	else
	{
		printf("error:0x%d\n",event.status);
	}
  }
}

2、传输字符串或者结构体

①发送

typedef struct
{
	uint8_t name;
	uint8_t id;
	uint8_t age;
}T_data;

void Send_thread_entry(void const * argument)
{

  for(;;)
  {
		T_data m_data;
		m_data.age=20;
		m_data.id=2;
		m_data.name=1;
		
		osMessagePut(TestQueueHandle,(uint32_t)&m_data,0);
		
		osDelay(100);
  }
}

②接收

void Receive_thread_entry(void const * argument)
{
  osEvent event;
  for(;;)
  {
    event=osMessageGet(TestQueueHandle,osWaitForever);
		
		if(event.status==osEventMessage)
		{
			T_data *pData=(T_data *)event.value.p;
			printf("data=%d\n",pData->age);
			printf("id=%d\n",pData->id);
			printf("name=%d\n",pData->name);
		}
  }
}

3、以邮箱的形式传输数据

邮箱不能使用cubemx自动生成,需要手动添加

osMailQId mailQ01Handle;

osMailQDef(mailQ01,15,T_data);
mailQ01Handle=osMailCreate(osMailQ(mailQ01),NULL);

①邮箱发送数据

T_data m_data;
m_data.age=20;
m_data.id=2;
m_data.name=1;		
		
osMailPut(mailQ01Handle,&m_data);

②邮箱接收数据

osEvent event=osMailGet(mailQ01Handle,osWaitForever);
if(event.status==osEventMail)
{
	T_data *m_Data=(T_data *)event.value.p;
	printf("data=%d\n",m_Data->age);
	printf("id=%d\n",m_Data->id);
	printf("name=%d\n",m_Data->name);			
}

五、代码总结

创建一个队列:

osMessageQId TestQueueHandle;

osMessageQDef(TestQueue, 16, uint16_t);
TestQueueHandle = osMessageCreate(osMessageQ(TestQueue), NULL);

删除队列:

osMessageDelete(TestQueueHandle);

发送一个数字:

uint32_t send_data=100;

osMessagePut(myQueue01Handle,send_data,0);

接收一个数字:

osMessageGet(myQueue01Handle,osWaitForever);

发送一个字符串或者结构体:

typedef struct
{
    uint8_t name;
    uint8_t age;
    uint8_t id;
}T_Data;

T_Data m_data;
m_data.age=18;
m_data.name=12;
m_data.id=123;
        
osMessagePut(myQueue01Handle,(uint32_t)&m_data,0);

  

接收一个字符或者结构体:

uint8_t name;
uint8_t id;
uint8_t age;

osEvent event=osMessageGet(myQueue01Handle,osWaitForever);
T_Data *p_data=(T_Data *)event.value.p;
name=p_data->name;
id=p_data->id;
age=p_data->age;

创建邮箱:

osMailQId mailQ01Handle;

 

收发的类型设置为结构体T_data

osMailQDef(mailQ01,15,T_data);
mailQ01Handle=osMailCreate(osMailQ(mailQ01),NULL);

邮箱发送数据:

T_Data m_data;
m_data.age=18;
m_data.name=12;
m_data.id=123;
osMailPut(mailQ01Handle,&m_data);

邮箱接收数据:

osEvent event=osMailGet(mailQ01Handle,osWaitForever);
T_Data *p_data=(T_Data *)event.value.p;
name=p_data->name;
id=p_data->id;
age=p_data->age;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值