打印
[STM32F1]

串口DMA/空闲中断/缓冲区的问题

[复制链接]
2694|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
djz1992|  楼主 | 2020-9-1 11:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 djz1992 于 2020-9-1 11:22 编辑

我的数据主要是三部分。
第一是AT指令;第二进入透传后的MQTT数据;第三是OTA时候的http格式数据。
这三部分数据情况都不一样,而且长度都不一定。
AT指令的回复有快有慢,有分段。
MQTT的数据不是一发一收,服务器说不定就来数据。
OTA的数据量大,http服务器那边没有分包。


捣鼓了三天。
一开始是空闲中断+DMA接收,遇到下载bin文件,数据量超过DMA缓冲区长度的时候会有问题,搞了个双缓冲。
问题来了,串口空闲中断经常把一帧数据分成两节来接收,结果放在两个缓冲区内。AT指令的回复判断都出错。好吧,加一个环形缓冲,把DMA收到的都复制出来。
一开始确实不错效果,分段的数据都被拼接到一起了,但是环形缓冲的数据是环形的。在用strstr判断是否有字符串的时候,判断范围不好控制,给了head,结尾是用\0截至,得添加一个。
在环形缓冲区里添加会混乱,又用定时器去判断是不是有数据,有就读出来。然后搞个超时,来判断后面确实没有了,可以开始处理了,再添加\0。
结果我这个菜鸟,越搞越复杂,还各种bug。
算了,老老实实的中断字节接收吧。。。

空闲中断和DMA的使用感觉还是有局限性的。
为什么一帧数据的中途会触发一次甚至几次空闲中断?如果一帧数据收完才触发空闲中断,那就舒服了啊。。。
@m564522634 @xyz549040622 @dirtwillfly

使用特权

评论回复
沙发
m564522634| | 2020-9-1 15:35 | 只看该作者
空闲中断判断的是字节超时的问题, 我估计你DMA多次触发 出问题的是AT指令那部分,因为对于单片机DMA来说那确实是两帧数据, 你这个问题是软件架构的问题,低层驱动要处理什么,服务模块要处理机,应用代码要处理要分清楚,AT指令你直观要是一帧数据,实际要是多包数据快速发送给你的,DMA很容易误断的

使用特权

评论回复
板凳
yklstudent| | 2020-9-1 21:07 | 只看该作者
有过相同经历,直接放弃研究了

使用特权

评论回复
地板
djz1992|  楼主 | 2020-9-1 21:08 | 只看该作者
m564522634 发表于 2020-9-1 15:35
空闲中断判断的是字节超时的问题, 我估计你DMA多次触发 出问题的是AT指令那部分,因为对于单片机DMA来说那 ...

是的。我现在串口DMA双缓冲,进空闲中断后立马启动另一个缓冲区的DMA接收。然后把当前缓冲区数据复制到一个buf里。
然后在处理完后全部清零。下次从头开始填充。这样一个AT指令的回复,就算分了n次进空闲中断也没事。

我在想双缓存区是不是有必要,如果是单缓冲区,进了空闲中断,先复制,复制完了后再开启DMA接收。这样行不行?会不会复制太慢引起DMA开启太晚,数据丢失?

使用特权

评论回复
5
djz1992|  楼主 | 2020-9-1 21:11 | 只看该作者
m564522634 发表于 2020-9-1 15:35
空闲中断判断的是字节超时的问题, 我估计你DMA多次触发 出问题的是AT指令那部分,因为对于单片机DMA来说那 ...

就是AT指令这部分最讨厌。AT指令的回复长短不一,而且回复的速度也相差很大,有些回复甚至要5到10秒
在没有os的情况下,很多例程都是delay等待,然后发送和处理是紧跟着的,很影响其他部分的工作。不然就用定时器,发完就走,处理部分集中在一起,超时后进入处理部分。

使用特权

评论回复
6
djz1992|  楼主 | 2020-9-1 21:13 | 只看该作者
yklstudent 发表于 2020-9-1 21:07
有过相同经历,直接放弃研究了

现在给DMA开辟了双缓冲,再配合DMA接收完复制到统一的处理缓冲区。然后处理

使用特权

评论回复
7
djz1992|  楼主 | 2020-9-1 21:14 | 只看该作者
m564522634 发表于 2020-9-1 15:35
空闲中断判断的是字节超时的问题, 我估计你DMA多次触发 出问题的是AT指令那部分,因为对于单片机DMA来说那 ...

另外,本来放弃了,想用中断单字节接收。但是中断溢出老是出错,网上说是HAL库的一个问题。我看网上的例程都是同样的写法,但是实际上会溢出错误。后来还是用了DMA和空闲中断。

使用特权

评论回复
8
m564522634| | 2020-9-8 22:37 | 只看该作者
djz1992 发表于 2020-9-1 21:14
另外,本来放弃了,想用中断单字节接收。但是中断溢出老是出错,网上说是HAL库的一个问题。我看网上的例 ...

溢出错误 是你的串口中断没有及时读取FIFO缓冲中的数据造成数据覆盖就会了生这种错误,一般造成这情况是你系统中有更加高级的中断打断了串口的接收中断造成的,你要把串口的接收中断优先级提高的

使用特权

评论回复
9
yizushijie| | 2020-9-9 08:24 | 只看该作者
AT指令存在断帧,我是依靠超时实现的。超时不到,就继续接收。需要抓取AT指令的超时时间

使用特权

评论回复
10
djz1992|  楼主 | 2020-9-11 07:59 | 只看该作者
m564522634 发表于 2020-9-8 22:37
溢出错误 是你的串口中断没有及时读取FIFO缓冲中的数据造成数据覆盖就会了生这种错误,一般造成这情况是 ...

是的。还是dma方便,就是不好控制。不过环形缓冲比较好的解决这个问题。

使用特权

评论回复
11
djz1992|  楼主 | 2020-9-11 08:01 | 只看该作者
yizushijie 发表于 2020-9-9 08:24
AT指令存在断帧,我是依靠超时实现的。超时不到,就继续接收。需要抓取AT指令的超时时间 ...

请教一个问题。AT指令部分的发送和回复判断,很多人都是发送后用delay延时,然后直接判断。这样对其他功能影响挺大,在没有os系统的话。
你是怎么操作的,可以把发送和接受处理分开,但是就得记住之前发的是什么

使用特权

评论回复
评论
yizushijie 2020-9-12 22:24 回复TA
我自己做的一个处理逻辑。每个逻辑加入正确应答,错误应答。超时应答逻辑。AT是一发一收的逻辑,发送的命令必须有回答的 
12
自己的灌饼| | 2020-9-11 09:26 | 只看该作者
我的数据主要是三部分。
第一是AT指令;第二进入透传后的MQTT数据;第三是OTA时候的http格式数据。
这三部分数据情况都不一样,而且长度都不一定。
AT指令的回复有快有慢,有分段。
MQTT的数据不是一发一收,服务器说不定就来数据。
OTA的数据量大,http服务器那边没有分包。

使用特权

评论回复
13
ufbycd| | 2020-9-11 16:36 | 只看该作者
自己的灌饼 发表于 2020-9-11 09:26
我的数据主要是三部分。
第一是AT指令;第二进入透传后的MQTT数据;第三是OTA时候的http格式数据。
这三部 ...

不要用一个函数处理全部情况,不同的协议应该歨不同的函数。
AT指令可以走轮询或中断等待接收,MQTT走中断接收,OTA走DMA接收。
或者全部都走中断接收+缓存,根据不同的协议走不同的函数去处理缓存。

使用特权

评论回复
14
ufbycd| | 2020-9-11 16:52 | 只看该作者

不要用一个函数处理全部情况,不同的协议应该歨不同的函数。
AT指令可以走轮询或中断等待接收,MQTT走中断接收,OTA走DMA接收。
或者全部都走中断接收+缓存,根据不同的协议走不同的函数去处理缓存。

使用特权

评论回复
15
zq_1943| | 2020-9-12 08:56 | 只看该作者
接收区使用环形缓冲接收机制,基本可以解决大部分问题,
至于楼主的这个问题,还是需要发送端数据稳定,保证一个空闲中断就是一帧才好解决。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:人生苦短,冬日苦长,正是青葱,却无骄阳

115

主题

620

帖子

5

粉丝