我在从NMEA语句中解析GPS数据时遇到了困难。我正在使用Quectel L89全球导航卫星系统模块(波特率: 115200)和Truestudio IDE。我用CubeMX制作了程序的骨架结构。
我试着将HAL_UART_RxCpltCallback与HAL_UART_Receive_IT和HAL_UART_Receive_IT分开使用。我有时能读数据,有时看不懂。问题是原始数据从$GPRMC开始,以$PSTMCPU结尾,而从ST读取数据时,rec_buffer从$GPRMC(ok条件)开始,有时从$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原始数据:
$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的数据。我不能改变波特率,也不能停止专有的句子。
发布于 2019-01-05 21:02:45
您的GNSS输出没有什么“错误”;这种设备输出许多标准和专有语句是正常的。您的职责是要么将模块配置为只输出所需的句子,要么解析这些句子并丢弃那些您不想要的句子。
向GNSS发送以下命令以禁用除RMC语句之外的所有可配置语句:
$PSMTSETPAR,1201,0X00000040*75您需要在每次启动时发送此配置,或者通过以下方式将配置保存在非易失性内存中:
$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语句,然后处理它。例如,以下允许对串行输入进行非阻塞处理.如果不需要执行其他函数,则可以延长超时以无限期地等待每个字符:
// 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
}https://stackoverflow.com/questions/54051269
复制相似问题