STM32开发 -- GPS模块开发详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29350001/article/details/82110535

一、了解硬件

我使用的GPS模块型号为UBX-M8030

参看:UBX-M8030 系列
参看:UBX-M8030 datasheet

1、查看一下它的特性:

多用途 GNSS 芯片,提供三种产品等级
最多可并发接收 3 个 GNSS(GPS、伽利略、GLONASS、北斗)
行业领先的 -167 dBm 导航灵敏度
业界最低电流消耗
在城市峡谷中具有绝佳的定位精度
安全性和完整性保护
支持所有的卫星增强系统
车载级芯片的工作温度为 -40°至 +105°C

2、原理图

这里写图片描述
这里写图片描述

可以看出与MCU相连的只有RXD、TXD、GPS_POW三个引脚

其中GPS_POW 模块主电源使能引脚:
用来使能BL9198稳压芯片输入5v输出3.3v

同4G模块一样,GPS_POW 引脚,高电平GPS工作,低电平GPS不工作。

#define GPS_POWER_ON()          (GPIO_SetBits   (BSP_GPIOA_PORTS, BSP_GPIOA_GPS_POWEN_PINS))
#define GPS_POWER_OFF()         (GPIO_ResetBits (BSP_GPIOA_PORTS, BSP_GPIOA_GPS_POWEN_PINS))

这里不做过多讲解了。

二、软件部分

1、初始化

首先明确一下,我们一共使用了4个串口:

4G模块 – USART1
GPS – USART2
BLE – USART3
DEBUG – UART4

串口初始化

其中串口初始化部分我就不讲了,参看:STM32开发 – 串口详解

需要注意的两点:
1、串口时钟使能
USART2是挂载在 APB1 下面的外设,所以使能函数为:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);  

2、GPIO端口模式设置
TX的GPIO工作模式为:GPIO_Mode_AF_PP;//复用推挽输出
RX的GPIO工作模式为:GPIO_Mode_IN_FLOATING;//浮空输入或者上拉输入

DMA配置

通过DMA方式接收GPS过来的数据。

void GpsRxDMACfg( uint8_t buf[],uint16_t BufferSize)
{
    DMA_InitTypeDef DMA_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //开启DMA1时钟
    USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);   //打开串口2 DMA接收使能  开启串口DMA接收

    DMA_DeInit(GPS_RxDMA_Ch);  //恢复缺省值
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR); //设置USART2发送数据寄存器
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buf; //设置发送缓冲区首地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //设置外设位目标,内存缓冲区->外设寄存器
    DMA_InitStructure.DMA_BufferSize = BufferSize; //需要发送的字节数
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不做增加调整,调整不调整都是DMA自动实现的
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存缓冲区地址增加调整
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据宽度8位,1个字节
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存数据宽度8位,1个字节
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //单次传输模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //优先级设置
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //关闭内存到内存的DMA模式
    DMA_Init(GPS_RxDMA_Ch, &DMA_InitStructure); //写入配置
    DMA_Cmd(GPS_RxDMA_Ch, ENABLE); //开启DMA通信,等待接收数据
}

这里留下一个小疑问,DMA是什么作用?

三、GNSS卫星协议

参看:GNSS卫星协议

NMEA(National Marine Electronics Association) 0183协议简介
NMEA 0183 是美国国家海洋电子协会为海用电子设备制定的标准格式,是一种航海、海运方面有关于数字信号传递的标准,此标准定义了电子信号所需要的传输协议,传输数据时间。这个协议是文本格式的。大致格式如下:
这里写图片描述
NMEA0183消息输出格式 : $–sss,df1,df2,…[CR][LF]
数据标识是表示某种卫星发射。 –标识如下:
这里写图片描述

各主要 GNNS 消息内容识别码的含义如下:

GGA:时间、位置、定位数据
GLL:经纬度,UTC时间和定位状态
GSA:接收机模式和卫星工作数据,包括位置和水平/竖直稀释精度等。稀释精度(Dilution of Precision)是个地理定位
术语.一个接收器可以在同一时间得到许多颗卫星定位信息,但在精密定位上,只要四颗卫星讯号即已足够了
GSV:接收机能接收到的卫星信息,包括卫星 ID,海拔,仰角,方位角,信噪比(SNR)等
RMC:日期,时间,位置,方向,速度数据。是最常用的一个消息
VTG:方位角与对地速度
MSS:信噪比(SNR),信号强度,频率,比特率
ZDA:时间和日期数据
注: GNSS系统还含有一些未在此列出的其它信号,特定软硬件平台只能处理的特定的信号

与地理信息密切相关的消息及其所含主要内容如下,各消息之间的信息字段有出入也有重复,在一轮消息循环里,各消息相同的字段中包含相同的地理数据,可综合多个消息来获取完整的数据。
这里写图片描述

各信息内容识别码下的信号分析如下:

1. GGA(时间、位置、定位数据)

例样数据:
$–GGA,1661229.478,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M,7.3,M, ,0000*18
这里写图片描述

2. GLL(经纬度,UTC时间和定位状态)

例样数据:
$–GLL,3723.2475,N,12158.3416,W,161229.487,A,0*2C
这里写图片描述
这里写图片描述

3. GSA(接收机模式和卫星工作数据,包括位置和水平/竖直稀释精度等)

例样数据:
$–GSA,A,3,07,02,26,27,09,04,15, , , , , ,1.8,1.0,1.5*33
这里写图片描述

4. GSV(接收机能接收到的卫星信息,包括卫星ID,仰角,方位角,信噪比(SNR)等)

例样数据:
$–GSV,2,1,07,07,79,048,42,02,51,062,43,26,36,256,42,27,27,138,42*71

$–GSV,2,2,07,09,23,313,42,04,19,159,41,15,12,041,42*41
这两条语句描述一个完整的卫星信息(这里共描述7颗卫星,每颗卫星的描述部分已用不同颜色标出),每颗卫星用4个段来描述:卫星ID(又称随机伪代码, PRC)、卫星高程(仰角,卫星和接收点连线与水平面的夹角)、方位角(连线在水平面上的投影与正北方向的顺时针旋转夹角)、信噪比。
这里写图片描述
这里写图片描述
这里写图片描述

5. MSS(信噪比(SNR),信号强度,频率,比特率)

例样数据:
$–MSS,55,27,318.0,100,*66
这里写图片描述

6. RMC(日期,时间,位置,方向,速度数据。是最常用的一个消息)

例样数据:
$–RMC,161229.487,A,3723.2475,N,12158.3416,W,0.13,309.62,120598, , ,A*10
这条语句基本上包含了GPS应用程序所需的全部数据:纬度、经度、速度、方向、卫星时间、状态以及磁场变量
这里写图片描述

7. VTG(方位角与对地速度)

例样数据:
$–VTG,309.62,T, ,M,0.13,N,0.2,K,A*6E
这里写图片描述
这里写图片描述

8. TXT(短文本信息传送)

例样数据:
$–TXT,01,01,01,ANTENNA OK*2B
这里写图片描述

四、数据接收

我们知道了GPS使用的是USART2,DMA接收使能
这里写图片描述

一个比较重要的函数,获取当前剩余数据量大小:

uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx)

则:
先配置DMA

GpsRxDMACfg( GpsTransferBuffer,DEF_GPS_RBUFSIZE );   
//GpsTransferBuffer为接收buffer,DEF_GPS_RBUFSIZE 为设置的接收buffer大小(512

根据设置的接收buff大小减去当前剩余数据量,得到当前接收数据大小。

curcount = DEF_GPS_RBUFSIZE - DMA_GetCurrDataCounter( GPS_RxDMA_Ch );   

五、GNNS 消息解析

最重要的是将接收到的GNNS 消息解析,提取出自己想要的数据。

这部分根据GNNS 消息格式来看。
这里写图片描述

举个栗子:
$GPGSV,2,1,07,07,79,048,42,02,51,062,43,26,36,256,42,27,27,138,42*71

$GPGSV,2,2,07,09,23,313,42,04,19,159,41,15,12,041,42*41

循环到接收buffer里 ‘$’位置,然后为信息内容识别码 GPGSV,然后就是数逗号。
最后提取想要的数据。

gps.c 代码如下:

#include "gps.h" 
#include "led.h" 
#include "delay.h"                                 
#include "usart3.h"                                    
#include "stdio.h"   
#include "stdarg.h"  
#include "string.h"  
#include "math.h"
//////////////////////////////////////////////////////////////////////////////////   
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F103开发板
//ATK-S1216F8 GPS模块驱动代码    
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2015/04/11
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved                             
//////////////////////////////////////////////////////////////////////////////////     


const u32 BAUD_id[9]={4800,9600,19200,38400,57600,115200,230400,460800,921600};//模块支持波特率数组
//从buf里面得到第cx个逗号所在的位置
//返回值:0~0XFE,代表逗号所在位置的偏移.
//       0XFF,代表不存在第cx个逗号                             
u8 NMEA_Comma_Pos(u8 *buf,u8 cx)
{               
    u8 *p=buf;
    while(cx)
    {        
        if(*buf=='*'||*buf<' '||*buf>'z')return 0XFF;//遇到'*'或者非法字符,则不存在第cx个逗号
        if(*buf==',')cx--;
        buf++;
    }
    return buf-p;    
}
//m^n函数
//返回值:m^n次方.
u32 NMEA_Pow(u8 m,u8 n)
{
    u32 result=1;    
    while(n--)result*=m;    
    return result;
}
//str转换为数字,以','或者'*'结束
//buf:数字存储区
//dx:小数点位数,返回给调用函数
//返回值:转换后的数值
int NMEA_Str2num(u8 *buf,u8*dx)
{
    u8 *p=buf;
    u32 ires=0,fres=0;
    u8 ilen=0,flen=0,i;
    u8 mask=0;
    int res;
    while(1) //得到整数和小数的长度
    {
        if(*p=='-'){mask|=0X02;p++;}//是负数
        if(*p==','||(*p=='*'))break;//遇到结束了
        if(*p=='.'){mask|=0X01;p++;}//遇到小数点了
        else if(*p>'9'||(*p<'0'))   //有非法字符
        {   
            ilen=0;
            flen=0;
            break;
        }   
        if(mask&0X01)flen++;
        else ilen++;
        p++;
    }
    if(mask&0X02)buf++; //去掉负号
    for(i=0;i<ilen;i++) //得到整数部分数据
    {  
        ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-'0');
    }
    if(flen>5)flen=5;   //最多取5位小数
    *dx=flen;           //小数点位数
    for(i=0;i<flen;i++) //得到小数部分数据
    {  
        fres+=NMEA_Pow(10,flen-1-i)*(buf[ilen+1+i]-'0');
    } 
    res=ires*NMEA_Pow(10,flen)+fres;
    if(mask&0X02)res=-res;         
    return res;
}                                
//分析GPGSV信息
//gpsx:nmea信息结构体
//buf:接收到的GPS数据缓冲区首地址
void NMEA_GPGSV_Analysis(nmea_msg *gpsx,u8 *buf)
{
    u8 *p,*p1,dx;
    u8 len,i,j,slx=0;
    u8 posx;     
    p=buf;
    p1=(u8*)strstr((const char *)p,"$GPGSV");
    len=p1[7]-'0';                              //得到GPGSV的条数
    posx=NMEA_Comma_Pos(p1,3);                  //得到可见卫星总数
    if(posx!=0XFF)gpsx->svnum=NMEA_Str2num(p1+posx,&dx);
    for(i=0;i<len;i++)
    {    
        p1=(u8*)strstr((const char *)p,"$GPGSV");  
        for(j=0;j<4;j++)
        {     
            posx=NMEA_Comma_Pos(p1,4+j*4);
            if(posx!=0XFF)gpsx->slmsg[slx].num=NMEA_Str2num(p1+posx,&dx);   //得到卫星编号
            else break; 
            posx=NMEA_Comma_Pos(p1,5+j*4);
            if(posx!=0XFF)gpsx->slmsg[slx].eledeg=NMEA_Str2num(p1+posx,&dx);//得到卫星仰角 
            else break;
            posx=NMEA_Comma_Pos(p1,6+j*4);
            if(posx!=0XFF)gpsx->slmsg[slx].azideg=NMEA_Str2num(p1+posx,&dx);//得到卫星方位角
            else break; 
            posx=NMEA_Comma_Pos(p1,7+j*4);
            if(posx!=0XFF)gpsx->slmsg[slx].sn=NMEA_Str2num(p1+posx,&dx);    //得到卫星信噪比
            else break;
            slx++;     
        }   
        p=p1+1;//切换到下一个GPGSV信息
    }   
}
//分析BDGSV信息
//gpsx:nmea信息结构体
//buf:接收到的GPS数据缓冲区首地址
void NMEA_BDGSV_Analysis(nmea_msg *gpsx,u8 *buf)
{
    u8 *p,*p1,dx;
    u8 len,i,j,slx=0;
    u8 posx;     
    p=buf;
    p1=(u8*)strstr((const char *)p,"$BDGSV");
    len=p1[7]-'0';                              //得到BDGSV的条数
    posx=NMEA_Comma_Pos(p1,3);                  //得到可见北斗卫星总数
    if(posx!=0XFF)gpsx->beidou_svnum=NMEA_Str2num(p1+posx,&dx);
    for(i=0;i<len;i++)
    {    
        p1=(u8*)strstr((const char *)p,"$BDGSV");  
        for(j=0;j<4;j++)
        {     
            posx=NMEA_Comma_Pos(p1,4+j*4);
            if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_num=NMEA_Str2num(p1+posx,&dx); //得到卫星编号
            else break; 
            posx=NMEA_Comma_Pos(p1,5+j*4);
            if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_eledeg=NMEA_Str2num(p1+posx,&dx);//得到卫星仰角 
            else break;
            posx=NMEA_Comma_Pos(p1,6+j*4);
            if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_azideg=NMEA_Str2num(p1+posx,&dx);//得到卫星方位角
            else break; 
            posx=NMEA_Comma_Pos(p1,7+j*4);
            if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_sn=NMEA_Str2num(p1+posx,&dx);  //得到卫星信噪比
            else break;
            slx++;     
        }   
        p=p1+1;//切换到下一个BDGSV信息
    }   
}
//分析GNGGA信息
//gpsx:nmea信息结构体
//buf:接收到的GPS数据缓冲区首地址
void NMEA_GNGGA_Analysis(nmea_msg *gpsx,u8 *buf)
{
    u8 *p1,dx;           
    u8 posx;    
    p1=(u8*)strstr((const char *)buf,"$GNGGA");
    posx=NMEA_Comma_Pos(p1,6);                              //得到GPS状态
    if(posx!=0XFF)gpsx->gpssta=NMEA_Str2num(p1+posx,&dx);   
    posx=NMEA_Comma_Pos(p1,7);                              //得到用于定位的卫星数
    if(posx!=0XFF)gpsx->posslnum=NMEA_Str2num(p1+posx,&dx); 
    posx=NMEA_Comma_Pos(p1,9);                              //得到海拔高度
    if(posx!=0XFF)gpsx->altitude=NMEA_Str2num(p1+posx,&dx);  
}
//分析GNGSA信息
//gpsx:nmea信息结构体
//buf:接收到的GPS数据缓冲区首地址
void NMEA_GNGSA_Analysis(nmea_msg *gpsx,u8 *buf)
{
    u8 *p1,dx;           
    u8 posx; 
    u8 i;   
    p1=(u8*)strstr((const char *)buf,"$GNGSA");
    posx=NMEA_Comma_Pos(p1,2);                              //得到定位类型
    if(posx!=0XFF)gpsx->fixmode=NMEA_Str2num(p1+posx,&dx);  
    for(i=0;i<12;i++)                                       //得到定位卫星编号
    {
        posx=NMEA_Comma_Pos(p1,3+i);                     
        if(posx!=0XFF)gpsx->possl[i]=NMEA_Str2num(p1+posx,&dx);
        else break; 
    }                 
    posx=NMEA_Comma_Pos(p1,15);                             //得到PDOP位置精度因子
    if(posx!=0XFF)gpsx->pdop=NMEA_Str2num(p1+posx,&dx);  
    posx=NMEA_Comma_Pos(p1,16);                             //得到HDOP位置精度因子
    if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx);  
    posx=NMEA_Comma_Pos(p1,17);                             //得到VDOP位置精度因子
    if(posx!=0XFF)gpsx->vdop=NMEA_Str2num(p1+posx,&dx);  
}
//分析GNRMC信息
//gpsx:nmea信息结构体
//buf:接收到的GPS数据缓冲区首地址
void NMEA_GNRMC_Analysis(nmea_msg *gpsx,u8 *buf)
{
    u8 *p1,dx;           
    u8 posx;     
    u32 temp;      
    float rs;  
    p1=(u8*)strstr((const char *)buf,"$GNRMC");//"$GNRMC",经常有&和GNRMC分开的情况,故只判断GPRMC.
    posx=NMEA_Comma_Pos(p1,1);                              //得到UTC时间
    if(posx!=0XFF)
    {
        temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx);     //得到UTC时间,去掉ms
        gpsx->utc.hour=temp/10000;
        gpsx->utc.min=(temp/100)%100;
        gpsx->utc.sec=temp%100;      
    }   
    posx=NMEA_Comma_Pos(p1,3);                              //得到纬度
    if(posx!=0XFF)
    {
        temp=NMEA_Str2num(p1+posx,&dx);          
        gpsx->latitude=temp/NMEA_Pow(10,dx+2);  //得到°
        rs=temp%NMEA_Pow(10,dx+2);              //得到'        
        gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° 
    }
    posx=NMEA_Comma_Pos(p1,4);                              //南纬还是北纬 
    if(posx!=0XFF)gpsx->nshemi=*(p1+posx);                   
    posx=NMEA_Comma_Pos(p1,5);                              //得到经度
    if(posx!=0XFF)
    {                                                 
        temp=NMEA_Str2num(p1+posx,&dx);          
        gpsx->longitude=temp/NMEA_Pow(10,dx+2); //得到°
        rs=temp%NMEA_Pow(10,dx+2);              //得到'        
        gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° 
    }
    posx=NMEA_Comma_Pos(p1,6);                              //东经还是西经
    if(posx!=0XFF)gpsx->ewhemi=*(p1+posx);       
    posx=NMEA_Comma_Pos(p1,9);                              //得到UTC日期
    if(posx!=0XFF)
    {
        temp=NMEA_Str2num(p1+posx,&dx);                     //得到UTC日期
        gpsx->utc.date=temp/10000;
        gpsx->utc.month=(temp/100)%100;
        gpsx->utc.year=2000+temp%100;        
    } 
}
//分析GNVTG信息
//gpsx:nmea信息结构体
//buf:接收到的GPS数据缓冲区首地址
void NMEA_GNVTG_Analysis(nmea_msg *gpsx,u8 *buf)
{
    u8 *p1,dx;           
    u8 posx;    
    p1=(u8*)strstr((const char *)buf,"$GNVTG");                             
    posx=NMEA_Comma_Pos(p1,7);                              //得到地面速率
    if(posx!=0XFF)
    {
        gpsx->speed=NMEA_Str2num(p1+posx,&dx);
        if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx);             //确保扩大1000倍
    }
}  
//提取NMEA-0183信息
//gpsx:nmea信息结构体
//buf:接收到的GPS数据缓冲区首地址
void GPS_Analysis(nmea_msg *gpsx,u8 *buf)
{
    NMEA_GPGSV_Analysis(gpsx,buf);  //GPGSV解析
    NMEA_BDGSV_Analysis(gpsx,buf);  //BDGSV解析
    NMEA_GNGGA_Analysis(gpsx,buf);  //GNGGA解析   
    NMEA_GNGSA_Analysis(gpsx,buf);  //GPNSA解析
    NMEA_GNRMC_Analysis(gpsx,buf);  //GPNMC解析
    NMEA_GNVTG_Analysis(gpsx,buf);  //GPNTG解析
}
///////////////////////////////////////////UBLOX 配置代码/////////////////////////////////////
////检查CFG配置执行情况
////返回值:0,ACK成功
////       1,接收超时错误
////       2,没有找到同步字符
////       3,接收到NACK应答
u8 SkyTra_Cfg_Ack_Check(void)
{            
    u16 len=0,i;
    u8 rval=0;
    while((USART3_RX_STA&0X8000)==0 && len<100)//等待接收到应答   
    {
        len++;
        delay_ms(5);
    }        
    if(len<100)     //超时错误.
    {
        len=USART3_RX_STA&0X7FFF;   //此次接收到的数据长度 
        for(i=0;i<len;i++)
        {
            if(USART3_RX_BUF[i]==0X83)break;
            else if(USART3_RX_BUF[i]==0X84)
            {
                rval=3;
                break;
            }
        }
        if(i==len)rval=2;                       //没有找到同步字符
    }else rval=1;                               //接收超时错误
    USART3_RX_STA=0;                            //清除接收
    return rval;  
}
//配置SkyTra_GPS/北斗模块波特率
//baud_id:0~8,对应波特率,4800/9600/19200/38400/57600/115200/230400/460800/921600      
//返回值:0,执行成功;其他,执行失败(这里不会返回0了)
u8 SkyTra_Cfg_Prt(u8 baud_id)
{
    SkyTra_baudrate *cfg_prt=(SkyTra_baudrate *)USART3_TX_BUF;
    cfg_prt->sos=0XA1A0;        //引导序列(小端模式)
    cfg_prt->PL=0X0400;         //有效数据长度(小端模式)
    cfg_prt->id=0X05;           //配置波特率的ID 
    cfg_prt->com_port=0X00;         //操作串口1
    cfg_prt->Baud_id=baud_id;       ////波特率对应编号
    cfg_prt->Attributes=1;        //保存到SRAM&FLASH
    cfg_prt->CS=cfg_prt->id^cfg_prt->com_port^cfg_prt->Baud_id^cfg_prt->Attributes;
    cfg_prt->end=0X0A0D;        //发送结束符(小端模式)
    SkyTra_Send_Date((u8*)cfg_prt,sizeof(SkyTra_baudrate));//发送数据给SkyTra   
    delay_ms(200);              //等待发送完成 
    usart3_init(BAUD_id[baud_id]);  //重新初始化串口3  
    return SkyTra_Cfg_Ack_Check();//这里不会反回0,因为UBLOX发回来的应答在串口重新初始化的时候已经被丢弃了.
} 
//配置SkyTra_GPS模块的时钟脉冲宽度
//width:脉冲宽度1~100000(us)
//返回值:0,发送成功;其他,发送失败.
u8 SkyTra_Cfg_Tp(u32 width)
{
    u32 temp=width;
    SkyTra_pps_width *cfg_tp=(SkyTra_pps_width *)USART3_TX_BUF;
    temp=(width>>24)|((width>>8)&0X0000FF00)|((width<<8)&0X00FF0000)|((width<<24)&0XFF000000);//小端模式
    cfg_tp->sos=0XA1A0;         //cfg header(小端模式)
    cfg_tp->PL=0X0700;        //有效数据长度(小端模式)
    cfg_tp->id=0X65 ;               //cfg tp id
    cfg_tp->Sub_ID=0X01;            //数据区长度为20个字节.
    cfg_tp->width=temp;       //脉冲宽度,us
    cfg_tp->Attributes=0X01;  //保存到SRAM&FLASH   
    cfg_tp->CS=cfg_tp->id^cfg_tp->Sub_ID^(cfg_tp->width>>24)^(cfg_tp->width>>16)&0XFF^(cfg_tp->width>>8)&0XFF^cfg_tp->width&0XFF^cfg_tp->Attributes;        //用户延时为0ns
    cfg_tp->end=0X0A0D;       //发送结束符(小端模式)
    SkyTra_Send_Date((u8*)cfg_tp,sizeof(SkyTra_pps_width));//发送数据给NEO-6M  
    return SkyTra_Cfg_Ack_Check();
}
//配置SkyTraF8-BD的更新速率       
//Frep:(取值范围:1,2,4,5,8,10,20,25,40,50)测量时间间隔,单位为Hz,最大不能大于50Hz
//返回值:0,发送成功;其他,发送失败.
u8 SkyTra_Cfg_Rate(u8 Frep)
{
    SkyTra_PosRate *cfg_rate=(SkyTra_PosRate *)USART3_TX_BUF;
    cfg_rate->sos=0XA1A0;       //cfg header(小端模式)
    cfg_rate->PL=0X0300;            //有效数据长度(小端模式)
    cfg_rate->id=0X0E;        //cfg rate id
    cfg_rate->rate=Frep;          //更新速率
    cfg_rate->Attributes=0X01;      //保存到SRAM&FLASH .
    cfg_rate->CS=cfg_rate->id^cfg_rate->rate^cfg_rate->Attributes;//脉冲间隔,us
    cfg_rate->end=0X0A0D;       //发送结束符(小端模式)
    SkyTra_Send_Date((u8*)cfg_rate,sizeof(SkyTra_PosRate));//发送数据给NEO-6M 
    return SkyTra_Cfg_Ack_Check();
}
//发送一批数据给SkyTraF8-BD,这里通过串口3发送
//dbuf:数据缓存首地址
//len:要发送的字节数
void SkyTra_Send_Date(u8* dbuf,u16 len)
{
    u16 j;
    for(j=0;j<len;j++)//循环发送数据
    {
        while((USART3->SR&0X40)==0);//循环发送,直到发送完毕   
        USART3->DR=dbuf[j];  
    }   
}

其中字符串函数,和进制间转换、进制和字符串间转换有点难度。
这个后续专门写一篇文章再做介绍。

六、u-center简单使用

未完待续!!

七、GPS飘移

猜你喜欢

转载自blog.csdn.net/qq_29350001/article/details/82110535