N32WB452LEQ6芯片USART2通信(PB4、PB5)解析GPS定位信息

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;      //
            }           
        } 
    }             
}
 

  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kevinpan2011

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值