发新帖我要提问
12
返回列表
打印
[其他]

移植NMEA协议库解析GGA数据格式

[复制链接]
楼主: 鱿鱼丝
手机看帖
扫描二维码
随时随地手机跟帖
21
鱿鱼丝|  楼主 | 2023-6-28 14:35 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
5-2 解码测试函数nmea_decode_test()
解码函数主要是调用函数库中的函数,并加标志位进行处理。
/**
  * @brief  nmea_decode_test 解码GPS模块信息
  * @param  无
  * @retval 无
  */
int nmea_decode_test(void)
{
        double deg_lat;//转换成[degree].[degree]格式的纬度
        double deg_lon;//转换成[degree].[degree]格式的经度
       
    nmeaINFO info;          //GPS解码后得到的信息
    nmeaPARSER parser;      //解码时使用的数据结构  
    uint8_t new_parse=0;    //是否有新的解码数据标志
  
    nmeaTIME beiJingTime;    //北京时间
        uint8 str_buff[50];
       
    /* 设置用于输出调试信息的函数 */
    nmea_property()->trace_func = &trace;
    nmea_property()->error_func = &error;
    nmea_property()->info_func = &gps_info;

    /* 初始化GPS数据结构 */
    nmea_zero_INFO(&info);
    nmea_parser_init(&parser);

    while(1)
    {
//          for(int t = 0;t<256;t++){uart_putchar(DEBUG_UART,gps_rbuff[t]);}
      if(GPS_HalfTransferEnd)     /* 接收到GPS_RBUFF_SIZE一半的数据 */
      {
        /* 进行nmea格式解码 */
        nmea_parse(&parser, (const char*)&gps_rbuff[0], HALF_GPS_RBUFF_SIZE, &info);
        
        GPS_HalfTransferEnd = 0;   //清空标志位
        new_parse = 1;             //设置解码消息标志
      }
      else if(GPS_TransferEnd)    /* 接收到另一半数据 */
      {

        nmea_parse(&parser, (const char*)&gps_rbuff[HALF_GPS_RBUFF_SIZE], HALF_GPS_RBUFF_SIZE, &info);
      
        GPS_TransferEnd = 0;
        new_parse =1;
      }
      
      if(new_parse)                //有新的解码消息   
      {   
        /* 对解码后的时间进行转换,转换成北京时间 */
        GMTconvert(&info.utc,&beiJingTime,8,1);
        
        /* 输出解码得到的信息 */
        //        printf("\r\n时间%d-%02d-%02d,%d:%d:%d\r\n", beiJingTime.year+1900, beiJingTime.mon,beiJingTime.day,beiJingTime.hour,beiJingTime.min,beiJingTime.sec);

                //info.lat lon中的格式为[degree][min].[sec/60],使用以下函数转换成[degree].[degree]格式
                deg_lat = nmea_ndeg2degree(info.lat);
                deg_lon = nmea_ndeg2degree(info.lon);

//                printf("\r\n纬度:%f,经度%f\r\n",deg_lat,deg_lon);
//                printf("\r\n海拔高度:%f 米 ", info.elv);
//                printf("\r\n速度:%f km/h ", info.speed);
//                printf("\r\n航向:%f 度", info.direction);
//                printf("\r\n正在使用的GPS卫星:%d,可见GPS卫星:%d",info.satinfo.inuse,info.satinfo.inview);
//                printf("\r\n正在使用的北斗卫星:%d,可见北斗卫星:%d",info.BDsatinfo.inuse,info.BDsatinfo.inview);
//                printf("\r\nPDOP:%f,HDOP:%f,VDOP:%f",info.PDOP,info.HDOP,info.VDOP);
      
                /* 显示时间日期 */
                sprintf(str_buff," Date:%4d/%02d/%02d ", beiJingTime.year+1900, beiJingTime.mon,beiJingTime.day);
                LCD_ShowString(0,2,str_buff,BLACK);

                sprintf(str_buff," Time:%02d:%02d:%02d", beiJingTime.hour,beiJingTime.min,beiJingTime.sec);
                LCD_ShowString(0,20,str_buff,BLACK);

                /* 正在使用的卫星 可见的卫星*/
                sprintf(str_buff," GPS:%2d ", info.satinfo.inuse);
                LCD_ShowString(150,0,str_buff,BLACK);

                /* 正在使用的卫星 可见的卫星*/
                sprintf(str_buff," BDS:%2d ", info.BDsatinfo.inuse);
                LCD_ShowString(150,20,str_buff,BLACK);

                /* 纬度 经度*/
                sprintf(str_buff," lat:%.6f ", deg_lat);
                LCD_ShowString(0,40,str_buff,BLUE);

                sprintf(str_buff," lon:%.6f",deg_lon);
                LCD_ShowString(115,40,str_buff,BLUE);

                /* 速度 */
                sprintf(str_buff," speed:%4.2f km/h", info.speed);
                LCD_ShowString(0,60,str_buff,RED);

                /* 航向 */
                sprintf(str_buff," Angle:%3.2f deg", info.direction);
                LCD_ShowString(0,80,str_buff,MAGENTA);
                new_parse = 0;
      }
        }
}

使用特权

评论回复
22
鱿鱼丝|  楼主 | 2023-6-28 14:36 | 只看该作者
根据串口的内容,紧接着调用 NMEA库函数 nmea_parse 进行解码,解码的结果存放在数据结构变量 info 中,由于解码结果得到的时间信息是格林威治时间,所以在输出解码结果前,调用了 GMTconvert 函数把它转化成北京时间。

使用了 nmea_ndeg2degree 函数把 info.lat 及 info.lon 参数转化到了 deg_lat 和 deg_lon 变量中。

info.lat 及 info.lon 存储的就是纬度、 经度信息,但它们的单位是[degree][min].[sec/60]格式,即 NMEA 语句解码后的原始 ddmm.mmmm 表示的数据,通常在地图上使用的格式都是[degree].[degree], 所以一定要经过这样转换后再使用。

使用特权

评论回复
23
鱿鱼丝|  楼主 | 2023-6-28 14:36 | 只看该作者
5-3 MM32堆栈空间设置
由于 NMEA 解码库在进行解码时需要动态分配较大的空间,所以我们需要在 MM32的启动文件 startup_mm32f327x_keil.s 文件中对堆栈空间进行修改,本工程中设置的栈空间大小设置为 0x00002000, 堆空间大小设置为 0x0000 0800。
Stack_Size      EQU     0x00002000  
;这时候为8kb栈空间 实测最大调用为3264b

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp

; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size       EQU     0x00000800

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

                PRESERVE8
                THUMB

使用特权

评论回复
24
鱿鱼丝|  楼主 | 2023-6-28 14:52 | 只看该作者
主函数调用
#include "headfile.h"
// **************************** 代码区域 ****************************

int main(void)
{
        board_init(true);                                                                        //初始化 UART1 DEBUG输出串口
        GPS_Config();                                                                                //初始化 GPS   DMA加大容量栈空间
        Lcd_Init();        LCD_ShowString(0,0,"GPS_TEST",MAGENTA);        //初始化 IPS   ST7789屏幕       
        nmea_decode_test();                                                                  //GPS解码测试

        while(1)
        {
        }
       
}

使用特权

评论回复
25
鱿鱼丝|  楼主 | 2023-6-28 14:52 | 只看该作者
在全部模块初始化结束之后,就可以在屏幕上边参数信息了,包括经纬度和时间等等。

另外:确认天线处在卫星信号良好的位置中, 天线需要正面朝上,并置于室外无遮挡物处。 若把天线置于室内,是无法定位的,卫星信号在室内基本无信号

最后工程文件我将放置在百度网盘链接: https://pan.baidu.com/s/1QRNr87n38MjN-yKf30Uiww提取码:jr2t

不足之处多多指教,工程的我是根据野火的NMEA库移植而来。dma配置部分花费的时间比较多,后来看了灵动官网的一些配置,参考而来。参数手册很重要,一些dma的通道都是从中看来的。

使用特权

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

本版积分规则