Proteus仿真Arduino MEGA开发板的GPS模块

该博客介绍了一个基于Arduino的物联网项目开发过程,包括创建开发板、添加GPS模块和仿真串口的步骤。文章详细讲解了如何解析GPS模块发送的$GPRMC数据,包括时间、位置、速度等信息,并提供了错误处理函数。代码示例展示了如何存储和处理接收到的GPS数据,以便在物联网应用中使用。

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

第一步:创建开发板,选择对应的型号

第二步:添加GPS模块

 第三步:添加仿真串口

 第四步:代码烧进去

 二,代码部分


$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
<1> UTC时间,hhmmss(时分秒)格式    08 时20 分06 秒
<2> 定位状态,A=有效定位,V=无效定位
<3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)  北纬38 度52.9276 分
<4> 纬度半球N(北半球)或S(南半球)
<5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)  东经115 度27.4283 分
<6> 经度半球E(东经)或W(西经)
<7> 地面速率(000.0~999.9节,前面的0也将被传输)
<8> 地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)
<9> UTC日期,ddmmyy(日月年)格式    26日10月09年
<10> 磁偏角(000.0~180.0度,前面的0也将被传输)
<11> 磁偏角方向,E(东)或W(西)
<12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)

注意几点:
1、当GPS数据有效时第17位(一般情况下,程序里最好是找第二个逗号在取下一位判断)为“A”,无效时为“V”;
2、GPS有效时,当速度为0时显示0.0(两位数),当速度不为0时小数点前面数据根据情况变化,最大为三位,此处速度单位为节(海里),需要做处理才能得到我们习惯的单位(公里/小时);
3、GPS无效时,除了第17位显示V以外,不输入速度,角度数据;
4、当给GPS复位时第17位为V,不输出速度,角度,时间数据。

代码参考:Arduino项目开发:物联网应用

#define GPSSerial Serial
#define DEBUGSerial Serial1    //注意这里一定义
int L=13;                     //LED指示灯的引脚

struct {
  char GPS_Buffer[80];
  bool isGetData;           //是否获取到GPS数据
  bool isParseData;        //是否解析完成
  char UTCTime[11];         //UTC时间
  char latitude[11];        //维度
  char  N_S[2];             //N/S
  char longitude[12];            //经度
  char  E_W[2];             //E/W
  bool isUsefull;           //定位信息是否有效
}Save_Data;

const unsigned int gpsRxBufferLength=600;

char gpsRxBuffer[gpsRxBufferLength];
unsigned int ii=0;


void setup() {                     //初始化部分
    GPSSerial.begin(9600);        //定义波特率9600
    DEBUGSerial.begin(9600);
    pinMode(L,OUTPUT);
    DEBUGSerial.println("Wating....");
    
    Save_Data.isGetData=false;      //结构体初始化
    Save_Data.isParseData=false;
    Save_Data.isUsefull=false;
}

void loop() {
    gpsRead();                     //获取GPS数据
    
    parseGpsBuffer();               //解析GPS数据

    printGpsBuffer();               //输出解析后的数据

 
}

/*---------------解析 错误时函数----------------------------*/
void errorLog(int num)                         //解析错误
{
  DEBUGSerial.print("ERROR");
  DEBUGSerial.println(num);
  while(1)
  {
    digitalWrite(L,HIGH);
    delay(300);
    digitalWrite(L,LOW);
    delay(300);
  }
}

/*----------------获取 GPS 数据-------------------------------*/
void gpsRead()                          //获取GPS数据
{
    while(GPSSerial.available())
  {
    gpsRxBuffer[ii++]=GPSSerial.read();
    //Serial1.println(ii);
    if(ii==gpsRxBufferLength)clrGpsRxBuffer();     //判断是否到达最大,600
  }
 char *GPS_BufferHead;
 char *GPS_BufferTail;
 
  if((GPS_BufferHead=strstr(gpsRxBuffer,"$GPRMC,"))!=NULL|| (GPS_BufferHead=strstr(gpsRxBuffer, "$GNRMC,"))!=NULL)  //判断接受到数据是否为 $GNRMC 或 $GPRMC
  {
    //Serial1.println("");
    if(((GPS_BufferTail=strstr(GPS_BufferHead,"\r\n"))!=NULL)&&(GPS_BufferTail>GPS_BufferHead))            //判断换行符,
    {
       memcpy(Save_Data.GPS_Buffer,GPS_BufferHead,GPS_BufferTail-GPS_BufferHead);                       //将数据存储到,结构数据位
       Save_Data.isGetData=true;
       clrGpsRxBuffer();                      //清空
    }
  }
}

/*---------------获取数据达到 最大值-----------------------------*/
void clrGpsRxBuffer(void)
{
  memset(gpsRxBuffer,0,gpsRxBufferLength);     //清空
  ii=0;
}

/*-------------------解析 GPS 数据-----------------------------*/
void parseGpsBuffer()
{
  char *subString;
  char *subStringNext;
  //Serial1.println("start.....");
  if(Save_Data.isGetData)
  {
    Save_Data.isGetData=false;
    DEBUGSerial.println("*************");
    DEBUGSerial.println(Save_Data.GPS_Buffer);      //输出读取的数据
    for(int i=0;i<7;i++)
    {
      if(i==0)
      {
        if((subString=strstr(Save_Data.GPS_Buffer,","))==NULL)  //从结构体中查找,是否有 ,如果存在返回第一次出现的逗号地址
        errorLog(1);                            //解析错误
      }
      else
      {
        subString++;//Serial1.print(i  );Serial1.println(subStringNext);
        if((subStringNext=strstr(subString,","))!=NULL) //从结构体中查找,是否有 ,如果存在返回第一次出现的逗号地址开始
        {
          char usefullBuffer[2];
          switch(i)
          {
            case 1:memcpy(Save_Data.UTCTime,subString,subStringNext-subString);
            break;                                                //获取UTC 时间
            case 2:memcpy(usefullBuffer,subString,subStringNext-subString);
            break;                                                //获取UTC时间
            case 3:memcpy(Save_Data.latitude,subString,subStringNext-subString);
            break;                                                //获取维度信息
            case 4:memcpy(Save_Data.N_S,subString,subStringNext-subString);
            break;                                                 //获取 N/S
            case 5:memcpy(Save_Data.longitude,subString,subStringNext-subString);
            break;                                                  //获取经度信息
            case 6:memcpy(Save_Data.E_W,subString,subStringNext-subString);
            break;                                                  //获取 E/W
            default:break;
          }

          subString=subStringNext;
          Save_Data.isParseData=true;
          
          if(usefullBuffer[0]=='A')
          Save_Data.isUsefull=true;
          else if(usefullBuffer[0]=='V')
          Save_Data.isUsefull=false;
          
        }
        else 
         {
          errorLog(2);                   //解析错误 
         }
      }
    }
  }
}

/*----------输出 解析后的数据--------------------*/
void printGpsBuffer()
{
  if(Save_Data.isParseData)
  {
    Save_Data.isParseData=false;
    DEBUGSerial.print("Save_Data.UTCTime= ");
    DEBUGSerial.println(Save_Data.UTCTime);
    if(Save_Data.isUsefull)
    {
      Save_Data.isUsefull=false;
      DEBUGSerial.print("Save_Data.latitude=");
      DEBUGSerial.println(Save_Data.latitude);

      DEBUGSerial.print("Save_Data.N_S=");
      DEBUGSerial.println(Save_Data.N_S);

      DEBUGSerial.print("Save_Data.longitude=");
      DEBUGSerial.println(Save_Data.longitude);

      DEBUGSerial.print("Save_Data.E_W=");
      DEBUGSerial.println(Save_Data.E_W);
      
    }
    else
    {
      DEBUGSerial.println("GPS DATA is not usefull!");
      Serial1.println("");
      Serial1.print("\n\n");
      
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值