Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
UART
串口发送数据,接收方收到的数据分了几包。
发布于 2020-12-07 22:24:58 浏览:2839
订阅该版
在使用串口发送数据的时候,一包数据大概260个字节左右,发送的时候是整包发的,但是好像在发送的过程中被打断了,接收方可以接收到,但是可以看到是分了几次才接收到的,这种情况怎么处理? 接收方用的是串口空闲中断来接收数据。 数据发送方,用的是rt的发送接口,代码如下: ```c rt_err_t my_uart_putchar(const char *name,const rt_uint8_t c) { rt_size_t len = 0; rt_uint32_t timeout = 0; rt_device_t uart_device = RT_NULL; uart_device = rt_device_find(name); if (RT_NULL == uart_device) { rt_kprintf("when uart putchar, %s device not found!\n",name); return -RT_ERROR; } do { len = rt_device_write(uart_device, 0, &c, 1); timeout++; } while (len != 1 && timeout < 500); return RT_EOK; } ``` ``` void my_uart_putbytes(const char *name,const rt_uint8_t *s, rt_uint16_t len) { for (int j = 0; j < len; ++j) { my_uart_putchar(name,s[j]); } } ```
查看更多
wenbodong
2020-12-08
这家伙很懒,什么也没写!
接收方使用串口空闲中断的提前是:发送方要连续发送。如果接收方超过一个字节周期接收不到数据视为空闲,则发送方的发送线程不能被打断超过一个字节周期。如果是115200波特率的话,这个周期大概是86us。被打断超过这个时间是很容易的,比如在另一个线程打印了一条日志。 解释方法有很多,以下是几种方案: 1. 提高发送线程的优先级,并保证比他高优先级的线程和中断函数中不执行长时间的操作,比如打印日志。更简单一点,将发送线程优先级提至最高,那只需要保证中断函数中不执行长时间操作即可。不建议关中断,115200波特率的一个字节是86us,十几个字节能达到1ms,这是相当长的时间。关中断的话,可能会丢失很多数据。 2. 使用DMA发送。 3. 接收方使用软件来检测空闲,而不是硬件。这样可以放宽实时要求,比如1ms接收不到数据视为本包结束。当然,这样会牺牲一点传输带宽。人家每86us就可以发新包,而你得等1ms。 下面贴出我日常使用的接收代码,即第3种方案。 初始化串口时通过rt_device_set_rx_indicate设置回调,在回调中发送一个数据事件。 ```c /** * 硬件串口接收数据的回调函数 * * @param stream 串口流 * @param drv 串口设备 * @param size 待接收的数据大小 * * @return */ rt_err_t serial_stream_rx_notify(serial_stream_t *stream, rt_device_t dev, rt_size_t size) { rt_event_send(stream->serial_rx_event, SERIAL_RX_EVENT); return RT_EOK; } ``` 这是接收一个字节的函数,其先调用rt_device_read读取,若有数据则直接返回。若无数据,则等待数据事件。等待成功了再读取数据,若超时则返回失败。 ``` /** * 从串口流读取单个字节数据 * * @param stream 串口流 * @param timeout 超时时间 * * @return 实际读取的字节数 */ rt_int32_t serial_stream_read_byte(serial_stream_t *stream, rt_tick_t timeout) { rt_uint8_t data; rt_err_t ret; rt_uint32_t event; while(RT_TRUE) { if(rt_device_read(stream->serial, 0, &data, 1) == 1) { return data; } ret = rt_event_recv(stream->serial_rx_event, SERIAL_RX_EVENT, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, timeout, &event); if(ret != RT_EOK) { return -1; } } } ``` 当然,你肯定不是想一个字节一个字节的接收的,所以请看下面这个函数。其负责接收一整包数据。请注意,有两个超时时间。begin_timeout是首字节超时,cont_timeout是字节间超时。cont_timeout是负责分包的,那为什么还要有个begin_timeout呢?想象一下,我并不知道对方什么时候会发数据,它可能1个小时只发1包数据,如果我使用1ms超时来接收,那将不停地收到空数据。虽然这也没啥问题,不过笔者不喜欢哈哈。如果长时间无数据也不需要做额外操作的话,可以把begin_timeout设置为RT_WAITING_FOREVER。 ``` rt_size_t serial_stream_read_bytes2(serial_stream_t *stream, rt_uint8_t *buf, rt_size_t size, rt_tick_t begin_timeout, rt_tick_t cont_timeout) { rt_size_t i; rt_int32_t data; for(i = 0; i < size; i++) { data = serial_stream_read_byte(stream, i == 0 ? begin_timeout : cont_timeout); if(data == -1) { break; } buf[i] = (rt_uint8_t)data; } return i; } ```
4
个回答
默认排序
按发布时间排序
whj467467222
认证专家
2020-12-07
开源,分享,交流,共同进步
串口是字符型设备,每次发送数据一定是一个字节一个字节,你使用轮询的模式去发送,这个发送的动作还是在线程当中,你能保证你发送的时候不被其他高优先级的任务和其他中断打断吗?当然你可以使用关闭中断的方式来实现,但是这样就严重影响了 RTOS 的实时性。 所以分包是一个不可能避免的事情,你能做的就是如何去把分开的包给组合起来。
技术宅
2020-12-20
这家伙很懒,什么也没写!
关注一下
lqwuliang
2022-07-01
天下没有解决不了的bug,只有发现不了的bug.
DMA接收,空闲中断接收。再加个定时器超时判断,再拼包处理
撰写答案
登录
注册新账号
关注者
2
被浏览
2.8k
关于作者
小小李sunny
这家伙很懒,什么也没写!
提问
24
回答
1444
被采纳
289
关注TA
发私信
相关问题
1
rt thread 2.0.2 usart 接收缓存问题
2
关于STM32串口通信的问题
3
STM32F1+RTT串口接收终端数据丢失问题
4
UART TX丢数据?
5
RTT打开串口的时候如何自定义波特率呢?
6
STM32F4的USART数据接收问题
7
串口1234使用问题
8
串口接收回调函数
9
LPC18xx UART问题讨论
10
x1000串口配置的失败问题
推荐文章
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
在用clangd开发RTT吗,快来试试如何简单获得清晰干净的工作区
2
GD32F450 片内 flash驱动适配
3
STM32H7R7运行CherryUSB
4
RT-Smart首次线下培训,锁定2024 RT-Thread开发者大会!
5
使用RC522软件包驱动FM1722
热门标签
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
UART
WIZnet_W5500
ota在线升级
PWM
freemodbus
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
6
次点赞
YZRD
2
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部