打印

USART 接受GPS数据讨论

[复制链接]
7273|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xuqj4490|  楼主 | 2011-1-11 17:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人新手,这是学生生涯中唯一一次接触实际的项目。现在和大家请教下普遍的串口接受的问题,以启发后面的新人(当然包括我自己)。

     现在我是需要用STM32的USART接受GPS输出的数据,GPS固定每1秒输出一次。STM32的USART没有固定的接受缓冲区。我的理解就是需要每接受到一个字节,就响应下串口接受中断,然后把这个数据读到你自己设置的缓冲区中,这样做是可以,但比较麻烦。

     对于GPS这种数据,它的数据帧的长度只有两种可能(我手里的是这样的,分别是147和195个字节),且他们数据帧的帧头和帧尾都是固定的。

      对于这种情况,请教下大家是不是有更加简单和高效的方法,就可以从GPS数据帧中提起出我想要的数据呢?
沙发
香水城| | 2011-1-11 17:35 | 只看该作者
可以使用DMA传输数据。

使用特权

评论回复
板凳
xuqj4490|  楼主 | 2011-1-11 17:40 | 只看该作者
谢谢香版主的提示,DMA我也想到过。DMA方式是无需CPU的干预,但会不会出现我程序正在读USART缓冲区中数据时,DMA也正在写缓冲区数据的情况呢? 如果有这样的情况发送的话,应该是会出现错误吧?

使用特权

评论回复
地板
香水城| | 2011-1-11 17:49 | 只看该作者
你不是1秒钟才传送一次数据吗?这么长时间你都来不及吗?

使用特权

评论回复
5
heuyck| | 2011-1-12 09:22 | 只看该作者
DMA只能设置接收固定字节吧?有两种长度的不太好做?

不过象GPS这种慢速外设,直接在中断里面做不就好了?
收一个存一个,收到回车(记得回车是一行数据的结尾标志),把这一行解析了(也不耗什么时间)。
然后从数组开头重新存下一行的数据。

使用特权

评论回复
6
IJK| | 2011-1-12 09:35 | 只看该作者
DMA只能设置接收固定字节吧?有两种长度的不太好做?

不过象GPS这种慢速外设,直接在中断里面做不就好了?
收一个存一个,收到回车(记得回车是一行数据的结尾标志),把这一行解析了(也不耗什么时间)。
然后从数 ...
heuyck 发表于 2011-1-12 09:22


赞同,直接在中断里面做比较合适。

使用特权

评论回复
7
呆瓜一个| | 2011-1-12 09:48 | 只看该作者
速度比较慢,难度很小。

使用特权

评论回复
8
xuqj4490|  楼主 | 2011-1-12 23:15 | 只看该作者
多谢楼上各位的回复! 我自己看了下,GPS数据长度长度不定的话,用DMA方式确实是不好做的,正如 heuyck 所说,DMA要设置接受的字节长度。heuyck提到的方法和我之前的想法一样,我试试。

使用特权

评论回复
9
mohanwei| | 2011-1-12 23:24 | 只看该作者
搜“NMEA 解析”,有一个类可以解析GPS数据,并将经纬度、速度、高度、时间等信息放入一个结构体中。你可以参考一下。只需要把接收到的字节不停传递给它即可,它内部用状态机来实现解析。

使用特权

评论回复
10
jgphu| | 2011-1-25 14:10 | 只看该作者

使用特权

评论回复
11
TuBie| | 2011-1-26 00:22 | 只看该作者
这个用中断或者查询来做都可以,把数据放入一个缓冲区,如果一段时间没有收到新数据(例如100ms),就认为数据帧结束了,然后再从头到尾解析一下就可以了。工作量不大的。

使用特权

评论回复
12
香水城| | 2011-1-26 08:19 | 只看该作者
如果是9600的波特率,按800字节/秒计算,147和195字节也只分别需要0.185~0.245秒就完成,使用超时控制很容易实现的。即使按照250ms超时计算,你还有至少600~700ms的时间做计算。

使用特权

评论回复
13
xuqj4490|  楼主 | 2011-2-9 15:51 | 只看该作者
目前我是用中断来实现的,每接受到一个字节的数据就响应接受中断。因为GPS数据有标准的帧头和帧尾,遇到帧头就开始存数据到缓冲区,遇到帧尾就解析数据。这种方法比较直接,我一开始就考虑了这个方法,我当时发帖的目的是和大家讨论下,有没有更加高效的方法。

使用特权

评论回复
14
roc_qiu| | 2011-2-10 14:38 | 只看该作者
中断里面尽量少做事情。顶多是接收一下数据,然后判断一下是否需要对数据进行分析。具体的分析工作还是留到主循环去做。
另外,GPS发送出来的数据不只两种长度,是可以根据你的命令进行配置的,最长大约有500字节左右。但实际上消耗的时间没有500字节需要的那么长,实际上接收8bit是由硬件完成,软件耗时是去读的时间。当然,现在我也不是很明白,利用硬件UART接收数据时是否占用系统资源。

使用特权

评论回复
15
sdpz| | 2011-2-11 09:11 | 只看该作者
香主说的是单字节超时,即数据流断开的时间超过一个字节所需时间的话,在串口通信时可以认为是整个数据包收完了。这个数据流的概念,在一些有通信超时检测功能的MCU里直接体现出来了,没有的话就在定时器中断里判断。在我身边的工程师,几乎没一个有这种认识,都是测量整串码所占时间,可悲...
由于协议是文本协议,控制命令和数据体一般不会重叠,按heuyck说的检测回车符也是不错的办法。
楼主说数据长度只有两种可能,我只想说,一切皆有可能,因为接收的是字符串,长度可变,随时可能变出个148和196。处理字符串绝对没有像操作整形变量那样简单。
不过标准C函数库里有大量字符串处理函数,其中就有sscanf可以直接从字符串里分离出各种形式变量的高级函数。楼主不妨了解一下。
尽管在你的项目中,数据接收速度是如此慢,但在实际应用中,可能遇到一次收到两串码的情况。这时就要考虑队列的应用了。不然就要承担丢失数据的风险。

使用特权

评论回复
16
xuqj4490|  楼主 | 2011-2-14 13:45 | 只看该作者
这篇帖子能得到这么多高手的讨论和指教,真是很高兴。
1. 对于sdpz再次提到的单字节超时,我在做485多机通信的时候应用过,在定时器中断中判断。
2. sscanf确实很好用,因为我只需要GPS帧中的几个数据,所以我就没有用这个函数。
3. 对于GPS输出的数据,因为我们买的是一个做好的模块,它输出的数据一次只有两种格式。我在经行帧解析的时候,首先经行帧长度的检查,如果长度不对,就认为出错了。
4. 对于sdpz提到的“尽管在你的项目中,数据接收速度是如此慢,但在实际应用中,可能遇到一次收到两串码的情况。这时就要考虑队列的应用了。不然就要承担丢失数据的风险。”,这个确实是我没有想到但确实会出现的问题,多谢sdpz的提醒。

使用特权

评论回复
17
berry2006| | 2011-2-16 09:12 | 只看该作者
mark

使用特权

评论回复
18
xiepengchenghn| | 2011-7-7 20:33 | 只看该作者
mark,遇到类似问题

使用特权

评论回复
19
lzfbillie| | 2013-1-9 21:45 | 只看该作者
mark一下,马上要开始这部分的问题

使用特权

评论回复
20
nnhy| | 2013-1-10 01:50 | 只看该作者
直接二进制操作数据,应该就是最快的了

使用特权

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

本版积分规则

9

主题

33

帖子

2

粉丝