MS-DTU/Anjiehui7_TTS_ST_V2.4_LOCAL/GPS-Driver/EC20-TAU1103/drv_gps.c

563 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
*********************************************************************************************************
* IAR Development Kits
* on the
*
* M451
*
* Filename : uart_dtu.c
* Version : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/
#include "includes.h"
#include "drv_dtu.h"
#include "drv_gps.h"
// GPS开启计时
volatile uint32_t DTU_gpsTime = 0;
// 是否需要检查并重启GPS
uint8_t DTU_needCheckGPS = 0;
// **************** 上传GPS调试信息 ********************
// GPS闪断次数取值为0~599循环计数
uint16_t GPS_BOD_COUNT = 0;
// *****************************************************
// 打开GPS功能
uint32_t DTU_EnableGPS()
{
char cmd[50], buff[50];
uint8_t try_count = 2;
static uint8_t first = 1;
// 禁止重启GPS
DTU_needCheckGPS = 0;
if(!IS_VCC_GPS_ON())
{
VCC_GPS_ON();
delay_ms(2500);
}
// DTU_ExecuteCmd("AT+QGPSDEL=3", "OK", "ERROR", buff, DTU_tmrQPendShort);
// DTU_ExecuteCmd("AT+QGPSXTRA=0", "OK", "ERROR", buff, DTU_tmrQPendShort);
// return FALSE;
#if 0
// 检查QGPSXTRA
if(!DTU_ExecuteCmd("AT+QGPSXTRA?", "+QGPSXTRA: 1", "+QGPSXTRA: 0", buff, DTU_tmrQPendShort))
{
// 如果没有, 则设置并重启
if(DTU_ExecuteCmd("AT+QGPSXTRA=1", "OK", "ERROR", buff, DTU_tmrQPendShort))
{
DTU_PowerOff();
delay_ms(200);
NVIC_SystemReset();
}
}
// 检查QGPSXTRADATA
if(DTU_ExecuteCmd("AT+QGPSXTRADATA?", "+QGPSXTRADATA: ", "ERROR", buff, DTU_tmrQPendShort)
&& strstr(buff, "+QGPSXTRADATA: 0,"))
{
// 先删除内存文件
DTU_ExecuteCmd("AT+QFDEL=\"RAM:xtra2.bin\"", "OK", "ERROR", buff, DTU_tmrQPendShort);
// 下载XTRADATA
if(Sim808_GPRSDial()
&& DTU_ExecuteCmd("AT+QHTTPCFG=\"contextid\",1", "OK", "ERROR", buff, DTU_tmrQPendShort)
&& DTU_ExecuteCmd("AT+QHTTPCFG=\"responseheader\",0", "OK", "ERROR", buff, DTU_tmrQPendShort)
&& DTU_ExecuteCmd("AT+QHTTPURL=40,10", "CONNECT", "ERROR", buff, DTU_tmrQPendShort)
)
{
strcpy(cmd, "http://xtrapath1.izatcloud.net/xtra2.bin");
UART_Transmit(&huart1, (uint8_t *) cmd, strlen(cmd));
if(DTU_ParseResult("OK", "ERROR", buff, DTU_tmrQPendShort)
&& DTU_ExecuteCmd("AT+QHTTPGET=80", "+QHTTPGET: 0,", "ERROR", buff, DTU_tmrQPendSpec)
&& DTU_ExecuteCmd("AT+QHTTPREADFILE=\"RAM:xtra2.bin\",80", "+QHTTPREADFILE: 0", "ERROR", buff, DTU_tmrQPendSpec)
&& DTU_ExecuteCmd("AT+QLTS=2", "+QLTS: ", "ERROR", buff, DTU_tmrQPendShort) // Get UTC time
)
{
// 获取时间
memset(cmd, 0, sizeof(cmd));
strncpy(cmd, strstr(buff, "+QLTS: \"") + 8, 19);
// 注入时间、XTRADATA
sprintf(buff, "AT+QGPSXTRATIME=0,\"%s\",1,1,3500", cmd); // Inject UTC time
strcpy(cmd, buff);
if(DTU_ExecuteCmd(cmd, "OK", "ERROR", buff, DTU_tmrQPendShort)
&& DTU_ExecuteCmd("AT+QGPSXTRADATA=\"RAM:xtra2.bin\"", "OK", "ERROR", buff, DTU_tmrQPendShort)
)
{
printf("\nGPS XTRADATA Injected.\n");
}
}
}
}
#endif
while(try_count--)
{
delay_ms(200);
// 先停止GPS定位
if(DTU_ExecuteCmd("AT+QGPSEND", "OK", "ERROR", buff, DTU_tmrQPendShort))
{
printf("\nGPS disabled.\n");
delay_ms(200);
}
// 查询当前输出端口是否为uartdebug
if(first || !DTU_ExecuteCmd("AT+QGPSCFG=\"outport\"", "+QGPSCFG:", "ERROR", buff, DTU_tmrQPendShort)
|| strstr(buff, "uartdebug") == 0)
{
// 设置当前输出端口为uartdebug
if(!DTU_ExecuteCmd("AT+QGPSCFG=\"outport\",\"uartdebug\"", "OK", "ERROR", buff, DTU_tmrQPendShort))
{
printf("\nSet GPS outport failed.\n");
continue;
}
first = 0;
}
if(DTU_ExecuteCmd("AT+QGPS=1,255,50,0,4", "OK", "ERROR", buff, DTU_tmrQPendShort))
{
printf("\nGPS enabled.\n");
// 允许重启GPS
DTU_needCheckGPS = 1;
return TRUE;
}
}
printf("\nGPS enable failed.\n");
// 允许重启GPS
DTU_needCheckGPS = 1;
return FALSE;
}
// 关闭GPS功能
void DTU_DisableGPS()
{
char buff[50];
if(IS_VCC_GPS_ON())
{
VCC_GPS_OFF();
if(DTU_ExecuteCmd("AT+QGPSEND", "OK", "ERROR", buff, DTU_tmrQPendShort))
printf("\nGPS disabled.\n");
else
printf("\nGPS disable failed.\n");
}
}
// 处理时差函数
void GPS_ProcessTimeLag(date_time_t *sysTime, int8_t timeLag)
{
// 处理时差:正时差
if(timeLag > 0)
{
sysTime->hour += timeLag;
if(sysTime->hour >= 24)
{
sysTime->hour %= 24;
if(sysTime->day < get_month_days(sysTime->year + 2000, sysTime->month))
sysTime->day++;
else
{
sysTime->day = 1;
if(sysTime->month < 12)
sysTime->month++;
else
{
sysTime->month = 1;
sysTime->year++;
}
}
}
}
// 处理时差:负时差
else if(timeLag < 0)
{
// hour是无符号数
if(sysTime->hour >= (-timeLag))
sysTime->hour += timeLag;
else
{
sysTime->hour += (24 + timeLag);
if(sysTime->day > 1)
sysTime->day--;
else
{
if(sysTime->month > 1)
{
sysTime->month--;
sysTime->day = get_month_days(sysTime->year + 2000, sysTime->month);
}
else
{
sysTime->month = 12;
sysTime->day = 31;
sysTime->year--;
}
}
}
}
}
// ASCII重组
void ASCII2Hex(char hchar, char lchar, uint8_t* hex)
{
uint8_t h = 0, l = 0;
if(hchar >= '0' && hchar <= '9')
{
h = hchar - '0';
}
else if(hchar >= 'A' && hchar <= 'F')
{
h = hchar - 'A' + 10;
}
else if(hchar >= 'a' && hchar <= 'f')
{
h = hchar - 'a' + 10;
}
if(lchar >= '0' && lchar <= '9')
{
l = lchar - '0';
}
else if(lchar >= 'A' && lchar <= 'F')
{
l = lchar - 'A' + 10;
}
else if(lchar >= 'a' && lchar <= 'f')
{
l = lchar - 'a' + 10;
}
*hex = (h << 4) | l;
}
uint8_t check_sum(char *message)
{
int16_t i, len = strlen(message);
uint8_t cs0, cs1 = 0;
if(len < 4 || message[0] != '$' || message[len - 3] != '*')
return 0;
for(i = 1; i < len - 3; i++)
{
cs1 ^= message[i];
}
ASCII2Hex(message[len - 2], message[len - 1], &cs0);
if(cs1 == cs0)
return 1;
printf("\nCheck sum error: %s<>%02X", message, cs1);
return 0;
}
uint32_t parse_vtg(char *message, data_dtu_t *sample)
{
char *p = message, *pe = p + strlen(message), *p1 = NULL;
char buff[20];
// $GNVTG,293.56,T,,M,1.13,N,2.10,K,A*28
// 运动角度
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// T=真北参照系
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// 运动角度
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// M=磁北参照系
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// 水平运动速度(节)
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// N=节
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// 水平运动速度(千米)
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
p1 = strstr(p, ",");
if(!p1)
return 0;
memset(buff, 0, sizeof(buff));
strncpy(buff, p, p1 - p);
sample->speed = atof(buff);
return 1;
}
uint32_t parse_gga(char *message, data_dtu_t *sample)
{
char *p = message, *pe = p + strlen(message), *p1 = NULL;
char buff[20];
// $GNGGA,014600.000,3029.3359,N,10357.9168,E,1,4,4.16,200.1,M,-32.0,M,,*6B
if(!check_sum(message))
return 0;
// UTC 时间
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// 纬度
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// N/S
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// 经度
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// E/W
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// GPS状态
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// 正在使用的卫星数
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
p1 = strstr(p, ",");
if(!p1)
return 0;
memset(buff, 0, sizeof(buff));
strncpy(buff, p, p1 - p);
sample->sateCount = atoi(buff);
return 1;
}
uint32_t parse_rmc(char *message, data_dtu_t *sample)
{
char *p = message, *pe = p + strlen(message), *p1 = NULL;
char buff[20];
uint16_t deg;
float fen;
// $GNRMC,014600.000,A,3029.3359,N,10357.9168,E,1.13,293.56,070417,,,A*7C
if(!check_sum(message))
return 0;
// UTC时间
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
p1 = strstr(p, ",");
if(!p1 || p1 < p + 6)
return 0;
// 2位小时
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
p += 2;
sample->sysTime.hour = atoi(buff);
// 2位分钟
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
p += 2;
sample->sysTime.minute = atoi(buff);
// 2位秒
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
p += 2;
sample->sysTime.second = atoi(buff);
if(sample->sysTime.hour > 23 || sample->sysTime.minute > 59 || sample->sysTime.second > 59)
return 0;
// 定位状态
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
sample->posState = (*p == 'A');
// 纬度
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
p1 = strstr(p, ",");
if(!p1 || p1 < p + 10)
return 0;
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
deg = atoi(buff);
p += 2;
strncpy(buff, p, 9);
fen = atof(buff);
if(deg > 90 || fen >= 60 || (deg == 90 && fen > 0))
return 0;
sample->latitude = (deg + fen / 60) * 1000000ul;
// N/S
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
if(*p == 'S')
sample->latitude = -sample->latitude;
// 经度
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
p1 = strstr(p, ",");
if(!p1 || p1 < p + 11)
return 0;
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 3);
deg = atoi(buff);
p += 3;
strncpy(buff, p, 9);
fen = atof(buff);
if(deg > 180 || fen >= 60 || (deg == 180 && fen > 0))
return 0;
sample->longitude = (deg + fen / 60) * 1000000ul;
// E/W
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
if(*p == 'W')
sample->longitude = -sample->longitude;
// 速度(节)
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
p1 = strstr(p, ",");
if(!p1)
return 0;
memset(buff, 0, sizeof(buff));
strncpy(buff, p, p1 - p);
sample->speed = atof(buff) * 1.852;
// 方位角
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// UTC日期
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
p1 = strstr(p, ",");
if(!p1 || p1 < p + 6)
return 0;
// 2位日期
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
p += 2;
sample->sysTime.day = atoi(buff);
// 2位月份
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
p += 2;
sample->sysTime.month = atoi(buff);
// 2位年份
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
p += 2;
sample->sysTime.year = atoi(buff);
if(sample->sysTime.month < 1 || sample->sysTime.month > 12 || sample->sysTime.day < 1 || sample->sysTime.day > 31)
return 0;
// 处理时差
GPS_ProcessTimeLag(&sample->sysTime, dcBuff.configData.timeLag);
return 1;
}
uint8_t parse_frame(uint8_t *bufIdx, char *message, data_dtu_t *sample)
{
uint8_t ret = 0;
S_RTC_TIME_DATA_T sRTC;
if(strncmp(message, "$GPGGA", 6) == 0 || strncmp(message, "$GNGGA", 6) == 0)
{
// printf("\n%s\n", message);
*bufIdx = 1 - *bufIdx;
}
else if(strncmp(message, "$GPRMC", 6) == 0 || strncmp(message, "$GNRMC", 6) == 0)
{
printf("\n%s\n", message);
// 获取当前时间
RTC_GetDateAndTime(&sRTC);
// 记录GPS上次数据时间
DTU_gpsTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
parse_gga(DTU_gpsData[1 - *bufIdx], sample);
ret = parse_rmc(message, sample);
if(!ret)
sample->posState = 0;
}
return ret;
}
void DTU_CheckGPS()
{
uint32_t time;
S_RTC_TIME_DATA_T sRTC;
if(IS_VCC_GPS_ON())
{
// 获取当前时间
RTC_GetDateAndTime(&sRTC);
// 计算自上次gps定位以来的时间
time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
if(!Wakeup_Sleeping && time > DTU_gpsTime + 30 && (GPS_Waiting || dcBuff.configDisplay.op_SEND_GPS_DATA))
{
// 如果是第一次,或者曾经有输出了,则闪断计数
if(GPS_BOD_COUNT == 599)
GPS_BOD_COUNT = 0;
else
GPS_BOD_COUNT++;
printf("\nGPS_BOD_COUNT: %d\n", GPS_BOD_COUNT);
printf("\n*** Restart GPS module ***\n");
DTU_EnableGPS();
DTU_gpsTime = time;
}
}
}