USART接受GPS数据讨论

蒙蒙静   2011-1-11 17:23 楼主
本人新手,这是学生生涯中唯一一次接触实际的项目。现在和大家请教下普遍的串口接受的问题,以启发后面的新人(当然包括我自己)。

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

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

      对于这种情况,请教下大家是不是有更加简单和高效的方法,就可以从GPS数据帧中提起出我想要的数据呢?

回复评论 (22)

                                 可以使用DMA传输数据。
点赞  2011-1-11 17:35
                                 谢谢版主主的提示,DMA我也想到过。DMA方式是无需CPU的干预,但会不会出现我程序正在读USART缓冲区中数据时,DMA也正在写缓冲区数据的情况呢? 如果有这样的情况发送的话,应该是会出现错误吧?
点赞  2011-1-11 17:40
                                 你不是1秒钟才传送一次数据吗?这么长时间你都来不及吗?
点赞  2011-1-11 17:49
DMA只能设置接收固定字节吧?有两种长度的不太好做?

不过象GPS这种慢速外设,直接在中断里面做不就好了?
收一个存一个,收到回车(记得回车是一行数据的结尾标志),把这一行解析了(也不耗什么时间)。
然后从数组开头重新存下一行的数据。
点赞  2011-1-12 09:22
DMA只能设置接收固定字节吧?有两种长度的不太好做?

不过象GPS这种慢速外设,直接在中断里面做不就好了?
收一个存一个,收到回车(记得回车是一行数据的结尾标志),把这一行解析了(也不耗什么时间)。
然后从数 ...
赞同,直接在中断里面做比较合适。
点赞  2011-1-12 09:35
                                 速度比较慢,难度很小。
点赞  2011-1-12 09:48
                                 多谢楼上各位的回复! 我自己看了下,GPS数据长度长度不定的话,用DMA方式确实是不好做的,正如 heuyck 所说,DMA要设置接受的字节长度。heuyck提到的方法和我之前的想法一样,我试试。
点赞  2011-1-12 23:15
                                 搜“NMEA 解析”,有一个类可以解析GPS数据,并将经纬度、速度、高度、时间等信息放入一个结构体中。你可以参考一下。只需要把接收到的字节不停传递给它即可,它内部用状态机来实现解析。
点赞  2011-1-12 23:24
                                 赞
点赞  2011-1-25 14:10
                                 这个用中断或者查询来做都可以,把数据放入一个缓冲区,如果一段时间没有收到新数据(例如100ms),就认为数据帧结束了,然后再从头到尾解析一下就可以了。工作量不大的。
点赞  2011-1-26 00:22
                                 如果是9600的波特率,按800字节/秒计算,147和195字节也只分别需要0.185~0.245秒就完成,使用超时控制很容易实现的。即使按照250ms超时计算,你还有至少600~700ms的时间做计算。
点赞  2011-1-26 08:19
                                 目前我是用中断来实现的,每接受到一个字节的数据就响应接受中断。因为GPS数据有标准的帧头和帧尾,遇到帧头就开始存数据到缓冲区,遇到帧尾就解析数据。这种方法比较直接,我一开始就考虑了这个方法,我当时发帖的目的是和大家讨论下,有没有更加高效的方法。
点赞  2011-2-9 15:51
中断里面尽量少做事情。顶多是接收一下数据,然后判断一下是否需要对数据进行分析。具体的分析工作还是留到主循环去做。
另外,GPS发送出来的数据不只两种长度,是可以根据你的命令进行配置的,最长大约有500字节左右。但实际上消耗的时间没有500字节需要的那么长,实际上接收8bit是由硬件完成,软件耗时是去读的时间。当然,现在我也不是很明白,利用硬件UART接收数据时是否占用系统资源。
点赞  2011-2-10 14:38
版主说的是单字节超时,即数据流断开的时间超过一个字节所需时间的话,在串口通信时可以认为是整个数据包收完了。这个数据流的概念,在一些有通信超时检测功能的MCU里直接体现出来了,没有的话就在定时器中断里判断。在我身边的工程师,几乎没一个有这种认识,都是测量整串码所占时间,可悲...
由于协议是文本协议,控制命令和数据体一般不会重叠,按heuyck说的检测回车符也是不错的办法。
楼主说数据长度只有两种可能,我只想说,一切皆有可能,因为接收的是字符串,长度可变,随时可能变出个148和196。处理字符串绝对没有像操作整形变量那样简单。
不过标准C函数库里有大量字符串处理函数,其中就有sscanf可以直接从字符串里分离出各种形式变量的高级函数。楼主不妨了解一下。
尽管在你的项目中,数据接收速度是如此慢,但在实际应用中,可能遇到一次收到两串码的情况。这时就要考虑队列的应用了。不然就要承担丢失数据的风险。
点赞  2011-2-11 09:11
这篇帖子能得到这么多高手的讨论和指教,真是很高兴。
1. 对于sdpz再次提到的单字节超时,我在做485多机通信的时候应用过,在定时器中断中判断。
2. sscanf确实很好用,因为我只需要GPS帧中的几个数据,所以我就没有用这个函数。
3. 对于GPS输出的数据,因为我们买的是一个做好的模块,它输出的数据一次只有两种格式。我在经行帧解析的时候,首先经行帧长度的检查,如果长度不对,就认为出错了。
4. 对于sdpz提到的“尽管在你的项目中,数据接收速度是如此慢,但在实际应用中,可能遇到一次收到两串码的情况。这时就要考虑队列的应用了。不然就要承担丢失数据的风险。”,这个确实是我没有想到但确实会出现的问题,多谢sdpz的提醒。
点赞  2011-2-14 13:45
                                 mark
点赞  2011-2-16 09:12

直接上源码

void USART1_IRQHandler(void)
{  
        char pchar,*pstr;

        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
            /* Clear the USART1 Receive interrupt */
            USART_ClearITPendingBit(USART1, USART_IT_RXNE);

            /* Read one byte from the receive data register */
                pchar = USART_ReceiveData(USART1)&0xFF;
            
                RxBuffer1[RxCounter1++] = pchar;
               
                if(pchar == '\r') {               
                        pstr = strstr( (char*)RxBuffer1, "$GPRMC");          

                        if(        pstr != NULL) {         
                                sscanf( pstr,"$GPRMC,%[^,],%c,%f,%c,%f,%c,%f,%f,%[^,]",
                                                gps.gprmc.utc_time,
                                           &(gps.gprmc.status),
                                                &(gps.gprmc.latitude_value),
                                                &(gps.gprmc.latitude),
                                           &(gps.gprmc.longtitude_value),
                                                &(gps.gprmc.longtitude),
                                                &(gps.gprmc.speed),
                                           &(gps.gprmc.azimuth_angle),
                                                gps.gprmc.utc_data
                                          );                        
                        }
                        RxCounter1 = 0;                               
                }
        }     
}
点赞  2011-7-20 11:41
你好,我现在也在做stm32串口接收GPS数据,现在有代码方面的问题,可以询问一下吗,我的qq是1308846319,你的QQ是多少,方便联系
点赞  2016-3-4 16:47
引用: seu_zhang 发表于 2016-3-4 16:47
你好,我现在也在做stm32串口接收GPS数据,现在有代码方面的问题,可以询问一下吗,我的qq是1308846319,你 ...

你这得留电话号码
点赞  2016-3-15 11:55
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复