Arduino GPS 解析

该代码示例展示了如何从串口流中解析和提取GPS的GNGGA信息。通过检查接收到的字符,一旦找到GNGGA标识符,就提取并打印相关信息。同时,提供了两种不同的实现方式,一种使用字符数组,另一种使用字符串处理。在处理过程中,注意了数据的清除和重用,确保能连续接收和解析新的GNGGA数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码来自多个部分,不一一引用。仅供参考。

GNGGA信息解析

char msg_line[600];
char read;
int i = 0;

void setup() {
  // put your setup code here, to run once:
  Serial1.begin(38400);
  Serial.begin(38400);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial1.available()) {
    //Serial.print((char)Serial1.read());
    msg_line[i++] = (char)Serial1.read(); // read each character into the list
    //Serial.print(msg_line[i]);

    if(i >= 580) {
      int ii = 0;
      while(ii<i){
      if(ii+20 < 600 && msg_line[ii] == 'G' && msg_line[ii+1] == 'A'){  //对GA那一行进行提取
        int t = ii;
        while(t<ii+73){
          Serial.print(msg_line[t]);
          t++;}//print info 
       }
       ii++;
       }
      memset(msg_line, 0, 600);
      i = 0;} //clear info
    //Serial.print((char)Serial1.read());
  }
}

GGA提取

#define GPSMAX 670                                                             //GPS数据读取一次获得长度
#define GGA 70                                                                      //GGA长度
#define READBEGIN  600                                                      //开始提取GPS长度

char gpsdata[GPSMAX];                                                          //GPS数据提取
char read;
char gpsread[GGA];                                                             //提取的GPS字符串

void GPSread()     //GPS数据读取
{
  int kk = 0;
  if (gpsSerial.available()) {
    gpsdata[i++] = (char)gpsSerial.read();                                                                       //读取每一个元素
    if(i >= READBEGIN) {
      int ii = 0;
      while(ii < i){
        if(ii+GPSMAX-READBEGIN < GPSMAX && gpsdata[ii] == 'G' && gpsdata[ii+1] == 'G' && gpsdata[ii+2] == 'A'){ 
         //对GGA那一行进行提取
          int tt = ii;
          while(gpsdata[tt] != '\n'){
            gpsread[kk++] = gpsdata[tt];
            //Serial.print(gpsdata[tt]);                                                                            //输出提取的GPS数据 
            tt++;
          }
          gpsread[kk+1] = '\n';
          Serial.print('\n');
        }
        ii++;
      }
      memset(gpsdata, 0, GPSMAX);
      i = 0;
    } //clear info
  }
}

下面GNGGA 提取代码,问题在于:如何从串口流里面提取到GNGGA 完整语句。。。

#include <SoftwareSerial.h>

SoftwareSerial ss(4, 3);  // RX,TX

// 变量声明
String gngga = "";  // 读取到的GNGGA信息
String info[15];  // 用字符数组存储
int commaPosition = -1;

//函数声明
String getTime(); // 获取北京时间
String getLat(); // 获取纬度dd.mmssss
String getLng(); // 获取经度dd.mmssss
String getStatus(); // 获取当前定位状态,0=未定位,1 = 非差分定位,2=差分定位

void setup() {
  Serial.begin(9600);
  ss.begin(9600);
}

void loop() {
  gngga = "";
  while (ss.available() > 0) {
    gngga += char(ss.read());
    delay(10);  // 延时,不延时的话就会跳出while循环
  }

  if (gngga.length() > 0) {
    //Serial.println(gngga);
    //在这里进行数据的解析
    for (int i = 0; i < 15; i++) {
      commaPosition = gngga.indexOf(',');
      if (commaPosition != -1)
      {
        //Serial.println(gngga.substring(0, commaPosition));
        info[i] = gngga.substring(0, commaPosition);
        gngga = gngga.substring(commaPosition + 1, gngga.length());
      }
      else {
        if (gngga.length() > 0) {  // 最后一个会执行这个
          info[i] = gngga.substring(0, commaPosition);
          //Serial.println(gngga);
        }
      }
    }
    Serial.println("time: " + getTime());
    Serial.println("lat: " + getLat());
    Serial.println("lng: " + getLng());
    Serial.println("status: " + getStatus());
  }
}

String getTime(){
   return info[1];
}

String getLat(){
   return info[2];  
}

String getLng(){
   return info[4];  
}

String getStatus(){
   return info[6]; 
}

提供一种思路:

#include <avr/wdt.h>
#include <LiquidCrystal.h>
#include <Adafruit_GPS.h>
#include <Arduino.h>
 
Adafruit_GPS GPS(&Serial3); //Create GPS object
LiquidCrystal lcd(12,11, 10, 9, 8, 7, 6, 5, 4, 3, 2);
 
boolean flag = false;
 
void setup() {
    wdt_enable(WDTO_2S);
    pinMode(13,OUTPUT);
    lcd.begin(16,2);
    GPS.begin(9600);       //Turn GPS on at baud rate of 9600
      lcd.begin(16,2);              // columns, rows.  use 16,2 for a 16x2 LCD, etc.
      lcd.clear();                  // start with a blank screen
      lcd.setCursor(0,0);           // set cursor to column 0, row 0 (the first row)
      lcd.print("Waiting for the");    // change this text to whatever you like. keep it clean.
      lcd.setCursor(0,1);           // set cursor to column 0, row 1
      lcd.print("     satellites!");
}
 
char NMEA2[30];//30 is enough for time
 
void loop() {
    while(!GPS.newNMEAreceived()) { //Keep reading characters in this loop until a good NMEA sentence is received
          GPS.read(); //read a character from the GPS
      }
      GPS.parse(GPS.lastNMEA());  //Once you get a good NMEA, parse it
      String NMEA1 = GPS.lastNMEA();      //Once parsed, save NMEA sentence into NMEA1
      NMEA1.trim();
      if(!flag)    //if interruput not acitive, then write new value.
          NMEA1.toCharArray(NMEA2,30);
      light();
      delay(250);
}
void show(){
    lcd.clear();                  
      lcd.setCursor(0,0);  
      lcd.print("  ");
      lcd.print(NMEA2[24]);//print year
      lcd.print(NMEA2[25]);
      lcd.print(NMEA2[26]);
      lcd.print(NMEA2[27]);
      lcd.print(".");
      lcd.print(NMEA2[21]);//print month
      lcd.print(NMEA2[22]);
      lcd.print(".");
      lcd.print(NMEA2[18]);//print day
      lcd.print(NMEA2[19]);
 
      lcd.setCursor(0,1);  
      lcd.print("   ");
      lcd.print(NMEA2[7]);//print hour
      lcd.print(NMEA2[8]);
      lcd.print(":");
      lcd.print(NMEA2[9]);//print minute
      lcd.print(NMEA2[10]);
      lcd.print(":");
      lcd.print(NMEA2[11]);//print second
      lcd.print(NMEA2[12]);
      lcd.print("  UTC");
}
 
void light(){
    wdt_reset(); 
    flag = true;
    digitalWrite(13, HIGH);
 
    if(NMEA2[0] == '$' && NMEA2[3]=='Z' && NMEA2[4]=='D' && NMEA2[5] == 'A' ){//if ZDA sentence
        if(NMEA2[7] == ','){ //this means gps haven't get the time
            lcd.clear();
            lcd.setCursor(0,0);           // set cursor to column 0, row 0 (the first row)
              lcd.print("Waiting for the");    // change this text to whatever you like. keep it clean.
              lcd.setCursor(0,1);           // set cursor to column 0, row 1
              lcd.print("      satellite!");  //little change to show gps is working but not get time yet 
              flag = false;
            return;
        }
              show();
      }
      digitalWrite(13, LOW);
      flag = false;
}

制作一个基于arduino 和12864液晶模块的图形化显示GPS导航系统,作品效果和成本可能无法和TB上的导航产品媲美,但是动手过程会带给你乐趣和知识。 需要了解的背景知识: arduino 相关基础; 能使用12864 液晶模块; 能够用arduino 通过串口通信获取GPS模块定位信息; 能够用arduino 操作SD卡模块; 需要的主要硬件: arduino UNO 1片; 12864 液晶模块 1片; GPS模块1片; SD卡模块及SD卡 1套; 原理介绍: 将地图数据依据瓦片算法存储在SD卡中,通过串口获取GPS定位信息并从中解析出经纬度坐标,依据经纬度坐标读取相应地图数据显示在12864液晶模块上,同时显示定位坐标点。 1. 地图存储算法——瓦片系统(Maps Tile System) 本制作采用的地图数据和地图存储算法来源于微软的bing maps并做了相应修改,具体可参考: Bing Maps Tile System[1*] Virtual Earth Tile Image URI 参数解析 Goolge and Microsoft Map Url Parameters 在瓦片系统中地图采用金字塔式的分层存储结构,不同层具有不同级别的地图分辨率(地图精细程度),每一层地图被分割成等像素大小(256X256)的瓦片,算法要解决的问题就是给定经纬度坐标和缩放级别(层索引)得到具体相应的瓦片编号。 在连接[1*]的最后有算法实现的代码可共参考。 2. 针对12864液晶模块的设计 12864液晶模块是128像素宽64像素高的单色液晶显示模块,本制作为了适应模块显示做出了两个设计。 1). 将256X256像素的瓦片裁切成128X64像素大小的8份 子瓦片,如下图所示: 每层每个瓦片均做相应处理。 2). 通过阈值方法将8位png索引图像(bing maps 的道路数据)转换成二进制地图数据文件,为了能够显示原图中的文字信息,采用多阈值提取求或方法提取原地图中背景、地物和标注文字数据,由于标注文字和背景之间的扰动,提取效果有待改进。 显示效果: 生成地图程序(需要连接互联网): 通过设置地图范围经纬度信息获取要使用定位的区域,可通过google earth 等能显示经纬度的软件或网页获取经纬度的最大最小值(上大下小,右大左小), 缩放级别建议设置范围1~15,较大地图范围和较高缩放级别会增加地图下载、显示加载的时间。 arduino 代码说明: 1. 在“LCD12864RSPI” 文件中加入画点函数,减少重绘区域; 2. 使用占用内存小、具有只读能力的SD模块库“petit_fatfs”; 3. 分配1K内存用于地图数据缓存,由于SD卡库只支持8.3文件名,地图数据文件名采用十六进制不定长压缩编码方式命名。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值