打印
[STM32F1]

【原创】论串口的随机不定格式字符串接收

[复制链接]
1347|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

本篇帖子介绍串口随机接收数据的一种方法,
不大众也不通用,但却比较适合某些特定场合,
本文内容可与此篇相对照,
关于串口随机接收不确定字符串的讨论

先说一下项目应用背景
因项目需要,用到了SIM868模块,
需要同时使用两路串口通信,分辨进行GPRS数据通信,
并实时获取GPS定位数据,问题比较棘手(能力有限啊)。

GPRS通信方面,上电初期需要按照一定的指令顺序对SIM868模块进行初始化,
用过SIM相关莫快得朋友都明白,就是固定格式的一堆AT指令,
成功连接服务器后不断发送各种通信数据,包括AT指令以及一些通信数据,
GPS方面需要从大片的串口数据中返回我们需要的某一条指令数据,
并截取指定位置的数据,上传至服务器
例如下图(需要截取指定的定位数据)


面临的问题:
1、AT指令设计数十条,需要按顺序发送,并队返回得响应进行对应的处理,
指令顺序切不可乱,返回的结果要可靠获取,并作出响应,
2、AT指令与自定义格式数据存在混杂,并可能出现响应延迟,
导致“答非所问”的现象。
3、串口发挥数据量较大,且长度格式不定,要截取的有用数据却不多,
而且要求尽可能少出错
4、通信频率较高,此处使用115200bps,单片机资源有限,STM32仅有72Mhz,
同时要进行一些其他工作。






沙发
通宵敲代码|  楼主 | 2017-1-6 20:04 | 只看该作者
本帖最后由 通宵敲代码 于 2017-1-6 20:10 编辑


针对以上问题,我们按需分配使用两路USART(STM32串口不少),
分辨对接GPRS通信与GPS通信,使用中断接收方试获取数据。


针对第一个问题,串口需要按顺序发送相应的AT指令,不可错乱,
我们定义一套惭怍不找,使用swith case语句按步执行,
每一步设定执行条件,一步一步执行,就可解决。如下


使用特权

评论回复
板凳
通宵敲代码|  楼主 | 2017-1-6 20:04 | 只看该作者
本帖最后由 通宵敲代码 于 2017-1-6 20:29 编辑


第二个问题跟第三个问题基本属于同一种情况,主要是串口中断中如何按要求接受处理数据,
由于STM32的串口只有8字节的移位寄存器,
不具有缓存区(可以用DMA功能自己开辟缓存区),
因此串口每接收一个自己就中断一次,
大量数据接收时,需要串口频繁中断,
此时根本来不及进行数据处理,否则极易造成数据丢包,
只能讲数据存取缓存区,待中断结束后再处理。

如一楼中的图所示,GPS接口每次返回大量的数据,
而对我们有用的却只有标出的那一行数据,
其他字节数据的接收同样造成单片机触发串口中断,
但却是毫无意义的时钟浪费,必须要尽可能低减少.


经过实验测试,我们选定了一下这种方法,
首先,按照有效字节长度,开辟一块缓存区,
用于数据的存储,并定义一个全局变量,
记录串口接收的字节数。如下所示


由于我们所要接收数据的特殊性与一致性,
(有同样的格式内容却又各不相同),注意观察第一幅图,
因此,在中断函数中,我们只需判断有效数据的报头即可,
具体函数如下。


我们使用了多层if嵌套,用于正确获取报头,
并根据判断结果,设置数据存储的位置,
只有当报头完全复合时才开始存储有效数据,
当报头不符时,只需要执行几条if判断即可跳过,
经过测试,以STM32的处理速度,完全不存在丢包问题,
当然还可以进行更深入的优化,此处不做扩展。

至于接收下来的数据如果处理,
我们采用了一种比较大众的方法——数逗号
先把,数据轮询一次,找到每个逗号的位置,
然后以逗号为参考,获取各逗号之间的数据




使用特权

评论回复
地板
通宵敲代码|  楼主 | 2017-1-6 20:04 | 只看该作者
本帖最后由 通宵敲代码 于 2017-1-6 20:36 编辑

以上方法,只能针对固定格式,固定字符串,但GPRS通信时,每次返回的字符串都不一样,
甚至同一条指令在不同情况下返回的数据都不同,

针对这个问题,我们仍采用同样的处理模式,
不过这次判断的条件不固定,我们使用全局变量,
针对每条指令可能会出现的结果,
但度设置接收字符串的格式,
只有当接收到我们想要的字符串时,
才触发事件标志位进行数据处理。如下所示

串口中使用变量作为判断条件,针对不同的判断结果,
及时改变数据接收位置,或设置事件标识。


每发送一条指令,都设置相应的接收条件


接收效果如下


然后我们在对比接收到的数据,进行相应的处理即可


使用特权

评论回复
5
通宵敲代码|  楼主 | 2017-1-6 20:29 | 只看该作者
本帖最后由 通宵敲代码 于 2017-1-6 20:39 编辑


同时,为了更好地接收我们自己的数据,
我们设置了两个固定的报头和报尾,0xAA,0x4C
这样我们只需要从串口接收到的字符串中,
截取我们需要的数据就可以啦,如下图


使用特权

评论回复
6
LyCrystal| | 2017-1-7 09:27 | 只看该作者
谢谢分享

使用特权

评论回复
7
oufuqiang| | 2017-1-7 14:53 | 只看该作者
数据流处理,各路神仙显神通

使用特权

评论回复
8
皈依| | 2017-1-7 16:36 | 只看该作者
楼主也喜欢用st标准库啊

使用特权

评论回复
9
通宵敲代码|  楼主 | 2017-1-8 12:12 | 只看该作者
皈依 发表于 2017-1-7 16:36
楼主也喜欢用st标准库啊

用惯了而已,
而且各种资料,
都是用的标准库,
所以不择呢用cube

使用特权

评论回复
10
通宵敲代码|  楼主 | 2017-1-8 12:13 | 只看该作者
oufuqiang 发表于 2017-1-7 14:53
数据流处理,各路神仙显神通

见笑见笑,
很拙劣的一个办法,最近有点忙,
有时间研究研究上位机的处理方式,
应该还会有更好的办法

使用特权

评论回复
11
a136498491| | 2017-1-8 17:52 | 只看该作者
我是UART+DMA+FIFO,然后一个一个的判断出数据类型,分别处理。

使用特权

评论回复
12
通宵敲代码|  楼主 | 2017-1-9 12:13 | 只看该作者
a136498491 发表于 2017-1-8 17:52
我是UART+DMA+FIFO,然后一个一个的判断出数据类型,分别处理。

硬件资源的充分利用啊
不错不错

使用特权

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

本版积分规则

个人签名:年轻不是资本,奋斗才是良策!

302

主题

7540

帖子

69

粉丝