工作中使用ublox模块获取时间,由于对时间卡的比较严格,出现了gps模块跳秒的情况,故作一番详细的研究;
过程中有三个时间GPSTime、BDTime、UTCTime,这三个时间的关系大家可以去百度,我就不详细的介绍了;主要我们经常使用的是UTC时间,UTC时间+时区时间就是localTime,在实用的过程中发现一上电过一会时间会晚1s或者2秒的情况,之前一直没找到原因,因为这个问题也费了不少周折,起初就没有王GPS模块上去考虑,最后实在是没有别的方向了,只能怀疑模块给的时间就有问题;通过查看手册和技术支持沟通,最终确定模块在冷启动的时候会发生跳秒的情况,也就是时间会变,在使用UTC时间时有个跳秒的有效判断位,但是由于我们一上电就要获取时间值,故不能等待那么长时间,通过沟通测试,终于有了方案:使用GPSTime和BDTime这两个时间不会跳变,GPSTime-闰秒时间就是UTC时间,北斗也同理。
GPSTime和BDTime能读到一个星期数和这周的一个描述,然后通过儒略日方法计算就能换算为当地的年月日时分秒。
1.儒略日换算代码如下:
typedef struct
{
u16 GpsWeeks;
sl32 GpsMs;
sl32 GpsSecned;
u8 GpsLeaps;
}T_GpsTimeDate;
T_GpsTimeDate gUbloxGpsTime;
这段代码是大家可以共用的,获取的星期数和秒数来转化年月日时分秒
/************************************************************************************/
typedef struct
{
time_t time;
double sec;
}gtime_t;
double gpst0[] = {1980, 1, 6, 0, 0, 0};
gtime_t epoch2time(const double * ep)
{
const int doy[]={1,32,60,91,121,152,182,213,244,274,305,335};
gtime_t time={0};
int days, sec, year=(int)ep[0],mon=(int)ep[1],day=(int)ep[2];
if (year < 1970 || 2099 < year || mon < 1 || 12 < mon)
return time;
/*leap year if year % 4 == 0 in 1901-2099*/
days = (year - 1970) * 365 + (year - 1969)/4 + doy[mon-1] + day-2+(year%4==0&&mon>=3?1:0);
sec = (int) floor(ep[5]);
time.time = (time_t)days*86400+(int)ep[3]*3600+(int)ep[4]*60+sec;
time.sec = ep[5]-sec;
return time;
}
gtime_t gpst2time(int week, double sec)
{
gtime_t t=epoch2time(gpst0);
if (sec < -1E9||1E9 < sec)
sec = 0.0;
t.time+= 86400*7*week+(int)sec;
t.sec=sec-(int)sec;
return t;
}
/*************************************************************************************/
s32 gps_NAV_TimeGPS(s32 gps_gmt_offset,u32 leap_second)
{
char data[] = {0xB5, 0x62, 0x01, 0x20, 0x00, 0x00, 0x21, 0x64};
char dataRsp[BSP_DATARSP_BUF_LEN]={0};
struct tm result;
struct tm mytime;
struct tm *pmytime;
time_t t_tick;
s32 gpsOffset;
s32 status;
gtime_t GPSTime;
gtime_t UTCTime;
struct tm * gpstimeinfo;
if((gps_gmt_offset > 720)||(gps_gmt_offset<-720))
{
printf("Input par is error! gps_gmt_offset = %d",gps_gmt_offset);
return -1;
}
gpsOffset = gps_gmt_offset;
memset(dataRsp,0,BSP_DATARSP_BUF_LEN);
status = gpsExecCommand_UBlox(data, 8, dataRsp, 20+6);
if(status==OK)
{
//解析时间,加时区
char *pchar = &dataRsp[6];//数据区
//printf("pchar[11] = %d\n", pchar[11]);
if((pchar[11]&0x03) == 0x03)//GPSTime valid
{
gUbloxGpsTime.GpsMs = pchar[3]*0x1000000 + pchar[2]*0x10000 + pchar[1]*0x100 + pchar[0];
gUbloxGpsTime.GpsWeeks = pchar[9]*0x100 + pchar[8]; //小端模式
gUbloxGpsTime.GpsLeaps = pchar[11];
gUbloxGpsTime.GpsSecned = gUbloxGpsTime.GpsMs / 1000 - leap_second;
GPSTime = gpst2time(gUbloxGpsTime.GpsWeeks,gUbloxGpsTime.GpsSecned);
gpstimeinfo = localtime(&GPSTime.time);
}
return status;
}
s32 bd_NAV_TimeBD(s32 gps_gmt_offset,u32 leap_second)
{
char data[] = {0xB5, 0x62, 0x01, 0x24, 0x00, 0x00, 0x21, 0x64};
char dataRsp[BSP_DATARSP_BUF_LEN]={0};
struct tm result;
struct tm mytime;
struct tm *pmytime;
time_t t_tick;
s32 gpsOffset;
s32 status;
gtime_t GPSTime;
gtime_t UTCTime;
struct tm * gpstimeinfo;
if((gps_gmt_offset > 720)||(gps_gmt_offset<-720))
{
printf("Input par is error! gps_gmt_offset = %d",gps_gmt_offset);
return -1;
}
gpsOffset = gps_gmt_offset;
memset(dataRsp,0,BSP_DATARSP_BUF_LEN);
status = gpsExecCommand_UBlox(data, 8, dataRsp, 20+6);
if(status==OK)
{
//解析时间,加时区
char *pchar = &dataRsp[6];//数据区
//printf("pchar[11] = %d\n", pchar[11]);
if((pchar[15]&0x03) == 0x03)//GPSTime valid
{
gUbloxGpsTime.GpsMs = pchar[3]*0x1000000 + pchar[2]*0x10000 + pchar[1]*0x100 + pchar[0];
gUbloxGpsTime.GpsWeeks = pchar[13]*0x100 + pchar[12] + 1356; //小端模式 1356是和UTC差的星期数
gUbloxGpsTime.GpsLeaps = pchar[14];
gUbloxGpsTime.GpsSecned = gUbloxGpsTime.GpsMs / 1000 - leap_second;
GPSTime = gpst2time(gUbloxGpsTime.GpsWeeks,gUbloxGpsTime.GpsSecned);
gpstimeinfo = localtime(&GPSTime.time);
}
return status;
}
阅读(7742) | 评论(0) | 转发(0) |