MS-DTU/MS-DTU-V1/User/drv_gps.c

563 lines
12 KiB
C
Raw Normal View History

2025-04-03 14:18:58 +08:00
/*
*********************************************************************************************************
* 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<50><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
volatile uint32_t DTU_gpsTime = 0;
// <20>Ƿ<EFBFBD><C7B7><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><E9B2A2><EFBFBD><EFBFBD>GPS
uint8_t DTU_needCheckGPS = 0;
// **************** <20>ϴ<EFBFBD>GPS<50><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ ********************
// GPS<50><53><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD>ȡֵΪ0~599ѭ<39><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
uint16_t GPS_BOD_COUNT = 0;
// *****************************************************
// <20><><EFBFBD><EFBFBD>GPS<50><53><EFBFBD><EFBFBD>
uint32_t DTU_EnableGPS()
{
char cmd[50], buff[50];
uint8_t try_count = 2;
static uint8_t first = 1;
// <20><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD>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
// <20><><EFBFBD><EFBFBD>QGPSXTRA
if(!DTU_ExecuteCmd("AT+QGPSXTRA?", "+QGPSXTRA: 1", "+QGPSXTRA: 0", buff, DTU_tmrQPendShort))
{
// <20><><EFBFBD><EFBFBD>û<EFBFBD>У<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD>
if(DTU_ExecuteCmd("AT+QGPSXTRA=1", "OK", "ERROR", buff, DTU_tmrQPendShort))
{
DTU_PowerOff();
delay_ms(200);
NVIC_SystemReset();
}
}
// <20><><EFBFBD><EFBFBD>QGPSXTRADATA
if(DTU_ExecuteCmd("AT+QGPSXTRADATA?", "+QGPSXTRADATA: ", "ERROR", buff, DTU_tmrQPendShort)
&& strstr(buff, "+QGPSXTRADATA: 0,"))
{
// <20><>ɾ<EFBFBD><C9BE><EFBFBD>ڴ<EFBFBD><DAB4>ļ<EFBFBD>
DTU_ExecuteCmd("AT+QFDEL=\"RAM:xtra2.bin\"", "OK", "ERROR", buff, DTU_tmrQPendShort);
// <20><><EFBFBD><EFBFBD>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
)
{
// <20><>ȡʱ<C8A1><CAB1>
memset(cmd, 0, sizeof(cmd));
strncpy(cmd, strstr(buff, "+QLTS: \"") + 8, 19);
// ע<><D7A2>ʱ<EFBFBD>䡢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);
// <20><>ֹͣGPS<50><53>λ
if(DTU_ExecuteCmd("AT+QGPSEND", "OK", "ERROR", buff, DTU_tmrQPendShort))
{
printf("\nGPS disabled.\n");
delay_ms(200);
}
// <20><>ѯ<EFBFBD><D1AF>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD><CBBF>Ƿ<EFBFBD>Ϊuartdebug
if(first || !DTU_ExecuteCmd("AT+QGPSCFG=\"outport\"", "+QGPSCFG:", "ERROR", buff, DTU_tmrQPendShort)
|| strstr(buff, "uartdebug") == 0)
{
// <20><><EFBFBD>õ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD>Ϊ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");
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>GPS
DTU_needCheckGPS = 1;
return TRUE;
}
}
printf("\nGPS enable failed.\n");
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>GPS
DTU_needCheckGPS = 1;
return FALSE;
}
// <20>ر<EFBFBD>GPS<50><53><EFBFBD><EFBFBD>
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");
}
}
// <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EEBAAF>
void GPS_ProcessTimeLag(date_time_t *sysTime, int8_t timeLag)
{
// <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EEA3BA>ʱ<EFBFBD><CAB1>
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++;
}
}
}
}
// <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EEA3BA>ʱ<EFBFBD><CAB1>
else if(timeLag < 0)
{
// hour<75><72><EFBFBD>޷<EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD>
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<49><49><EFBFBD><EFBFBD>
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
// <20>˶<EFBFBD><CBB6>Ƕ<EFBFBD>
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// T=<3D><EFBFBD><E6B1B1><EFBFBD><EFBFBD>ϵ
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// <20>˶<EFBFBD><CBB6>Ƕ<EFBFBD>
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// M=<3D>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD>ϵ
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// ˮƽ<CBAE>˶<EFBFBD><CBB6>ٶȣ<D9B6><C8A3>ڣ<EFBFBD>
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// N=<3D><>
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// ˮƽ<CBAE>˶<EFBFBD><CBB6>ٶȣ<D9B6>ǧ<EFBFBD>ף<EFBFBD>
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 ʱ<><CAB1>
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// γ<><CEB3>
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// N/S
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// <20><><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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ʱ<43><CAB1>
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λ<32><CEBB><EFBFBD><EFBFBD>
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
p += 2;
sample->sysTime.minute = atoi(buff);
// 2λ<32><CEBB>
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;
// <20><>λ״̬
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
sample->posState = (*p == 'A');
// γ<><CEB3>
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;
// <20><><EFBFBD><EFBFBD>
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;
// <20>ٶȣ<D9B6><C8A3>ڣ<EFBFBD>
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;
// <20><>λ<EFBFBD><CEBB>
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
// UTC<54><43><EFBFBD><EFBFBD>
p = strstr(p, ",");
if(!p || ++p >= pe)
return 0;
p1 = strstr(p, ",");
if(!p1 || p1 < p + 6)
return 0;
// 2λ<32><CEBB><EFBFBD><EFBFBD>
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
p += 2;
sample->sysTime.day = atoi(buff);
// 2λ<32>·<EFBFBD>
memset(buff, 0, sizeof(buff));
strncpy(buff, p, 2);
p += 2;
sample->sysTime.month = atoi(buff);
// 2λ<32><CEBB><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
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);
// <20><>ȡ<EFBFBD><C8A1>ǰʱ<C7B0><CAB1>
RTC_GetDateAndTime(&sRTC);
// <20><>¼GPS<50>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
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())
{
// <20><>ȡ<EFBFBD><C8A1>ǰʱ<C7B0><CAB1>
RTC_GetDateAndTime(&sRTC);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>gps<70><73>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
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))
{
// <20><><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD>һ<EFBFBD>Σ<EFBFBD><CEA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD>
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;
}
}
}