#include "gps.h"
#include "delay.h"
#include "usart3.h"
#include "stdio.h"
#include "stdarg.h"
#include "string.h"
#include "math.h"
//==================================================================
//函数功能: GPS校验和计算
//输入参数: buf:数据缓存区首地址
// len:数据长度
// cka,ckb:两个校验结果
//返回值 : 无
//==================================================================
void GPS_CheckSum(u8 *buf, u16 len, u8* cka,u8*ckb)
{
u16 i;
*cka = 0;
*ckb = 0;
for(i=0;i<len;i++){
*cka = *cka + buf[i];
*ckb = *ckb + *cka;
}
}
//==================================================================
//函数功能: 通过串口给GPS模块发送数据
//输入参数: dbuf:数据内容
// len:数据长度
//返回值 : 0,发送成功;其他,发送失败.
//==================================================================
void GPS_Send_Date(u8* dbuf,u16 len){
u16 i;
for(i=0;i<len;i++){//循环发送数据
while(USART_GetFlagStatus(USART3,USART_FLAG_TC) == RESET);//直到上一个数据发送完毕之后再发送下一个
USART_SendData(USART3,dbuf[i]);
}
}
//==================================================================
//函数功能: 检查CFG配置执行情况
//输入参数: 无
//返回值 : 0,ACK成功
// 1,接收超时错误
// 2,没有找到同步字符
// 3,接收到NACK应答
//==================================================================
u8 GPS_Cfg_Ack_Check(void){
u16 i,len = 0;
u8 rval=0;
while( (USART3_RX_STA & 0x8000) == 0 && len < 100){//最多等待500ms来接收GPS模块应答
len++;
delay_ms(5);
}
if(len < 100){//没有接收超时
len = USART3_RX_STA & 0x7fff;//得到本次接收数据的长度
for(i=0;i<len;i++)//查找同步字符 0XB5
if(USART3_RX_BUF[i] == 0xb5)
break;
if(i == len)
rval = 2;//没有找到同步字符
else if(USART3_RX_BUF[i + 3] == 0x00)
rval = 3;//接收到NACK应答
else
rval = 0;//接收到ACK应答
}
else
rval = 1;//接收超时错误
USART3_RX_STA = 0;//清除接收
return rval;
}
//==================================================================
//函数功能: 配置GPS的更新速率
//输入参数: measrate:测量时间间隔,单位为ms,最少不能小于200ms(5Hz)
// reftime:参考时间,0=UTC Time;1=GPS Time(一般设置为1)
//返回值 : 0,发送成功;其他,发送失败.
//==================================================================
u8 GPS_Cfg_Rate(u16 measrate,u8 reftime){
_gps_cfg_rate *cfg_rate = (_gps_cfg_rate *)USART3_TX_BUF;
if(measrate < 200)//测量时间间隔最少不能小于200ms(5Hz)
return 1;
cfg_rate->header = 0x62b5; //设置header
cfg_rate->id = 0x0806; //设置id
cfg_rate->dlength = 6; //数据区长度为6个字节
cfg_rate->measrate = measrate; //脉冲间隔,us
cfg_rate->navrate = 1; //导航速率(周期),固定为1
cfg_rate->timeref = reftime; //参考时间为GPS时间
GPS_CheckSum( (u8*)(&cfg_rate->id), sizeof(_gps_cfg_rate) - 4, &cfg_rate->cka, &cfg_rate->ckb );//校验和
GPS_Send_Date( (u8*)cfg_rate,sizeof(_gps_cfg_rate) );//发送数据给GPS模块
return GPS_Cfg_Ack_Check();
}
//==================================================================
//函数功能: 重新配置GPS模块的波特率
//输入参数: baudrate:波特率,4800/9600/19200/38400/57600/115200/230400)
//返回值 : 0,执行成功;其他,执行失败(这里不会返回0了)
//==================================================================
u8 GPS_Cfg_Baudrate(u32 baudrate){
_gps_cfg_baudrate *cfg_baudrate = (_gps_cfg_baudrate *)USART3_TX_BUF;
cfg_baudrate->header = 0x62b5; //设置header
cfg_baudrate->id = 0x0006; //设置id
cfg_baudrate->dlength = 20; //数据区长度为6个字节
cfg_baudrate->portid = 1; //操作串口1
cfg_baudrate->reserved = 0; //保留字节,设置为0
cfg_baudrate->txready = 0; //TX Ready设置为0
cfg_baudrate->mode = 0x08d0; //8位,1个停止位,无校验位
cfg_baudrate->baudrate = baudrate; //波特率设置
cfg_baudrate->inprotomask = 0x0007; //0+1+2,看不懂啊
cfg_baudrate->outprotomask = 0x0007; //0+1+2,看不懂啊
cfg_baudrate->reserved4 = 0; //保留字节,设置为0
cfg_baudrate->reserved5 = 0; //保留字节,设置为0
GPS_CheckSum( (u8*)(&cfg_baudrate->id), sizeof(_gps_cfg_baudrate) - 4, &cfg_baudrate->cka, &cfg_baudrate->ckb );//校验和
GPS_Send_Date( (u8*)cfg_baudrate, sizeof(_gps_cfg_baudrate) );//发送数据给GPS模块
delay_ms(200);//等待发送完成
usart3_init(baudrate);//重新初始化串口3
return GPS_Cfg_Ack_Check();//这里不会反回0,因为UBLOX发回来的应答在串口重新初始化的时候已经被丢弃了
}
//==================================================================
//函数功能: 配置GPS模块的时钟脉冲输出
//输入参数: interval:脉冲间隔(us)
// length:脉冲宽度(us)
// status:脉冲配置:1,高电平有效;0,关闭;-1,低电平有效.
//返回值 : 0,发送成功;其他,发送失败.
//==================================================================
u8 GPS_Cfg_Tp(u32 interval,u32 length,signed char status){
_gps_cfg_tp *cfg_tp = (_gps_cfg_tp *)USART3_TX_BUF;
cfg_tp->header = 0x62b5; //设置header
cfg_tp->id = 0x0706; //设置id
cfg_tp->dlength = 20; //数据区长度为6个字节
cfg_tp->interval = interval; //脉冲间隔,us
cfg_tp->length = length; //脉冲宽度,us
cfg_tp->status = status; //时钟脉冲配置
cfg_tp->timeref = 0; //参考UTC时间
cfg_tp->flags = 0; //flags为0
cfg_tp->reserved = 0; //保留位为0
cfg_tp->antdelay = 820; //天线延时为820ns
cfg_tp->rfdelay = 0; //RF延时为0ns
cfg_tp->userdelay = 0; //用户延时为0ns
GPS_CheckSum( (u8*)(&cfg_tp->id), sizeof(_gps_cfg_tp) - 4, &cfg_tp->cka, &cfg_tp->ckb );//校验和
GPS_Send_Date( (u8*)cfg_tp, sizeof(_gps_cfg_tp) );//发送数据给GPS模块
return GPS_Cfg_Ack_Check();
}
//==================================================================
//函数功能: 从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函数
//输入参数: u8 m,u8 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:nm