首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我想使用STM32F0和Truestudio解析NMEA语句中的GNSS数据。

我想使用STM32F0和Truestudio解析NMEA语句中的GNSS数据。
EN

Stack Overflow用户
提问于 2019-01-05 10:54:16
回答 1查看 2.1K关注 0票数 0

我在从NMEA语句中解析GPS数据时遇到了困难。我正在使用Quectel L89全球导航卫星系统模块(波特率: 115200)和Truestudio IDE。我用CubeMX制作了程序的骨架结构。

我试着将HAL_UART_RxCpltCallbackHAL_UART_Receive_ITHAL_UART_Receive_IT分开使用。我有时能读数据,有时看不懂。问题是原始数据从$GPRMC开始,以$PSTMCPU结尾,而从ST读取数据时,rec_buffer从$GPRMC(ok条件)开始,有时从$GNVTG(错误条件)开始。

如何确保rec_buffer总是从$GPRMC开始

我在此宣布:(1)

代码语言:javascript
复制
  HAL_UART_Receive_IT(&huart2, rec_buff, 2400);  // from GPS UART

我也试过这个:

代码语言:javascript
复制
void HAL_UART_RxCpltCallback(   UART_HandleTypeDef *    huart   )
{
    if (huart->Instance == USART2)  //GPS UART
    {
        HAL_UART_Transmit(&huart1, &rec_buff[0], 1, 10);
        HAL_UART_Receive_IT(&huart2, rrc_buff, 2400);   
    }
}

L89原始数据:

代码语言:javascript
复制
$GPRMC,094640.000,A,2838.86700,N,07711.56483,E,0.4,99.3,050119,,,A*5E
$GPGGA,094640.000,2838.86700,N,07711.56483,E,1,08,1.0,226.91,M,-35.9,M,,*42
$GNGNS,094640.000,2838.86700,N,07711.56483,E,ANNNNN,08,1.0,0226.9,-35.9,,*78
$GPVTG,99.3,T,,M,0.4,N,0.7,K,A*3D
$GPGST,094640.000,46.0,26.0,17.7,0.2,25.7,18.2,19.6*68
$GPGBS,094640.000,25.7,18.2,19.6,,,,*4B
$GNGSA,A,3,23,09,03,16,26,22,27,07,,,,,1.9,1.0,1.6*28
$GNGSA,A,3,,,,,,,,,,,,,1.9,1.0,1.6*22
$GPGSV,3,1,11,16,70,076,27,03,58,227,30,23,52,331,36,26,44,046,18*78
$GPGSV,3,2,11,22,44,198,21,09,24,316,34,27,19,137,19,07,16,266,27*70
$GPGSV,3,3,11,31,14,058,,14,10,112,,08,09,164,20,,,,*45
$PSTMPRES,14.7,-4.3,3.4,4.7,8.1,-34.9,-10.0,14.5,-8.6,,,,,,,,,,,,,,,,*05
$PSTMVRES,0.3,-0.0,0.0,-0.0,0.3,0.0,-0.5,-0.5,0.1,,,,,,,,,,,,,,,,*0B
$PSTMTG,2034,553618.0000,8,128199118,10,-46760.0000,002a,1025,0,0,10,2034,553618.0000,10,2034,553618.0000,6*5A
$PSTMTS,1,23,87178102.875,-44634.02,01,36,107871,1,9650745.91,13059080.41,21268551.81,-1601.01,2104.54,-615.14,-60384.66,6.69,0,0.00,0.00,0,0,0,0*01
$PSTMTS,1,09,88801609.812,-43889.80,01,34,102805,1,16028885.38,3193585.53,20890300.53,-1492.86,2210.83,804.75,142511.90,11.66,0,0.00,0.00,0,0,0,0*07
$PSTMTS,1,03,86575601.125,-48258.84,01,30,78613,1,13348561.56,22507400.16,4720188.47,-3.99,659.00,-3098.78,52480.77,6.38,0,0.00,0.00,0,0,0,0*2D
$PSTMTS,1,16,85874269.688,-47283.16,01,27,75521,1,-1886095.16,22466622.38,13519219.09,-747.65,-1602.10,2568.93,-3251.94,5.72,0,0.00,0.00,0,0,0,0*2A
$PSTMTS,1,26,3381954.688,-49146.08,00,18,53036,1,-8037289.25,15873771.62,19660297.47,-1174.67,-2217.50,1326.00,26300.98,7.53,0,0.00,0.00,0,0,0,0*3C
$PSTMTS,1,22,3609068.188,-49215.92,00,21,27316,1,10235851.56,24348322.31,-2780494.62,-516.89,-162.93,-3068.35,-184537.24,7.77,0,0.00,0.00,0,0,0,0*08
$PSTMTS,1,27,5418358.750,-44043.68,00,19,77495,1,-10438473.00,23018353.00,-7765070.44,-768.74,651.32,3023.75,-13120.58,14.66,0,0.00,0.00,0,0,0,0*23
$PSTMTS,1,07,90050798.438,-44830.90,01,27,76584,1,25565687.72,6701073.97,4735275.25,-590.77,171.17,3061.98,17221.07,16.12,0,0.00,0.00,0,0,0,0*04
$PSTMTS,1,08,454836.875,-43869.36,00,20,3383,0,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0,0.00,0.00,0,0,0,0*2B
$PSTMNOTCHSTATUS,3786017,0,2449,0,2,5420680,0,3824,0,2*57
$PSTMADCDATA,943,903,,,,,,*48
$PSTMANTENNASTATUS,0*4D
$PSTMSBAS,0,0,,,,*19
$PSTMCPU,48.64,-1,49*41

如有任何帮助/建议,将不胜感激。

谢谢clifford的建议。我需要解析来自RMC、VTG、GGA和GSA的数据。我不能改变波特率,也不能停止专有的句子。

EN

回答 1

Stack Overflow用户

发布于 2019-01-05 21:02:45

您的GNSS输出没有什么“错误”;这种设备输出许多标准和专有语句是正常的。您的职责是要么将模块配置为只输出所需的句子,要么解析这些句子并丢弃那些您不想要的句子。

向GNSS发送以下命令以禁用除RMC语句之外的所有可配置语句:

代码语言:javascript
复制
$PSMTSETPAR,1201,0X00000040*75

您需要在每次启动时发送此配置,或者通过以下方式将配置保存在非易失性内存中:

代码语言:javascript
复制
$PSMTSAVEPAR*58

该模块可能会输出其他不可配置的句子(我不是特定模块的familiare );您可能仍然需要在主机上执行解析和筛选。这就像解析说话者ID和格式说明符以及丢弃你不感兴趣的句子一样简单。有很多方法可以做到这一点;你的问题没有显示出这样的尝试。

您的代码太“低级”了- IEC61162-1 (NMEA 0183)语句格式是面向行的,但是HAL_UART_Receive_IT()只会在不了解协议的情况下获取一大块数据,并且与句子结构完全异步--您可以很容易地开始和结束中段语句。此外,HAL_UART_RxCpltCallback()发生在中断上下文中,而不是接收大量数据并对其进行解析的地方。您首先需要一些更高级的串行I/O代码,它可以将传入的数据缓冲到队列中,并支持面向行的输入。

然后,您需要处理每一行--丢弃那些没有兴趣的行。从这个意义上说,这是一个过于宽泛的问题,与GNSS数据解析无关--这实际上不是您的问题,正如我所说的,它的级别低于-您需要构建一个合适的串行I/O基础结构。

另一个问题是,等待接收2400个字符,您将得到块的数据,并且只有最近收到的数据才是有效的。如果需要实时接收当前职位,则不能这样做。

我不是圣HAL的专家,不会选择使用它;它是很糟糕的记录。在HAL_UART_RxCpltCallback中,您应该做的是将接收到的数据放入FIFO缓冲区中,由其他线程处理(即不在中断上下文中处理);由于NMEA语句的长度可变,您需要在单个字符的基础上这样做。一种可能更简单的方法是轮询霍尔接收缓冲区,使其具有零超时,并累积字符直到一行可用为止。然后,您可以检查这一行,看看它是否是RMC语句,然后处理它。例如,以下允许对串行输入进行非阻塞处理.如果不需要执行其他函数,则可以延长超时以无限期地等待每个字符:

代码语言:javascript
复制
// Strictly NMEA0183 requires only 81 byte sentence buffer, but 
// L89 appears to output non-compliant proprietary sentences.
static char line_buffer[1024];
int line_buffer_index = 0;

for (;;)
{
    HAL_StatusTypeDef rx_status = HAL_OK ;
    while( rx_status == HAL_OK )
    {
        // Receive a character if available (zero timeout)
        char ch = 0;
        HAL_StatusTypeDef rx_status = HAL_UART_Receive( &huart2, ch, 1, 0 ) ;

        // If character received and not the LF following the previous CR
        if( rx_status == HAL_OK && ch != `\n ` )
        {
            // If the end of the sentence...
            if( ch == `\r ` )
            {
                // terminate the line
                line_buffer[line_buffer_index] = `\0` ;

                // Start a new line
                line_buffer_index = 0 ;

                // Check if line is an RMC from a GNSS
                if( line_buffer_index > 6 &&
                    memcmp( line_buffer, "$G", 2) == 0 &&
                    memcmp( &line_buffer[3], "RMC", 3) == 0 )
                {
                    // Process RMC
                    processRMC( line_buffer ) ;
                }
            }
            else
            {
                // add character to line buffer
                line_buffer[line_buffer_index] = ch ;
                line_buffer_index++ ;
                if( line_buffer_index > sizeof(line_buffer) - 1 )
                {
                    // Line too long, discard all
                    line_buffer_index = 0 ;
                } 
            }
        }
    }

    // do other work here if necessary
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54051269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档