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();
}
}