嵌入式技术论坛
直播中

nhcp

15年用户 1137经验值
私信 关注
[问答]

一个线程可以从两个不同消息队列读写数据吗

如下图所属结构,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));

        }

    }

回帖(6)

zhongnian

2022-8-2 10:13:41
可以,别用 RT_WAITING_FOREVER,改成等待若干 ms 。然后判断返回值,如果是超时继续读下一个消息。如果不是超时进入消息处理。
举报

nhcp

2022-8-2 10:13:50
写了一下,接收消息队列的时候,返回值是没读到,为什么没有挂起呢,反而执行接收队列语句后面的语句
举报

zhongnian

2022-8-2 10:13:58
??? 怎么会没有返回值。
永久阻塞等待变成定时等待,当然会返回执行后面的语句,你看上面我说了两句话,你只看了一句吗?
判断返回值,根据返回值是不是OK再处理“接收队列语句后面的语句”
举报

nhcp

2022-8-2 10:14:08
我的意思是返回值不是RTEOK,是0xFFFFFFFE,跟那些标志位都对不上。
举报

zhongnian

2022-8-2 10:14:17
0xFFFFFFFE 不就是超时?!!!
判断非 OK 返回值要用它的负值!!!
if (ret == -RT_ETIMEOUT) {
// timeout todo
}
举报

zhongnian

2022-8-2 10:14:23
就是-2,-RT_ETIMEOUT,异常的返回值都加了负号的
举报

更多回帖

发帖
×
20
完善资料,
赚取积分