• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

GPS模块(NMEA-0183协议)数据读取

NMEA-0183协议内容请百度资讯搜索。下面程序需要根据需要读取的数据做相应修改
/*
  @file:myNmea.c
  @说明:处理UART接收到的GPS数据
*/
#include "myNmea.h"
NMEA_Typedef nmeaTypedef;
nmeaINFO     nmeaInfo[2];
uint16_t     speedBuf[8];
unsigned char HexChar2Int(char str)
{
  unsigned char sCh;
  switch(str){
    case 'A':case 'a':sCh=10;break;
    case 'B':case 'b':sCh=11;break;
    case 'C':case 'c':sCh=12;break;
    case 'D':case 'd':sCh=13;break;
    case 'E':case 'e':sCh=14;break;
    case 'F':case 'f':sCh=15;break; 
    default:
     if((str>='0')&&(str<='9'))
     {
       sCh=str-'0';
     }
  }
  return sCh;
}
unsigned char Str2Hex(char* str,unsigned char size)
{
  unsigned char i,datHex=0;
  for(i=0;i<size;i++){
    datHex|=(HexChar2Int(str[i])<<(4*(size-1-i)));
  }
  return datHex;
}
/*
@函数:void NmeaRx(nmeaPACKTYPE nmeaPackType)
@形参:nmeaPackType:想要接收的帧数据
*/
void NmeaRx(void)
{
  if(nmeaTypedef.staFlag&UART_RX_Flag)
  {//串口接收到了一个字符
    nmeaTypedef.rxNum++;
    nmeaTypedef.staFlag&=~UART_RX_Flag;//清除标志状态
    if((nmeaTypedef.rxDatNew=='.')//小数点
     ||(nmeaTypedef.rxDatNew=='-')//负号
     ||((nmeaTypedef.rxDatNew>='0')&&(nmeaTypedef.rxDatNew<='9'))//数字
     ||((nmeaTypedef.rxDatNew>='a')&&(nmeaTypedef.rxDatNew<='z'))//小写字母
     ||((nmeaTypedef.rxDatNew>='A')&&(nmeaTypedef.rxDatNew<='Z')))//大写字母
    {
      if(nmeaTypedef.pBuf<RX_BUF_SIZE){//缓存未溢出
        nmeaTypedef.rxBuf[nmeaTypedef.pBuf++]=nmeaTypedef.rxDatNew;
      }
    }
    else
    {//其他特殊符号
      nmeaTypedef.pBuf=0;//清除buf下标
      if(nmeaTypedef.rxDatNew=='$')
      {//帧起始字符
        nmeaTypedef.rxNum=0;
        nmeaTypedef.num=0;        
        nmeaTypedef.nmeaPackType=GPNON;//当前帧未确定
        nmeaTypedef.staFlag|=GET_CHECKSUM_ENABLE;//可以开始计算校验值
        nmeaTypedef.staFlag&=~GET_CHECKSUM_OK;   //还没到获取接收的校验值的时候
      }
      else if(nmeaTypedef.rxDatNew==',')
      {//各个数据间隔标志:用来判断当前是第几个数据
        nmeaTypedef.num++;//逗号计数加1
        switch(nmeaTypedef.nmeaPackType)
        {
          case GPNON://当前帧未确定:判读当前帧的名字
           if(!strcmp(nmeaTypedef.rxBuf,"GNRMC"))     nmeaTypedef.nmeaPackType=GPRMC;
           else if(!strcmp(nmeaTypedef.rxBuf,"GNVTG"))nmeaTypedef.nmeaPackType=GPVTG;
           else{//不是想要的数据
              nmeaTypedef.rxNum=0;
              nmeaTypedef.num=0;  
           }
           break;
          case GPRMC://根据逗号个数获取GPRMC相应的数据 
            if(nmeaTypedef.num==3)
            {//获取模块定位状态
              nmeaInfo[0].status=nmeaTypedef.rxBuf[0];
            }
            break;
          case GPVTG:
            if(nmeaTypedef.num==8)
            {//获取地面速度
              nmeaInfo[0].speed=atoi(nmeaTypedef.rxBuf);
            }
            break;
          default:; 
        }
      }
      else if(nmeaTypedef.rxDatNew=='*')
      {//校验和计算结束:下面两个字符未结束的校验数据
        nmeaTypedef.staFlag|= GET_CHECKSUM_OK;   
        nmeaTypedef.staFlag&=~GET_CHECKSUM_ENABLE;//校验值计算结束
      }
      else if((nmeaTypedef.rxDatNew=='\n')
            ||(nmeaTypedef.rxDatNew=='\r'))
      {//换行符:一帧数据结束
        nmeaTypedef.num=0;
        nmeaTypedef.rxNum=0;
        if(nmeaTypedef.staFlag&GET_CHECKSUM_OK){
          nmeaTypedef.staFlag&=~GET_CHECKSUM_OK;
          nmeaTypedef.checkSum[1]=Str2Hex(nmeaTypedef.rxBuf,2);
          if(nmeaTypedef.checkSum[1]==nmeaTypedef.checkSum[0])
          {//数据正确(校验值比对正确)
            switch(nmeaTypedef.nmeaPackType){
              case GPGGA:nmeaTypedef.checkStaFlag|=GPGGA;break;
              case GPGSA:nmeaTypedef.checkStaFlag|=GPGSA;break;
              case GPGSV:nmeaTypedef.checkStaFlag|=GPGSV;break;
              case GPRMC:nmeaTypedef.checkStaFlag|=GPRMC;break;
              case GPVTG:nmeaTypedef.checkStaFlag|=GPVTG;break;
              default:;
            }
          }
          else{
            switch(nmeaTypedef.nmeaPackType){
              case GPGGA:nmeaTypedef.checkStaFlag&=~GPGGA;break;
              case GPGSA:nmeaTypedef.checkStaFlag&=~GPGSA;break;
              case GPGSV:nmeaTypedef.checkStaFlag&=~GPGSV;break;
              case GPRMC:nmeaTypedef.checkStaFlag&=~GPRMC;break;
              case GPVTG:nmeaTypedef.checkStaFlag&=~GPVTG;break;
              default:;
            }
          }
          nmeaTypedef.nmeaPackType=GPNON;
        }
      } 
      memset(nmeaTypedef.rxBuf,0,sizeof(nmeaTypedef.rxBuf));//buf清除
    }
//***************************************************
    if((nmeaTypedef.staFlag&GET_CHECKSUM_ENABLE)&&nmeaTypedef.rxNum)
    {//计算'$'和'*'之间的所有字符的异或值
      if(nmeaTypedef.rxNum==1)nmeaTypedef.checkSum[0]=nmeaTypedef.rxDatNew;
      else nmeaTypedef.checkSum[0]^=nmeaTypedef.rxDatNew;      
    }
  }
}
uint16_t speedBuf[8];
void NmeaDataDeal(void)//数据滤波处理
{
  static uint8_t  i=0,j=0;
  static uint16_t sum=0;
  if(nmeaTypedef.checkStaFlag&GPVTG)
  {//GPVTG 的值收到并且校验正确了
    nmeaTypedef.checkStaFlag&=~GPVTG;
    i++;
    if(i>=8)i=0;
    if(j<8)j++;
    sum-=speedBuf[i];
    speedBuf[i]=nmeaInfo[0].speed; 
    sum+=speedBuf[i];
    nmeaInfo[1].speed=sum/j; 
  }
  if(nmeaTypedef.checkStaFlag&GPRMC)
  {//GPRMC 的值收到并且校验正确了
    nmeaTypedef.checkStaFlag&=~GPRMC;
     nmeaInfo[1].status= nmeaInfo[0].status;
  }
}
/**************************************
**函数  :__interrupt void UART1_R_RXNE_IRQHandler(void)
**功能  :串口1接收中断入口
**形参  :无
**返回值:无
*************************************/
#pragma vector=  UART1_R_RXNE_vector
__interrupt void UART1_R_RXNE_IRQHandler(void)
{//接收数据中断
  if(UART1_SR_RXNE)
  {//读数据寄存器非空
    UART1_SR_RXNE=0;
    nmeaTypedef.rxDatNew=UART1_DR;     //接收到的数据
    nmeaTypedef.staFlag|=UART_RX_Flag; //置位标志
    NmeaRx();
  }
} 
全部回复(1)
正序查看
倒序查看
2021-08-10 19:04

#ifndef __MYNMEA_H

#define __MYNMEA_H

#include "stdint.h"

#include <string.h>

 #include <stdlib.h>

typedef enum{ 

GPNON   = 0x00, 

GPGGA   = 0x01,  

GPGSA   = 0x02, 

GPGSV   = 0x04,   

GPRMC   = 0x08, 

GPVTG   = 0x10  

}nmeaPACKTYPE;

typedef struct{

char       status;  /**< 定位状态,A=有效定位,V=无效定位*/

uint16_t   speed;   /**地面速率(0000.0~1851.8公里/小时,前面的0也将被传输)*/

}nmeaINFO;

//需要获取的信息//********************************************//********************************************//********************************************

#define RX_BUF_SIZE         10   //UART接收缓存大小//********************************************

#define UART_RX_Flag        0x01 //staFlag[0]:UART是否接收到新的数据

#define GET_CHECKSUM_OK     0X02 //staFlag[1]:是否已经计算出检验和

#define GET_CHECKSUM_ENABLE 0X04 //staFlag[2]:是否使能校验和计算//********************************************

typedef struct{

  uint8_t       staFlag;              //状态标志便变量 

uint8_t       checkStaFlag;         // 

uint8_t       checkSum[2];   

uint8_t       num; 

char          rxDatNew;            //当前串口接受到的数据    

char          rxBuf[RX_BUF_SIZE];  //UART接收缓存数组:存放接收到的速度数据 

uint8_t       pBuf;                 //BUF指针角标 

uint8_t       rxNum;                // 

nmeaPACKTYPE  nmeaPackType;

}NMEA_Typedef;

//************************************************

extern NMEA_Typedef nmeaTypedef;

void NmeaRx(void);

void NmeaDataDeal(void);

#endif //__MYNMEA_H

0
回复