N32WB452LEQ6芯片USART2通信(PB4、PB5)解析GPS定位信息
主控芯片N32WB452LEQ6,系统时钟分配如下所示:
SYSCLK: 40000000
HCLK : 40000000
PCLK1 : 10000000
PCLK2 : 20000000
ADCPL : 40000000
ADCHL : 40000000
该芯片使用外部晶振,最高可以达到144MHZ,设置40MHZ是为了降低工作功耗,以适应手持设备低功耗需求。通信采用USART2通信(PB4、PB5),波特率9600,串口接收采用DMA模式,或者中断接收模式,可以通过宏定义#define USART2_DMA 1实现切换,根据产品需求,采用中断接收模式。GPS采用中科微AT6558R模组,模组每秒定时输出定位信息,资料可以去官网下载。
gps串口数据接收问题记录:
1.最初采用DMA接收,数据溢出,卡死,推测可能是每秒数据输出过多,到时DMA空闲接收无法正确判断每秒的数据包,持续不停地接收数据,应该可以通过提高通信波特率,或者过滤掉不需要的GPS数据,减少数据输出,使DMA可以通过空闲中断正确接收数据,只是当时项目比较赶,没有考虑到此处,就直接改成了普通中断接收了。
2.改为普通中断接收:接收所有数据,最大限制1K,发现经常丢失GGA数据,测试分析:数据接收解析过程,下包数据进来覆盖掉了当前数据,导致解析异常。
3.再该:每次只接收一条报文,及时缓存起来,然后解析处理数据,测试稳定。
代码前面是USART2初始化部分,后面附GPS部分解析代码,仅做记录,方便以后移植应用,无关代码,可忽略,代码已测试。
#ifndef __USART2_H
#define __USART2_H
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
#define USART2_RX_LEN 1024*8 //接受数据缓存区长度
#define USART2_TX_LEN 512 //接受数据缓存区长度
struct __USART2_ //串口数据结构体
{
char rxBuf[USART2_RX_LEN]; //接收缓存区
char txBuf[USART2_TX_LEN]; //发送缓存区
u16 rxLen; //串口1接收到的数据长度
u16 txLen; //串口1接收到的数据长度
u8 rxOk; //RX 数据接收完成标志
u8 txOk; //tx数据发送ready flag
u32 rxTimeOut;
u8 debug;
};
extern struct __USART2_ Usart2; //串口数据结构体
void usart2Init(u32 baudRate); //usart initial
void usart2Deal(void); //usart data deal
#ifdef __cplusplus
}
#endif
#endif
#include "Usart2.h"
struct __USART2_ Usart2; //串口数据结构体
// #define USART2_DMA 1
void usart2DmaInit(u32 baudRate ) //usart initial
{
GPIO_InitType GPIO_InitStructure;
USART_InitType USART_InitStructure;
NVIC_InitType NVIC_InitStructure;
DMA_InitType DMA_InitStructure;
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOB, ENABLE);
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART2, ENABLE);
GPIO_InitStructure.Pin = GPIO_PIN_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //edit by kevin
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
GPIO_ConfigPinRemap(GPIO_RMP3_USART2,ENABLE);
USART_InitStructure.BaudRate = baudRate;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
USART_Init(USART2, &USART_InitStructure);// init uart
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断通道使能
NVIC_Init(&NVIC_InitStructure); //根据配置设置
DMA_DeInit(DMA1_CH6);
DMA_InitStructure.PeriphAddr = (USART2_BASE + 0x04); //外设地址
DMA_InitStructure.MemAddr = (uint32_t)Usart2.rxBuf; //缓冲区地址
DMA_InitStructure.BufSize = USART2_RX_LEN; //传输大小(长度)
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC; //方向:外设到内存
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE; //外设地址不增
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE; //内存地址自增
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE; //外设传输数据宽度
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte; //内存传输数据宽度
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR ; //DMA_MODE_NORMAL DMA模式
DMA_InitStructure.Priority = DMA_PRIORITY_VERY_HIGH; //通道优先级
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE; //存储器到存储器模式不是能
DMA_Init(DMA1_CH6, &DMA_InitStructure);
USART_EnableDMA(USART2, USART_DMAREQ_RX, ENABLE); //使能接收DMA
USART_ConfigInt(USART2, USART_INT_IDLEF, ENABLE); //使能空闲中断
DMA_EnableChannel(DMA1_CH6, ENABLE);//使能DMA
USART_Enable(USART2, ENABLE);
}
void usart2IntInit(u32 baudRate ) //usart initial , backup code.
{
GPIO_InitType GPIO_InitStructure;
USART_InitType USART_InitStructure;
NVIC_InitType NVIC_InitStructure;
// DMA_InitType DMA_InitStructure;
// RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOB, ENABLE);
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART2, ENABLE);
GPIO_InitStructure.Pin = GPIO_PIN_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
GPIO_ConfigPinRemap(GPIO_RMP3_USART2,ENABLE);
USART_InitStructure.BaudRate = baudRate;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
USART_Init(USART2, &USART_InitStructure);// init uart
USART_Enable(USART2, ENABLE);// enable uart
USART_ClrFlag(USART2, USART_FLAG_TXC); //清除标志位
USART_ConfigInt(USART2, USART_INT_RXDNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void usart2Init(u32 baudRate )
{
#ifdef USART2_DMA
usart2DmaInit(baudRate); //usart initial,DMA rx mode
#else
usart2IntInit(baudRate); //usart initial,interupt rx mode
#endif
}
void usart2RxBuf(u8 rxData)
{
if(Usart2.rxLen<USART2_RX_LEN)
{
if (Usart2.rxOk != OK )
{
Usart2.rxBuf[Usart2.rxLen++] = rxData;
Usart2.rxTimeOut = 0;
if (Usart2.rxBuf[0] == '$')
{
if(Usart2.rxLen>10)
{
if(Usart2.rxBuf[Usart2.rxLen-2] == 0x0d && Usart2.rxBuf[Usart2.rxLen-1] == 0x0a)
{
memcpy(Gps.rxBuf,Usart2.rxBuf,Usart2.rxLen); //copy the data to buf
Gps.rxLen = Usart2.rxLen;
Gps.rxOk = OK;
memset(Usart2.rxBuf,0,Usart2.rxLen); //clear the data buf.
Usart2.rxLen = 0;
}
}
}
else
{
Usart2.rxLen = 0;
}
}
}
else
{
Usart2.rxLen =0;
memset(Usart2.rxBuf,0,USART2_RX_LEN); //clear the data buf.
}
}
#ifdef USART2_DMA
void USART2_IRQHandler(void)
{
uint32_t temp;
if ( (USART_GetIntStatus(USART2, USART_INT_OREF) != RESET) //Overrun error
|| (USART_GetIntStatus(USART2, USART_INT_NEF) != RESET) //Noise error flag
|| (USART_GetIntStatus(USART2, USART_INT_FEF) != RESET) //Framing error
)
{
temp = USART2->STS;
temp = USART2->DAT;
}
if((USART_GetIntStatus(USART2,USART_INT_IDLEF) != RESET))//IDLE line detected
{
temp = USART2->STS;//清IDLE标志
temp = USART2->DAT;
DMA_EnableChannel(DMA1_CH6,DISABLE);
temp = DMA_GetCurrDataCounter(DMA1_CH6); //应该是当前接收数据缓存器剩余空间长度
Usart2.rxLen = USART2_RX_LEN - temp; //计算出当前接收数据长度
DMA1_CH6->TXNUM=USART2_RX_LEN;
// DMA_EnableChannel(DMA1_CH6,ENABLE);
if(Usart2.rxLen<USART2_RX_LEN)
{
Usart2.rxOk =1; //数据包接收完成标志
}
else
{
memset(Usart2.rxBuf,0,USART2_RX_LEN); //clear the data buf.
}
DMA_EnableChannel(DMA1_CH6,ENABLE);
}
}
void usart2Deal(void) //This code just for testing.
{
if(Usart2.rxTimeOut>USART_TIME_OUT) //Receive timeout processing
{
Usart2.rxTimeOut = 0;
}
if(Usart2.rxOk)
{
Usart2.rxOk =0;
Usart2.rxTimeOut = 0;
memcpy(Gps.rxBuf,Usart2.rxBuf,Usart2.rxLen); //copy the data to buf
Gps.rxLen = Usart2.rxLen;
Gps.rxOk = OK;
memset(Usart2.rxBuf,0,USART2_RX_LEN); //clear the data buf.
}
}
#else
void USART2_IRQHandler(void)
{
u8 rec;
if(USART_GetIntStatus(USART2,USART_INT_RXDNE)==SET)
{
USART_ClrIntPendingBit(USART2,USART_INT_RXDNE);
rec=USART_ReceiveData(USART2); //read usart data:1byte
usart2RxBuf(rec); //rx data put into usart.rxBuf[len],and judge receiving complete.
}
//溢出-如果发生溢出需要先读SR,再读DR寄存器 则可清除不断入中断的问题
if(USART_GetFlagStatus(USART2,USART_FLAG_OREF)==SET)
{
USART_ClrFlag(USART2,USART_FLAG_OREF); //读SR
USART_ReceiveData(USART2); //读DR
}
}
void usart2Deal(void) //This code just for testing.
{
if(Usart2.rxTimeOut>USART_TIME_OUT) //Receive timeout processing
{
Usart2.rxTimeOut = 0;
}
if(Usart2.rxOk)
{
Usart2.rxOk =0;
}
}
#endif
#ifndef __GPS_H__
#define __GPS_H__
#include "main.h"
#define AGPS_CONNECT_ID 1
#define GPS_POWER(n) (n?GPIO_SetBits(GPIOB, GPIO_PIN_3):GPIO_ResetBits(GPIOB, GPIO_PIN_3));Gps.powerStatus = n
#define gpsUsartInit(baudRate) usart2Init(baudRate)
#define gpsSend(buf,len) usartSendBuf(USART2,buf,len) //usart 限定长度数据包发送
#define GPS_RX_LEN 128
#define GPS_TX_LEN 128
#define AGPS_TIME 7200 //下次AGPS时间,单位:秒
enum GPS_STATUS
{
GPS_START = 1,
GPS_AGPS,
GPS_WORK,
GPS_SHORT_WORK,
GPS_REV
};
struct __GPS_ //GPS data struct.
{
char rxBuf[GPS_RX_LEN];
// char txBuf[GPS_TX_LEN];
u32 rxTimeout;
u16 rxLen;
// u16 txLen;
u8 rxOk;
char name[30];
u16 agpsMs;
u16 agpsNum;
u8 workMode; //GPS工作模式,0省电模式、1:费电模式。
u8 hour; //gga 数据
u8 minute;
u8 second;
double latitude; //纬度
u32 mapLatitude;
char ns; //north or south
double longitude; //经度
u32 mapLongitude;
char ew; //east or west
u8 location;
u8 satelliteNum;
double hdop;
double msl;
char unit1;
double earth;
char unit2;
double differenceTime;
u32 differenceId;
u8 gpMsgNum; //GPGSV 消息数据
u8 gpMsgId; //消息号
u8 gpSatelliteNum; //卫星数目
u8 gpElevation; //仰角
u16 gpAzimuth ; //方位角
u8 bdMsgNum; //BDGSV 消息数据
u8 bdMsgId; //消息号
u8 bdSatelliteNum; //卫星数目
u8 bdElevation; //仰角
u16 bdAzimuth ; //方位角
u8 gnrmcHour; //GNRMC 数据 时
u8 gnrmcMinute; //分
u8 gnrmcSecond; //秒
char gnrmcStatus; //状态 A:有效 V:无效
double gnrmcLat; //纬度
char gnrmcNs; //南北 N=北,S=南
double gnrmcLon; //经度
char gnrmcEw; //东西 E=东 W=西
double gnrmcSpeed; //地面速度
double gnrmcOrientation; //方位
u8 gnrmcDay; //日期 日
u8 gnrmcMonth; //日期 月
u8 gnrmcYear; //日期 年
u16 high;
u32 workTime;
u32 workTimeLimit;
u32 firstWorkTime;
u8 powerStatus;
u8 openPower;
u8 status;
u8 runOk; //GPS运行OK标志。
u8 agpsEn; //允许AGPS开始标志。
u8 agpsOk; //AGPS完成标志
u8 firstLocation;
u8 firstPowerup;
u8 debug;
u8 txDebug;
u8 rxDebug;
u8 binRxDebug;
};
struct __GPS_DATA //GPS gga data struct.
{
char buf[20];
};
extern struct __GPS_ Gps;//GPS data struct.
void gpsIoInit(void); //GPS initial
void gpsDeal(void); //GPS data deal.
void agpsBinFileParser(char* buf,u32 dataLen,u32 serverID); //AGPS服务器bin文件解析。
#endif
#include "gps.h"
// GPRMC Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐定位信息
// GPVTG Track Made Good and Ground Speed(VTG)地面速度信息
// GPGGA Global Positioning System Fix Data(GGA)全球定位信息
// GPGSA GPS DOP and Active Satellites(GSA)当前卫星信息
// GPGSV GPS Satellites in View(GSV)可见卫星信息
// GPGLL Geographic Position(GLL)地理定位信息
// TXT: 短文本信息的传送(主要用于天线状态检测)
struct __GPS_ Gps;//GPS data struct.
void gpsIoInit(void) //GPS initial
{
GPIO_InitType GPIO_InitStructure;
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOB, ENABLE);
GPIO_InitStructure.Pin = GPIO_PIN_3; //GPS power controll io.
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
// GPS_POWER(TRUE); //默认打开GPS电源,不进入控制逻辑,此处打开,GPS控制比较混乱。
Gps.workTimeLimit = Parm.gpsMaxWorkTime*1000; //默认最大工作时间
Gps.debug = FALSE;
// Gps.debug = TRUE;
Gps.agpsOk = FALSE; //AGPS状态。
Gps.txDebug = FALSE;
Gps.txDebug = TRUE;
Gps.binRxDebug = FALSE;
Gps.binRxDebug = TRUE;
Gps.location = 0; //默认未定位状态。
Gps.firstLocation = FALSE;
Gps.runOk = FALSE; //GPS运行OK标志清理。
}
char findXcommaLocation(char *buf, u16 number)//从buf里面得到第num个逗号所在的位置() //返回值:0~0xFE,代表逗号所在位置的偏移.// 0xFF,代表不存在第num个逗号
{
char *p = buf;
while (number)
{
if (*buf<' ' || *buf>'z')return 0xFF;//遇到'*'或者非法字符,则不存在第num个逗号
if (*buf == ',')number--;
if(*buf == '*')
{
buf++;
break;
}
buf++;
}
return buf - p;
}
void gpsParser(void) //gps data parser.
{
if(Gps.rxOk) //GPS串口数据解析。
{
Gps.rxTimeout = Timer.ms;
if(Gps.debug)
{
debugLog("Gps.rxLen = %d.",Gps.rxLen);
// debugLog((const char*)Gps.rxBuf,Gps.rxLen); //This code just for testing.将接收到的GPS数据直接转给log口。
logSend((u8*)Gps.rxBuf,Gps.rxLen);
}
if(strstr(Gps.rxBuf,"GGA,")!=NULL) //
{
struct __GPS_DATA gga[14];
char* tempP = strstr(Gps.rxBuf,"GGA,");
u16 currentCommaNumber = 1;
u16 locationCurrent = 0;
u16 locationNext = 0;
u16 len = 0;
u8 temp = 0;
Gps.runOk = TRUE; //收到正确数据则认为GPS运行OK。
for(int bufNum = 0;bufNum<14;bufNum++) //将14串有效数据都转换出来。
{
locationCurrent = findXcommaLocation(tempP, currentCommaNumber); //当前逗号位置。
locationNext = findXcommaLocation(tempP, currentCommaNumber+1); //下一个个逗号位置。
len = locationNext - locationCurrent;
if((len > 1)&&(len<20))
{
for(int i = 0;i<len;i++)
{
gga[bufNum].buf[i] = tempP[i+locationCurrent];
}
}
else
{
for (u8 i = 0; i < 20; i++)
{
gga[bufNum].buf[i] = 0;
}
}
currentCommaNumber++;
}
u32 tempU32 = atof(gga[0].buf);
Gps.hour = tempU32/10000;
Gps.minute = (tempU32/100)%100;
Gps.second = tempU32%100;
temp = atof(gga[5].buf);
if (temp<=3||temp == 6)
{
Gps.location = temp;
}
else
{
Gps.location = 0;
}
if(Gps.location != 0)
{
Gps.latitude = atof(gga[1].buf);
tempU32 = Gps.latitude/100;
Gps.mapLatitude = tempU32*1000000+(Gps.latitude-tempU32*100)*1000000/60;
Gps.ns = gga[2].buf[0];
Gps.longitude = atof(gga[3].buf);
tempU32 = Gps.longitude/100;
Gps.mapLongitude = tempU32*1000000+(Gps.longitude-tempU32*100)*1000000/60;
Gps.ew = gga[4].buf[0];
}
else
{
Gps.latitude = 0;
Gps.mapLatitude = 0;
Gps.ns = 0;
Gps.longitude = 0;
Gps.mapLongitude = 0;
Gps.ew = 0;
}
Gps.location = atof(gga[5].buf);
Gps.satelliteNum = atof(gga[6].buf);
Gps.hdop = atof(gga[7].buf);
Gps.msl = atof(gga[8].buf);
Gps.unit1 = gga[9].buf[0];
Gps.earth = atof(gga[10].buf);
Gps.unit2 = gga[11].buf[0];
Gps.differenceTime = atof(gga[12].buf);
Gps.differenceId = atof(gga[13].buf);
if(Gps.debug)
{
debugLog("GGA解析:%02d:%02d:%02d,纬:%f,地图:%d南北:%c,经:%f,地图:%d,东西:%c,定位:%d,卫星数:%d,hdop:%f,msl:%f,单位:%c,大地:%f,单位:%c,差分时间:%f,差分Id:%d."
,Gps.hour,Gps.minute,Gps.second, Gps.latitude, Gps.mapLatitude,Gps.ns,Gps.longitude,Gps.mapLongitude,Gps.ew,Gps.location
,Gps.satelliteNum,Gps.hdop,Gps.msl,Gps.unit1,Gps.earth,Gps.unit2,Gps.differenceTime, Gps.differenceId);
}
}
else if(strstr(Gps.rxBuf,"$GNRMC,")!=NULL) //$GNRMC,080847.000,A,2235.09855,N,11357.99872,E,0.56,0.00,110923,,,A,V*09
{
struct __GPS_DATA rmc[11];
char* tempP=strstr(Gps.rxBuf,"$GNRMC,"); //更新当前指针
u16 currentCommaNumber = 1;
u16 locationCurrent = 0;
u16 locationNext = 0;
u16 len = 0;
// u8 temp = 0;
for(int bufNum = 0;bufNum<11;bufNum++) //将11串有效数据都转换出来,忽略后面的数据。
{
locationCurrent = findXcommaLocation(tempP, currentCommaNumber); //当前逗号位置。
locationNext = findXcommaLocation(tempP, currentCommaNumber+1); //下一个个逗号位置。
len = locationNext - locationCurrent;
if((len > 1)&&(len<20))
{
for(int i = 0;i<len;i++)
{
rmc[bufNum].buf[i] = tempP[i+locationCurrent];
}
}
else
{
for (u8 i = 0; i < 20; i++)
{
rmc[bufNum].buf[i] = 0;
}
}
currentCommaNumber++;
}
u32 utc = atof(rmc[0].buf);
Gps.gnrmcHour = utc/10000;
Gps.gnrmcMinute = (utc/100)%100;
Gps.gnrmcSecond = utc%100;
Gps.gnrmcStatus = rmc[1].buf[0];//状态A=数据有效;V=数据无效
if (Gps.gnrmcStatus == 'A')
{
Gps.gnrmcLat = atof(rmc[2].buf);
// tempU32 = Gps.latitude/100;
// Gps.mapLatitude = tempU32*1000000+(Gps.latitude-tempU32*100)*1000000/60;
Gps.gnrmcNs = rmc[3].buf[0];
Gps.gnrmcLon = atof(rmc[4].buf);
// tempU32 = Gps.longitude/100;
// Gps.mapLongitude = tempU32*1000000+(Gps.longitude-tempU32*100)*1000000/60;
Gps.gnrmcEw = rmc[5].buf[0];
}
else
{
Gps.gnrmcLat = atof(rmc[2].buf); //纬度
Gps.gnrmcNs = rmc[3].buf[0]; //南北
Gps.gnrmcLon = atof(rmc[4].buf); //经度
Gps.gnrmcEw = rmc[5].buf[0]; //东西
}
Gps.gnrmcSpeed = atof(rmc[6].buf); //地面速度 1节 = 1海里/小时 = 1.852km/h
Gps.gnrmcSpeed = Gps.gnrmcSpeed*18.52; //千米时扩大10倍。分辨率:0.1km/h
Gps.gnrmcOrientation = atof(rmc[7].buf); //方位
u32 date = atoi(rmc[8].buf);//日期
Gps.gnrmcDay = date/10000;
Gps.gnrmcMonth = (date/100)%100;
Gps.gnrmcYear = date%100;
if(Gps.debug) // 年 月 日 时 分 秒 定 纬 经 速 方
{
debugLog("GNRMC解析:%02d/%02d/%02d,%02d:%02d:%02d,%c,%f,%c,%f,%c,%f,%f.",Gps.gnrmcYear,Gps.gnrmcMonth,Gps.gnrmcDay,Gps.gnrmcHour,Gps.gnrmcMinute,Gps.gnrmcSecond,Gps.gnrmcStatus,Gps.gnrmcLat,Gps.gnrmcNs,Gps.gnrmcLon,Gps.gnrmcEw,Gps.gnrmcSpeed,Gps.gnrmcOrientation); //
}
}
else if(strstr(Gps.rxBuf,"$GPTXT,")!=NULL) //
{
if(strstr(Gps.rxBuf,"MS=")!=NULL)
{
char* tempP=strstr(Gps.rxBuf,"MS="); //更新当前指针
char msBuf[10] ={0};
char numBuf[10] ={0};
if(sscanf(tempP,"MS=%[^,]%*[,] %[^,]",msBuf,numBuf)!= 0)
{
Gps.agpsMs = atoi(msBuf);
Gps.agpsNum = atoi(numBuf);
if(Gps.debug)debugLog("GPTXT解析:MS=%d,%d.\r\n",Gps.agpsMs,Gps.agpsNum);
}
}
else if(strstr(Gps.rxBuf,"IC=")!=NULL)
{
char* tempP=strstr(Gps.rxBuf,"IC="); //更新当前指针
char name[50] ={0};
if(sscanf(tempP,"IC=%s",name)!= 0)
{
memcpy(Gps.name,name,30);
debugLog("GPTXT解析:IC=%s.\r\n",Gps.name);
}
}
}
memset(Gps.rxBuf,0,GPS_RX_LEN); //clear the data buf.
Gps.rxLen = 0;
Gps.rxOk =0;
if (Gps.firstPowerup == FALSE) //GPS首次上电,AGPS星历时效查询
{
Gps.firstPowerup =TRUE;
gpsSend("$PCAS03,,,,,,,,,,,1*1F\r\n",strlen("$PCAS03,,,,,,,,,,,1*1F\r\n"));
debugLog("GPS首次上电,AGPS星历时效查询.");
// gpsSend("$PCAS04,1*18\r\n",strlen("$PCAS04,1*18\r\n"));
// debugLog("GPS首次上电,设置单GPS模式,不要BD数据.\r\n");
}
}
if(Timer.ms - Gps.rxTimeout>4*1000) //GPS接收数据超时清零。
{
if(Timer.ms - Gps.rxTimeout>8*1000)
{
Gps.rxTimeout = Timer.ms; //超时变量
if (Gps.powerStatus == TRUE)
{
Gps.powerStatus = FALSE;
GPS_POWER(FALSE);
gpsUsartInit(9600); //usart initial for GPS
delay_ms(1000); //延时1秒,等待GPS彻底断电。
debugLog("GPS开机状态下,长时间未收到串口数据 ,重新初始化MCU串口,重启GPS模块.");
GPS_POWER(TRUE);
Gps.powerStatus = TRUE;
}
}
Gps.location = 0;
Gps.satelliteNum = 0;
Gps.latitude = 0;
Gps.mapLatitude = 0;
Gps.ns = 0;
Gps.longitude = 0;
Gps.mapLongitude = 0;
Gps.ew = 0;
Gps.msl = 0; //高度
Gps.gnrmcSpeed = 0; //速度
Gps.gnrmcOrientation = 0; //方向
Gps.agpsMs = 0;
Gps.agpsNum = 0;
Gps.firstLocation = FALSE;
}
if (Gps.firstLocation == FALSE) //首次定位补报一包位置,延时
{
if (Gps.location != 0) //首次定位,补报一包定位信息
{
Gps.firstLocation =TRUE;
if (Jt808.alarm == 0)
{
Jt808.alarm = ALARM_FIRST_LOCATION; //
}
}
}
}