如下图所属结构,5个线程,用到了3个消息队列,2个信号量,可行吗?不行就得用全局变量来控制了。
消息类型定义
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;
发送线程一个等待线程,一个接收线程
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);
}
这是接收线程
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));
}
}
更多回帖