因为串口接收的时候,会把一条数据分成几段来接收。所以采用定时器超时判断接受完一条完整数据。思路是接收到数据后,启动定时器,写入超时时间T,如果超过T,触发定时器超时函数,说明T时间内没有收到数据,完成了一条数据的接收。
这是串口配置代码,9600波特率DMA接收。
struct serial_configure pconfig;
/* 初始化串口 /
if (env_dev == RT_NULL)
{
env_dev = rt_device_find(ENV_NAME);
RT_ASSERT(env_dev);
pconfig.baud_rate = BAUD_RATE_9600;
pconfig.data_bits = DATA_BITS_8;
pconfig.stop_bits = STOP_BITS_1;
pconfig.parity = PARITY_NONE;
pconfig.bit_order = BIT_ORDER_LSB;
pconfig.invert = NRZ_NORMAL;
pconfig.bufsz = 4096;
pconfig.reserved = 0;
/ 设置串口参数 */
rt_device_control(env_dev, RT_DEVICE_CTRL_CONFIG, &pconfig);
/*设置串口的回调函数 */
rt_device_set_rx_indicate(env_dev, env_recv_ind);
}
if(RT_EOK ==rt_device_open(env_dev, RT_DEVICE_FLAG_DMA_RX ))
{}
接收回调里释放信号量
rt_err_t env_recv_ind(rt_device_t dev, rt_size_t size)
{
/* release semaphore to let finsh thread rx data */
rt_uint8_t ch = 0;
if (size > 0)
rt_sem_release(&env_rx);
return RT_EOK;
}
接收线程里读取不到信号量,则不执行下面的内容,读到信号量,则开始接收数据,把接收的数据保存在数组里,后续处理。
timeout_s.sec = 0; /* 秒 */
timeout_s.usec = 300000;
if (timeout == 1 && old_recv_cnt != 0 && recv_cnt == 0)
{
timeout = 0;
old_recv_cnt = 0;
LOG_D("接收定时溢出");
tmp_ptr = recv_buff;
rt_device_control(hw_dev, HWTIMER_CTRL_STOP, RT_NULL);
// dump_hex(recv_buff, cnt);//调试用
rt_memcpy(USART3_RX_BUF,recv_buff,sizeof(USART3_RX_BUF));//数据给USART3_RX_BUF
USART3_RX_LEN = cnt;//得到有效数据长度
rt_sem_release(&recv_comp);
recv_ok = 1;
cnt = 0;
cnt_test = 0;
}
if (rt_sem_take(&env_rx,1000) != RT_EOK)
{
continue;
}
else
{
rt_event_send(&feed_dog_event, EVENT_FLAG3);
}
rt_event_send(&feed_dog_event, EVENT_FLAG3);
while (recv_cnt = rt_device_read(env_dev, -1, tmp_ptr, 4096) )
{
// LOG_I("recv_cnt = %d", recv_cnt);
rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) ;
cnt += recv_cnt;
tmp_ptr += recv_cnt;
old_recv_cnt = recv_cnt;
}
重点在这里,我设置的时间是300ms,经过测试,设置时间短了,经常不能完整接收一条数据。但是300ms也太长了,串口发送数据,中间的间隔,怎么也不至于300ms,但是少于300ms,就接受不完整,300ms,就接收完整。
裸机时候开个定时器,好像超时时间10ms就够了。现在如果一条数据分成5段,则前面4段的等待时间是[0,300]ms,最后一段等待时间是300ms,接收一条完整数据最少要等待300+ms。效率太低了。
我需要修改代码哪个地方,来避免这种情况呢?
更多回帖