Я хочу проанализировать данные GNSS из предложения NMEA, используя STM32F0 и Truestudio - PullRequest
0 голосов
/ 05 января 2019

У меня возникли трудности при разборе данных GPS из предложения NMEA. Я использую GNSS-модуль Quectel L89 (скорость в бодах: 115200) и IDE Truestudio. Я использовал CubeMX для создания скелетной структуры программы.

Я пытался использовать оба HAL_UART_RxCpltCallback с HAL_UART_Receive_IT и HAL_UART_Receive_IT независимо. Я могу читать данные иногда, а иногда нет. Дело в том, что необработанные данные начинаются с $ GPRMC и заканчиваются $ PSTMCPU, а чтение данных из ST иногда rec_buffer начинается с $ GPRMC (нормальное состояние), а иногда с $ GNVTG (неправильное условие).

Как я могу убедиться, что rec_buffer всегда начинается с $ GPRMC

Я звоню в то время как (1):

  HAL_UART_Receive_IT(&huart2, rec_buff, 2400);  // from GPS UART

Я тоже пробовал это:

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 RAW DATA:

$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

Любая помощь / предложение будет оценено.

Спасибо Клиффорд за ваши предложения. Мне нужно проанализировать данные из RMC, VTG, GGA и GSA. Я не могу изменить скорость передачи, а также не могу останавливать проприетарные предложения.

1 Ответ

0 голосов
/ 06 января 2019

Нет ничего «неправильного» в выводе вашей GNSS; для такого устройства является нормальным выводить ряд стандартных и проприетарных предложений. Вы несете ответственность за настройку модуля на вывод только тех предложений, которые вам нужны, или разбора предложений и отбрасывания тех, которые вам не нужны.

Отправьте в GNSS следующую команду, чтобы отключить все настраиваемые предложения, кроме предложения RMC:

$PSMTSETPAR,1201,0X00000040*75

Вам необходимо либо отправлять эту конфигурацию каждый раз при запуске, либо сохранять конфигурацию в энергонезависимой памяти с помощью:

$PSMTSAVEPAR*58

Возможно, что модуль выведет другие предложения, которые не могут быть изменены (я не знаком с конкретным модулем); Вам все еще может потребоваться выполнить анализ и фильтрацию на хосте. Это так же просто, как синтаксический анализ идентификатора говорящего и спецификатора формата, а также отбрасывание предложений, которые вам не интересны. Существует множество способов сделать это; Ваш вопрос не показывает такой попытки.

Ваш код слишком "низкоуровневый" - формат предложения IEC61162-1 (NMEA 0183) ориентирован на строки, но HAL_UART_Receive_IT() будет просто собирать порцию данных без какого-либо знания протокола и полностью асинхронно к структуре предложения - вы можете легко начинать и заканчивать середину предложения. Более того, HAL_UART_RxCpltCallback() происходит в контексте прерывания - это не место для получения больших порций данных и их анализа. Сначала вам потребуется код последовательного ввода-вывода более высокого уровня, который буферизует входящие данные в очередь и поддерживает линейно-ориентированный ввод.

Затем вам нужно обработать каждую строку - отбросить те, которые не представляют интереса. В этом смысле это слишком широкий вопрос, и он не связан конкретно с анализом данных GNSS - это не совсем ваша проблема здесь, это, как я говорю, более низкий уровень, чем чем - вам не нужно создавать подходящую инфраструктуру последовательного ввода-вывода.

Другая проблема заключается в том, что вы ожидаете получения 2400 символов, вы получите данные в виде кусков, и действительными будут только последние полученные данные. Если в режиме реального времени требуется получение текущей позиции; Вы не можете сделать это таким образом.

Я не эксперт ST HAL и не хотел бы использовать его; это плохо документировано. То, что вы должны сделать в HAL_UART_RxCpltCallback, - это поместить полученные данные в буфер FIFO, который будет обработан каким-либо другим потоком (то есть не в контексте прерывания); из-за переменной длины предложений NMEA вам придется делать это на основе одного символа. Возможно, более простой способ - опросить приемный буфер HALL с нулевым тайм-аутом и накапливать символы до тех пор, пока строка не станет доступной. Затем вы можете проверить эту строку, чтобы увидеть, является ли это предложение RMC, а затем обработать его. Например, следующее позволяет неблокирующую обработку последовательного ввода. Если никакие другие функции не требуются, время ожидания может быть увеличено до бесконечного ожидания для каждого символа:

// 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
}
...