/* ********************************************************************************************************* * 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; } } }