|
对于一个数据采集线程,和一个数据接收线程而言。消息队列相较于邮箱能够传输不定长字节的数据。
但是,对于数据采集线程,有时需要持续性采集多次的数据,每次都放进数组中,然后将他们一次性全部发送出去,这个时候就是需要注意
区分,我们到底是每次采完直接发送,,达到指定数据后才提醒接收线程接收。
还是将数据放在数组中,将数组一次性发出。
举个简单的例子,比如,线程1需要采集50个数据为1组发送给线程2
此时,线程1每接收一个发送一个,然后线程2统一接收。
#include <rtthread.h>
#define ARRAY_SIZE 50
static rt_mq_t mq;
static rt_sem_t sem;
static float data[ARRAY_SIZE];
static void producer_thread_entry(void *parameter)
{
float temp_data;
for (int i = 0; i < 50; i++)
{
// 采集数据
temp_data = ...; // 采集数据的逻辑
// 发送数据到消息队列
rt_mq_send(mq, &temp_data, sizeof(float));
// 判断是否采集了50次数据
if (i == 49)
{
// 发送信号量给消费者线程
rt_sem_release(sem);
}
rt_thread_mdelay(1000); // 延时 1 秒
}
}
static void consumer_thread_entry(void *parameter)
{
float received_data[ARRAY_SIZE];
while (1)
{
// 等待信号量
rt_sem_take(sem, RT_WAITING_FOREVER);
// 接收数据从消息队列
for (int i = 0; i < ARRAY_SIZE; i++)
{
rt_mq_recv(mq, &received_data, sizeof(float), RT_WAITING_FOREVER);
}
// 处理接收到的数据
for (int i = 0; i < ARRAY_SIZE; i++)
{
// 处理 received_data
}
}
}
int main(void)
{
mq = rt_mq_create("mq", sizeof(float), 50, RT_IPC_FLAG_FIFO);
if (mq == RT_NULL)
{
rt_kprintf("Failed to create message queue\n");
return -1;
}
sem = rt_sem_create("sem", 0, RT_IPC_FLAG_FIFO);
if (sem == RT_NULL)
{
rt_kprintf("Failed to create semaphore\n");
return -1;
}
rt_thread_t tid1 = rt_thread_create("producer", producer_thread_entry, RT_NULL, 1024, 10, 10);
if (tid1 != RT_NULL)
{
rt_thread_startup(tid1);
}
rt_thread_t tid2 = rt_thread_create("consumer", consumer_thread_entry, RT_NULL, 1024, 20, 10);
if (tid2 != RT_NULL)
{
rt_thread_startup(tid2);
}
while (1)
{
rt_thread_mdelay(1000);
}
}
这个时候,创建消息队列的时候,就是
mq = rt_mq_create("mq", sizeof(float),//每个消息的最大字节数
, 50 //消息队列中最多有多少消息
,RT_IPC_FLAG_FIFO);
当我们将50个数据封装程一个数组,然后将数组一次性通过消息队列发送给线程2的时候
例如 定义数组 float value_data[50]; 存放数据
这个时候,创建的消息队列应该是
mq = rt_mq_create("mq", sizeof(float)*50,//每个消息(这里的每个消息就是指的这个数组是一个消息)的最大字节数
, 3 //消息队列中最多有多少消息,(随便设定,实测,不易过大)
,RT_IPC_FLAG_FIFO);
这个特别注意,在创建消息队列,传输数组的时候,数组作为消息发送的时候,单个消息的大小=sizeof(数组的存储类型float)*数组深度
|
|