中级会员
- 积分
- 214
- 金钱
- 214
- 注册时间
- 2014-4-30
- 在线时间
- 26 小时
|
使用了串口的中断轮询方式,
接收线程负责接收数据,接收完之后使用消息队列发送给数据处理线程。
注意,使用队列的接收函数时 ,这里可能是个rtthread的bug:
rt_mq_recv(&mq, &tmp, sizeof(tmp), RT_WAITING_FOREVER) == RT_EOK
当rt_mq_recv接收不定长数据时会出现,rt_mq_recv每次从mq队列里取数据后没有清除原来的数据,这样会导致下一次接收到的实际消息长度小于本次长度时,下次消息队列接收到的数据是夹杂着上一次数据的尾巴。
譬如,接收buffer大小大于7,小于消息队列单个消息长度,第一次发送消息"123456",第一次调用rt_mq_recv没有问题,第二次发送消息"111"时,第二次调用rt_mq_recv接收到的数据会变成"111456"。
解决方案:
在ipc.c中的rt_mq_recv函数
rt_memcpy(buffer, msg + 1, size > mq->msg_size ? mq->msg_size : size);
后面加一句:
rt_memset(msg + 1, 0, size > mq->msg_size ? mq->msg_size : size);
源代码如下:(由于是基于自己设计的开发板板,很多底层接口和驱动没办法直接用,这里就不上次整个工程了)
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include <drv_log.h>
#include <stdio.h>
#include <string.h>
#define PORT "uart4"
typedef struct {
char buf[128];
unsigned short sta;
}uart_rcv_typedef;
uart_rcv_typedef ur;
static rt_thread_t rcv_thread = RT_NULL, parse_thread = RT_NULL;
static rt_device_t dev_uart;
char gnss_cmd[] = "version\r\n";
static struct rt_messagequeue mq;
/* 消息队列中用到的放置消息的内存池*/
static rt_uint8_t msg_pool[1024];
static struct rt_semaphore rx_sem1;
static void rcv_thread_entry(void* parameter);
static void parse_thread_entry(void* parameter);
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&rx_sem1);
return RT_EOK;
}
//主函数
int app01_gnss_thread_start(void)
{
rt_sem_init(&rx_sem1, "rx_sem1", 0, RT_IPC_FLAG_FIFO);
rt_mq_init(&mq,"mqt",&msg_pool[0], 128,sizeof(msg_pool),RT_IPC_FLAG_FIFO);/* 内存池指向msg_pool */
dev_uart = rt_device_find(PORT);
rt_kprintf("%s listen on\n",PORT);
// rt_device_open(dev_uart , RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX );
rt_device_open(dev_uart , RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX );
rt_device_set_rx_indicate(dev_uart , uart_input);
rcv_thread =
rt_thread_create( "listen_uart4",
rcv_thread_entry,
RT_NULL,
512,
10,
20);
if (rcv_thread != RT_NULL)
rt_thread_startup(rcv_thread);
else
return -1;
parse_thread =
rt_thread_create( "parse_data",
parse_thread_entry,
RT_NULL,
2048,
10,
20);
if (parse_thread != RT_NULL)
rt_thread_startup(parse_thread);
else
return -1;
return RT_EOK;
}
//线程函数
static void rcv_thread_entry(void* parameter)
{
char te[128];
char ch;
while (1)
{
while (rt_device_read(dev_uart , -1, &ch, 1) != 1)
{
rt_sem_take(&rx_sem1, RT_WAITING_FOREVER);
}
ur.buf[ur.sta++] = ch;
if(ch == '\n')
{
ur.buf[ur.sta] = '\0';
rt_mq_send(&mq, &ur.buf, ur.sta&0x7fff);
memset(&ur,0,sizeof(uart_rcv_typedef));
}
}
}
static void parse_thread_entry(void* parameter)
{
char tmp[128];
while(1)
{
if (rt_mq_recv(&mq, &tmp, sizeof(tmp), RT_WAITING_FOREVER) == RT_EOK)
{
rt_kprintf("get:%s",tmp);
}
rt_thread_mdelay(50);
}
}
INIT_APP_EXPORT(app01_gnss_thread_start);
|
|