Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
信号量_semaphore
rt_mq_消息队列_msg_queue
线程
5
一个线程可以从两个不同消息队列读写数据吗?
发布于 2022-08-01 14:44:52 浏览:721
订阅该版
如下图所属结构,5个线程,用到了3个消息队列,2个信号量,可行吗?不行就得用全局变量来控制了。 ![screenshot_图片.png](https://oss-club.rt-thread.org/uploads/20220801/51b6a034c2d5b366730576af7e891a34.png.webp) 消息类型定义 ```c typedef struct { rt_uint8_t cmd; //1 :DTU 2 :realtime 3 :other rt_uint8_t addr; //从机地址 rt_uint8_t index; //读取的数据是第几条,实时数据是8,dtu数据是8 rt_uint8_t finish; //是否接收完成 0 未完成 1完成 }message_t; ``` 发送线程一个等待线程,一个接收线程 ```c while(1) { // for(rt_uint8_t i=COMM_SN;i<24;i++) // { // if(SET_DAT.uc[COMM_SN]==1)break; // else // { // COMM_SN++; // if(COMM_SN>23)return; // } // } num = find_valid_machine(list, 24); rd_real_time(list[i]); msg_send.addr = list[i] + 1; //这里是发送给接收线程,告诉接收线程按照什么方式解析数据,设备地址 result = rt_mq_send(&mq, &msg_send, sizeof(msg_send)); if (result != RT_EOK) { rt_kprintf("rt_mq_send ERR\n"); } //这是从接收线程读取队列,知道数据是否处理完成 result = rt_mq_recv(&mq, &msg_recv, sizeof(msg_recv),1000); if (result == RT_EOK) { //比较发送时的地址、指令、条目编号 if (msg_recv.addr == msg_send.addr && msg_send.cmd == msg_recv.cmd && msg_send.index == msg_recv.index) { if (msg_recv.finish == 1)//判断接收完成 { msg_send.cmd = 1;//发送读取dtu数据的指令 msg_send.finish = 0;//发送未完成 result = rt_mq_send(&mq, &msg_send, sizeof(msg_send)); rd_dtu_data(list[i],1,1,0);//dtu数据 if (result != RT_EOK) { rt_kprintf("rt_mq_send ERR\n"); } } } } rt_memset(&msg_recv, 0, sizeof(msg_recv)); result = rt_mq_recv(&mq, &msg_recv, sizeof(msg_recv),1000); if (result == RT_EOK) { if (msg_recv.addr == msg_send.addr && msg_send.cmd == msg_recv.cmd && msg_send.index == msg_recv.index) { // if (msg_recv.finish == 1) // { i++;//不管是否有dtu数据,i都会自加,和下一个地址的机器通信 // } } } rt_thread_delay(1000); } ``` 这是接收线程 ```c while(1) { rt_uint16_t i,j,n = 0; rt_uint8_t crc=0,addr; if (result == RT_ERROR) { } //从发送线程接收消息队列,得到解析数据的方式。不知道为什么,接收之后,result是0xFFFFFFFE,问题就出在这里 result = rt_mq_recv(&mq, &msg_recv, sizeof(msg_recv),1000); if (result == RT_EOK) { if(msg_recv.cmd == 2)//读取实时数据 { rt_uint16_t len = 0; if(recv_ok == 1) { if (USART3_RX_BUF[0] == msg_recv.addr) { // len = USART3_RX_BUF[2]<<8 + USART3_RX_BUF[3]; for(rt_uint16_t i=0;i<(USART3_RX_LEN+6-2);i++) { crc+=USART3_RX_BUF[i]; } if ((crc ==USART3_RX_BUF[USART3_RX_LEN-1]) && (COMM_addr3==USART3_RX_BUF[0])) { if(USART3_RX_BUF[1]==0x10)//向环控器写入数据后,收到环控器返回数据 { //printf("写入环控器后收到环控器返回的信息%d\n",USART3_RX_BUF[2]); if((USART3_RX_BUF[2]>=1)&&(USART3_RX_BUF[2]<=7)) { RS485_OK=USART3_RX_BUF[2]; } if((USART3_RX_BUF[2]>=9)&&(USART3_RX_BUF[2]<=11)) { RS485_OK=USART3_RX_BUF[2]-1; } } else if (USART3_RX_BUF[1]==0x03) { addr=COMM_addr3-1; COMM_OK[addr]=1;//这里是控制实时数据页面显示绿色 红色 灰色 for(rt_uint8_t i=0;i<160;i++) { SSSJ.uc[addr][i]=USART3_RX_BUF[4+i]; } msg_send = msg_recv; msg_send.finish = 1; //发送队列,告诉发送线程指定的数据已经解析完成 rt_mq_send(&mq, &msg_send, sizeof(msg_send)); } } } } } else if (msg_recv.cmd == 1) { //DTU模式,不用解析,直接发送 rt_device_write(dev, 0, USART3_RX_BUF,USART3_RX_LEN); msg_send = msg_recv; msg_send.finish = 1;//finish不重要,0或者1,都需要和下一台机器通信了 msg_send.cmd = 1;//说明是DTU通信 rt_mq_send(&mq, &msg_send, sizeof(msg_send)); } } ``` ------------ 下面是8月2日11:29补充 **发现一个问题,先发送消息队列,然后接收消息队列,因为用的一个消息队列,是不是直接在这里就把消息队列的消息接收了,导致接收线程接收不到消息。** **两个线程互相通信,类似半双工,需要两个消息队列吗?** ```c //这里是发送给接收线程,告诉接收线程按照什么方式解析数据,设备地址 result = rt_mq_send(&mq, &msg_send, sizeof(msg_send)); if (result != RT_EOK) { rt_kprintf("rt_mq_send ERR\n"); } //这是从接收线程读取队列,知道数据是否处理完成 result = rt_mq_recv(&mq, &msg_recv, sizeof(msg_recv),1000); ```
查看更多
3
个回答
默认排序
按发布时间排序
出出啊
2022-08-01
恃人不如自恃,人之为己者不如己之自为也
可以,别用 RT_WAITING_FOREVER,改成等待若干 ms 。然后判断返回值,如果是超时继续读下一个消息。如果不是超时进入消息处理。
aozima
2022-08-01
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
有图好评👍
flashman2002
2022-08-02
这家伙很懒,什么也没写!
图中的消息队列C的作用没有看懂,目的用于切换什么?消息队列不能用于切换任务的。
撰写答案
登录
注册新账号
关注者
0
被浏览
721
关于作者
伊森亨特
这家伙很懒,什么也没写!
提问
77
回答
31
被采纳
0
关注TA
发私信
相关问题
1
rt_object_init中报assertion failed错误?
2
在 MDK中的NANO 里创建消息队列失败,内存堆已开启
3
如何用消息队列传递结构体数据
4
消息队列满了以后接收乱码
5
消息队列传输不定长数据
6
使用消息队列在线程中发送总失败
7
初始化第二个消息队列时发生硬件错误
8
rtthread消息队列一对多的情况
9
消息队列为什么会出现获取到的内容有旧的数据?
10
通过消息队列名称,获取消息队列句柄
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
freemodbus主机在freertos的适配,参考rtthread例程
2
开源共生 商业共赢 | RT-Thread 2024开发者大会议程正式发布!
3
【24嵌入式设计大赛】基于RT-Thread星火一号的智慧家居系统
4
RT-Thread EtherKit开源以太网硬件正式发布
5
还在担心bsp不好维护吗?快使用yml管理主线bsp
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部