Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
串口
串口中断回调函数
5
RT-thread 串口DMA接收丢数据
发布于 2020-11-27 17:03:47 浏览:3251
订阅该版
[tocm] # 问题描述 + 1.DMA接收数据的时候丢数据了,数据偶尔被拆掉了 + 2.例如我一个包大概是28个字节,然后会被串口的接收回调认为是两条消息,一条是1Byte,一条是27Byte。然后有时候比如说两个数据包,会被拆成3个消息。第一个消息是第一个包的第一个字节(1Byte),第二个消息是第一个包后边的27Byte和第二个包的第一个Byte,第三个消息是第二个包后边的27Byte。这样导致两个包直接废掉了。 # 实验方法 + 1.使用RT-thread的串口例程,使能串口模式为DMA_TX和DMA_RX,开启接收回调。(使用了消息队列)。 + 2.轮询不等待的形式检测消息队列的消息 + 3.具体相关的部分代码 ```c void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { struct stm32_uart *uart; RT_ASSERT(huart != NULL); uart = (struct stm32_uart *)huart; // dma_isr(&uart->serial); //注释了 } /** * @brief Rx Half transfer completed callback * @param huart: UART handle * @note This example shows a simple way to report end of DMA Rx Half transfer, * and you can add your own implementation. * @retval None */ void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) { struct stm32_uart *uart; RT_ASSERT(huart != NULL); uart = (struct stm32_uart *)huart; // dma_isr(&uart->serial); //注释了 } ``` ```c /* 接收数据回调函数 */ static rt_err_t uart3_input(rt_device_t dev, rt_size_t size) { //static int recv_tick=0; struct rx_msg msg; rt_err_t result; msg.dev = dev; msg.size = size; // uint32_t ttt = (HAL_GetTick()/((uint32_t)HAL_GetTickFreq())); // SEGGER_RTT_printf(0,"(U3)tttz:%d!\n",ttt); result = rt_mq_send(&rx_u3mq, &msg, sizeof(msg)); // 如果数据包断掉了,两个消息队列之间的间隔是大约大于1ms if ( result == -RT_EFULL) { /* 消息队列满 */ rt_kprintf("message U3 queue full!\n"); } return result; } /* 从硬件中读取数据 */ static rt_uint16_t uart_read (struct rt_messagequeue *tp_rxMq_obj,unsigned char *tp_rx_buf) { rt_uint16_t rec_len; rt_uint16_t pkg_all_len = 0; struct rx_msg msg; rt_err_t result; rt_uint8_t timeout = 0; rt_memset ( &msg, 0, sizeof ( msg ) ); result = rt_mq_recv ( tp_rxMq_obj, &msg, sizeof ( msg ), RT_WAITING_NO ); if ( result == RT_EOK ) { // 记录上一个消息包的长度 pkg_all_len = msg.size; // 也有可能多个包被中断回调处理成一个包 if(pkg_all_len <= 1) { SEGGER_RTT_printf(0,"(b)msg.size:%d!\n",msg.size); timeout = 13; // 1.3ms稍微正常 while ( timeout ) //接收不定长数据 { timeout--; rt_hw_us_delay ( 100 ); // ttt = (HAL_GetTick()/((uint32_t)HAL_GetTickFreq())); //SEGGER_RTT_printf(0,"(U3)rx_length:%d!\n",rx_length); result = rt_mq_recv ( tp_rxMq_obj, &msg, sizeof ( msg ), RT_WAITING_NO ); // 一般一条数据有可能会被拆成两条指令,1和27,可以增加判断如果等于长度等于28的时候可以直接截断命令,节省时间。 if ( result == RT_EOK ) // 接收成功 { result = -RT_ERROR; SEGGER_RTT_printf(0,"(l)msg.size:%d!\n",msg.size); //pkg_all_len = pkg_all_len + msg.size; // 补上后面的数据 pkg_all_len = msg.size; // 补上后面的数据 SEGGER_RTT_printf(0,"(l)pkg_all_len:%d!\n",pkg_all_len); break; } } } /* 从串口读取数据*/ rec_len = rt_device_read ( msg.dev, 0, tp_rx_buf, pkg_all_len ); // 如果需要读取的数值大于缓冲区实际的数值,那么返回的值则是缓冲区内容实际的值 SEGGER_RTT_printf(0,"(l)rec_len:%d!\n",rec_len); SEGGER_RTT_printf(0,"Read_Data:%\n"); for(uint8_t l_i = 0;l_i < rec_len;l_i++) SEGGER_RTT_printf(0,"%02X ",tp_rx_buf[l_i]); SEGGER_RTT_printf(0,"\r\n"); } else { rec_len = 0; } return rec_len; } ```
查看更多
Acuity
2020-11-28
这家伙很懒,什么也没写!
1、首先,这不是串口丢数据; 2、串口协议是物理层标准,无数据链路层,过来的数据的一个字节流数据(流水一样,你无法区分哪一段),与TCP协议一样类似;可靠的做法是串口加私有协议,组成一帧,通过头尾判断得出一帧数据;如加“/\r/\n”作为结束符等。(这个与TCP粘包处理方法类似) 3、如果非要通过时间超时来判断一帧的话,可以自己开一个定时器,超出一定的时间后认为是一帧;这个属于应用范畴了,RTT底层驱动是不支持这个的; 4、再举个例子,CAN标准包含了数据链路层;对于标准CAN,每次进来就是8字节长度的数据帧。
6
个回答
默认排序
按发布时间排序
trigrass
2020-11-29
这家伙很懒,什么也没写!
rt-thread 要急待加强 驱动的 设计,测试,很多基本的东西好久都解决不了, 然后又去把有限的技术力量开发新东西。 在单片机领域 用空闲时间判断帧的结束 是通用做法, rt-thread 把驱动非要设计的和linux 的流类似, 真没有必要 ,小os 就要有小os 的特点 。 所以设计一个 合理的驱动架构 api 是非常重要的 ,尽量满足大多数应用的要求。
swet123
2022-01-22
ztlchina@foxmail.com
亲们, 你们这个标题太耸人听闻了。 串口是流式设备, 拆包是非常正常的。 你的应用要合并包应该是基础操作。 包括TCP, 基本操作就是要合并包,拆包。 我以为真的是丢数, 看来是拆包的问题。
Polarbear
2020-11-27
这家伙很懒,什么也没写!
# 错误情况补充 + 1.有时候接收中断给的消息大小会是只有几个字节,但是消息长度一般都是固定的 + 2.还有一种情况就是第一个消息是【28Byte(第一个数据包完整的)+1Byte(第二个数据包的第一个字节)】,第二个数据包是【27Byte+28Byte(第三个完整的数据包)】。这样就会废掉三个数据包。 + 3.每次触发了串口中断接收回调的时候发的第一个消息的msg.size都是1个字节的,每一个包的第一个字节很大概率会被拆掉一样。所以才做了超时判断去组装剩下的27Byte数据. # 观察情况补充 + 1.使用逻辑分析仪发现每个数据包的第一个字节跟后面的字节相隔大概35~40us。 # 期望结果 + 1.每次触发了中断接收回调函数的时候希望msg.size是准确的,不要被拆包了。
Jacksi
2020-12-02
这家伙很懒,什么也没写!
使用了串口空闲中断,其实也会出现拆包的现象。因为无法保证对端发送数据是一帧完整的发过来,也有可能拆成几包发过来,串口就是个字节流的设备。还是需要自己在帧协议方面处理下。
aprilhome
2021-05-26
这家伙很懒,什么也没写!
楼主解决了没?我现在也是同样的问题,一个29字节的数据可能被拆成1字节+28字节。但是这种现象只在其他单片机发送数据时出现,如果不用单片机而是用串口助手发就不会。并且根据论坛其他帖子屏蔽掉了dma_isr了。
撰写答案
登录
注册新账号
关注者
1
被浏览
3.3k
关于作者
Polarbear
这家伙很懒,什么也没写!
提问
7
回答
7
被采纳
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
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部