563 lines
12 KiB
C
563 lines
12 KiB
C
/*
|
||
*********************************************************************************************************
|
||
* 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 + 11)
|
||
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 + 12)
|
||
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)
|
||
{
|
||
// printf("\n%s\n", message);
|
||
*bufIdx = 1 - *bufIdx;
|
||
}
|
||
else if(strncmp(message, "$GPRMC", 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(time > DTU_gpsTime + 30)
|
||
{
|
||
// 如果是第一次,或者曾经有输出了,则闪断计数
|
||
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;
|
||
}
|
||
}
|
||
}
|