Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
串口
定时器
超时
超时判断串口接收完成时,超时时间选择多少合适?
发布于 2022-12-07 09:53:28 浏览:2216
订阅该版
因为串口接收的时候,会把一条数据分成几段来接收。所以采用定时器超时判断接受完一条完整数据。思路是接收到数据后,启动定时器,写入超时时间T,如果超过T,触发定时器超时函数,说明T时间内没有收到数据,完成了一条数据的接收。 这是串口配置代码,9600波特率DMA接收。 ```c 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 )) {} ``` 接收回调里释放信号量 ```c 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; } ``` 接收线程里读取不到信号量,则不执行下面的内容,读到信号量,则开始接收数据,把接收的数据保存在数组里,后续处理。 ```c 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。效率太低了。 我需要修改代码哪个地方,来避免这种情况呢?**
查看更多
4
个回答
默认排序
按发布时间排序
Ryan_CW
认证专家
2022-12-07
这家伙很懒,什么也没写!
给你参考我的代码吧,我采用的中断接收,dma接收也可以使用。但要注意间隔时间 思想是:接收到一个字符后,就开始等待timeoutByte个时间片, 在这个时间片内接收到数据认为数据没有接收完毕,如果没有收到认为接收成功 9600波特率timeoutByte可以为5ms - 20ms modbus规定的报文间隔要大于3.5个字符,你可以算下需要延时多少。 ```c /** * @brief 串口接收数据 * * @param serial * @param buf 接受缓冲区 * @param bufSize 接受缓冲区大小 * @param timeout timeout时间后还没接收到一个字符认为失败 * @param timeoutByte 两个字符直接超过timeoutByte认为接收完成 * @return int32_t */ int32_t uartRecvData(rt_device_t serial, char *buf, int32_t bufSize, int32_t timeout, int32_t timeoutByte) { uint32_t len = 0; int16_t resut = 0; while (1) { if (rt_event_recv(&uartEvent, 1 << getUartChannel(serial), RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, timeout, NULL) != RT_EOK) return len; timeout = timeoutByte; resut = rt_device_read(serial, 0, buf + len, bufSize - len); if (resut < 0) return 0; len += resut; if (len > bufSize) return 0; } } /** * @brief 串口中断接收回调函数 * * @param dev * @param size * @return rt_err_t */ static rt_err_t modbusServiceRxCallback(rt_device_t dev, rt_size_t size) { rt_event_send(&uartEvent, 1 << getUartChannel(dev)); return RT_EOK; } ```
用户名由3_15位
2022-12-07
这家伙很懒,什么也没写!
> 思路是接收到数据后,启动定时器,写入超时时间T,如果超过T,触发定时器超时函数,说明T时间内没有收到数据,完成了一条数据的接收。 - 关于这一点,串口有个空闲中断的选项。串口判断接收两个字符的时间后没有收到发送数据就会进入空闲中断。不需要开定时器的。 - 不知道你使用的串口驱动是什么样的。我使用串口V2驱动是没什么问题的。在STM32的串口V2驱动中,使用dma接收的话,会开启空闲中断。 - 另一个开启DMA,接收数据太多,接收处理不够快,会造成分包情况。这个很正常,需要自行处理。论坛里应该有相应解决办法。 - 我是用MODBUS协议在串口上的,数据量不大,偶尔分包丢帧并不影响。上位机也有做重发处理,判断没响应重发三次。保证数据正常
梅江松子
2022-12-10
这家伙很懒,什么也没写!
![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20221210/be74af676c635807466bcd41902c5ff7.png)
lqwuliang
2022-12-14
天下没有解决不了的bug,只有发现不了的bug.
这个根据发端来,一般我25ms超时,15ms也用过
撰写答案
登录
注册新账号
关注者
1
被浏览
2.2k
关于作者
伊森亨特
这家伙很懒,什么也没写!
提问
77
回答
31
被采纳
0
关注TA
发私信
相关问题
1
串口DMA发送数据时,数据被覆盖
2
关于串口DMA模式下rt_device_close问题
3
利用stm32f427实现usb转串口,电脑端什么也没有识别到
4
finsh 控制台 适配 RS 485请大神指点????
5
uart_sample.c 中,读串口设备时偏移量pos要设置为-1而不是0?
6
【结贴】at_device软件包中对串口接收数据缺少判断导致数据接收异常
7
串口无法接受数据,但可以发送
8
串口如何有效的清除掉接收缓冲,而不必一个一个的去读取
9
串口接收使用方式问题
10
雅特力FINSH问题
推荐文章
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
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
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
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
5
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部