gps.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. * gps.c
  3. *
  4. * Created on: Nov 15, 2019
  5. * Author: Bulanov Konstantin
  6. *
  7. * Contact information
  8. * -------------------
  9. *
  10. * e-mail : leech001@gmail.com
  11. */
  12. /*
  13. * |---------------------------------------------------------------------------------
  14. * | Copyright (C) Bulanov Konstantin,2019
  15. * |
  16. * | This program is free software: you can redistribute it and/or modify
  17. * | it under the terms of the GNU General Public License as published by
  18. * | the Free Software Foundation, either version 3 of the License, or
  19. * | any later version.
  20. * |
  21. * | This program is distributed in the hope that it will be useful,
  22. * | but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * | GNU General Public License for more details.
  25. * |
  26. * | You should have received a copy of the GNU General Public License
  27. * | along with this program. If not, see <http://www.gnu.org/licenses/>.
  28. * |---------------------------------------------------------------------------------
  29. */
  30. #include <stdio.h>
  31. #include <string.h>
  32. //#include <usart.h>
  33. #include "gps.h"
  34. #include "../admisc/ad0x0_timman.h"
  35. #include "stm32f1xx_hal_uart.h"
  36. #include <cstdlib>
  37. #if (GPS_DEBUG == 1)
  38. #include <usbd_cdc_if.h>
  39. #endif
  40. uint8_t rx_data = 0;
  41. uint8_t rx_buffer[GPSBUFSIZE];
  42. uint8_t rx_index = 0;
  43. UART_HandleTypeDef *p_huart;
  44. uint32_t last_recieve_tick=0;
  45. uint32_t last_HAL_res=0;
  46. HAL_UART_StateTypeDef last_UART_state;
  47. uint8_t gps_enable=0;
  48. uint8_t isinint=0;
  49. static GPS_t GPS;
  50. static gps_data_t gps_data;//для рф24
  51. void (*gps_data_ready_func)(gps_data_t*);
  52. static void update_gps_data(void);
  53. uint8_t gps_wakeup(void);
  54. static void gps_err(void){
  55. __ASM("nop");
  56. }
  57. #if (GPS_DEBUG == 1)
  58. void GPS_print(char *data){
  59. char buf[GPSBUFSIZE] = {0,};
  60. sprintf(buf, "%s\n", data);
  61. CDC_Transmit_FS((unsigned char *) buf, (uint16_t) strlen(buf));
  62. }
  63. #endif
  64. static uint32_t get_period_ms(uint32_t _tick_start){
  65. uint32_t t=(HAL_GetTick()<_tick_start)
  66. ?((uint64_t)HAL_GetTick()+UINT32_MAX-_tick_start)
  67. :(HAL_GetTick()-_tick_start);
  68. return t;
  69. }
  70. void GPS_Init(UART_HandleTypeDef *_huart,void (*p_data_ready_func)(gps_data_t*))
  71. {
  72. p_huart=_huart;
  73. gps_data_ready_func=p_data_ready_func;
  74. ad0x0_timman_remove(gps_wakeup);
  75. ad0x0_timman_add(100,gps_wakeup);
  76. //HAL_UART_Receive_IT(p_huart, &rx_data, 1);// перенес в старт
  77. }
  78. void GPS_UART_CallBack(void){
  79. if(isinint){
  80. ad0x0_err();
  81. return;
  82. }
  83. isinint=true;
  84. if (rx_data != '\n' && rx_index < sizeof(rx_buffer)) {
  85. rx_buffer[rx_index++] = rx_data;
  86. } else {
  87. #if (GPS_DEBUG == 1)
  88. GPS_print((char*)rx_buffer);
  89. #endif
  90. if(GPS_validate((char*) rx_buffer)){
  91. // GPS_parse((char*) rx_buffer);
  92. GPS_parse_ad0x0((char*) rx_buffer);
  93. }
  94. rx_index = 0;
  95. memset(rx_buffer, 0, sizeof(rx_buffer));
  96. }
  97. //last_HAL_res=HAL_UART_Receive_IT(p_huart, &rx_data, 1);
  98. last_HAL_res=HAL_UART_GetError(p_huart);
  99. last_UART_state=HAL_UART_GetState(p_huart);
  100. if(HAL_OK==last_HAL_res){
  101. if(HAL_UART_STATE_READY!=last_UART_state){
  102. __ASM("nop");
  103. }else{
  104. last_HAL_res=HAL_UART_Receive_IT(p_huart, &rx_data, 1);
  105. }
  106. }
  107. last_recieve_tick=HAL_GetTick();
  108. isinint=false;
  109. }
  110. void GPS_AbortReceiveCpltCallback(void){
  111. gps_start();
  112. }
  113. uint8_t gps_retransmit(void){
  114. last_UART_state=HAL_UART_GetState(p_huart);
  115. if(last_UART_state==HAL_UART_STATE_READY){
  116. last_HAL_res=HAL_UART_Receive_IT(p_huart, &rx_data, 1);
  117. }else{
  118. if(last_UART_state==HAL_UART_STATE_RESET){
  119. gps_enable=false;
  120. last_UART_state=HAL_UART_GetState(p_huart);
  121. last_HAL_res=HAL_UART_AbortReceive_IT(p_huart);
  122. return 0;
  123. // gps_enable=true;
  124. }
  125. if(last_UART_state & HAL_UART_ERROR_ORE){
  126. __HAL_UART_CLEAR_OREFLAG(p_huart);
  127. uint8_t tmpdr=p_huart->Instance->DR;
  128. last_UART_state=HAL_UART_GetState(p_huart);
  129. }
  130. if(last_UART_state & HAL_UART_ERROR_FE){
  131. __HAL_UART_CLEAR_FEFLAG(p_huart);
  132. last_UART_state=HAL_UART_GetState(p_huart);
  133. gps_enable=false;
  134. last_UART_state=HAL_UART_GetState(p_huart);
  135. last_HAL_res=HAL_UART_AbortReceive_IT(p_huart);
  136. }
  137. if(last_UART_state & HAL_UART_ERROR_NE){
  138. __HAL_UART_CLEAR_NEFLAG(p_huart);
  139. last_UART_state=HAL_UART_GetState(p_huart);
  140. }
  141. last_UART_state=HAL_UART_GetState(p_huart);
  142. if(last_UART_state==HAL_UART_STATE_READY){
  143. last_HAL_res=HAL_UART_Receive_IT(p_huart, &rx_data, 1);
  144. }
  145. }
  146. //if(HAL_OK!=last_HAL_res){ gps_err(); }
  147. // last_recieve_tick=HAL_GetTick();
  148. // ad0x0_timman_remove(gps_retransmit);
  149. // ad0x0_timman_add(10,gps_retransmit);
  150. return 1;
  151. }
  152. void gps_start(void){
  153. gps_enable=true;
  154. gps_retransmit();
  155. }
  156. void GPS_UART_ErrorCallback(void){
  157. last_HAL_res=HAL_UART_GetError(p_huart);
  158. last_UART_state=HAL_UART_GetState(p_huart);
  159. if(last_UART_state & HAL_UART_ERROR_ORE){
  160. __HAL_UART_CLEAR_OREFLAG(p_huart);
  161. }
  162. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  163. last_UART_state=HAL_UART_GetState(p_huart);
  164. if(HAL_UART_STATE_READY!=last_UART_state){
  165. __ASM("nop");
  166. }else{
  167. last_HAL_res=HAL_UART_Receive_IT(p_huart, &rx_data, 1);
  168. }
  169. /* switch(last_HAL_res){
  170. // case HAL_UART_ERROR_NONE: // – без ошибок;
  171. case HAL_UART_ERROR_PE: // – ошибка целостности данных;
  172. ad0x0_err();
  173. break;
  174. case HAL_UART_ERROR_NE: // – выделен шум;
  175. ad0x0_err();
  176. break;
  177. case HAL_UART_ERROR_FE: // – ошибка фрагментации;
  178. ad0x0_err();
  179. break;
  180. case HAL_UART_ERROR_ORE: // – ошибка переполнения;
  181. __HAL_UART_CLEAR_OREFLAG(p_huart);
  182. last_HAL_res=HAL_UART_Receive_IT(p_huart, &rx_data, 1);
  183. break;
  184. case HAL_UART_ERROR_DMA: // – ошибка DMA.
  185. ad0x0_err();
  186. break;
  187. // ad0x0_timman_remove(gps_retransmit);
  188. // ad0x0_timman_add(100,gps_retransmit);
  189. default:
  190. ad0x0_err();
  191. last_HAL_res=HAL_UART_Receive_IT(p_huart, &rx_data, 1);
  192. if(HAL_OK!=last_HAL_res){
  193. gps_err();
  194. }
  195. }*/
  196. }
  197. uint8_t gps_wakeup(void){
  198. uint32_t delta=get_period_ms(last_recieve_tick);
  199. if(delta>1000){
  200. if(gps_enable){
  201. // HAL_UART_DeInit(p_huart);
  202. // HAL_UART_Init(p_huart);
  203. last_HAL_res=HAL_UART_AbortReceive_IT(p_huart);
  204. gps_retransmit();
  205. last_recieve_tick=HAL_GetTick();
  206. }
  207. }
  208. return 0;
  209. }
  210. int GPS_validate(char *nmeastr){
  211. char check[3];
  212. char checkcalcstr[3];
  213. int i;
  214. int calculated_check;
  215. i=0;
  216. calculated_check=0;
  217. // check to ensure that the string starts with a $
  218. if(nmeastr[i] == '$')
  219. i++;
  220. else
  221. return 0;
  222. //No NULL reached, 75 char largest possible NMEA message, no '*' reached
  223. while((nmeastr[i] != 0) && (nmeastr[i] != '*') && (i < 75)){
  224. calculated_check ^= nmeastr[i];// calculate the checksum
  225. i++;
  226. }
  227. if(i >= 75){
  228. return 0;// the string was too long so return an error
  229. }
  230. if (nmeastr[i] == '*'){
  231. check[0] = nmeastr[i+1]; //put hex chars in check string
  232. check[1] = nmeastr[i+2];
  233. check[2] = 0;
  234. }
  235. else
  236. return 0;// no checksum separator found there for invalid
  237. sprintf(checkcalcstr,"%02X",calculated_check);
  238. return((checkcalcstr[0] == check[0])
  239. && (checkcalcstr[1] == check[1])) ? 1 : 0 ;
  240. }
  241. void setval(char _pt,void *p,char *str_p){
  242. /*ну да, б, заморочился с парсером, ваще не хотел его писАть, но решил задрочить себе мозги*/
  243. int d=0xFFFF;
  244. float f;
  245. if(!str_p){
  246. ad0x0_err();
  247. return;
  248. }
  249. switch(_pt){
  250. case 's':
  251. if(p)strcpy((char*)p,str_p);
  252. break;
  253. case 'c':
  254. if(p)*((char*)p)=*str_p;
  255. break;
  256. case 'f':
  257. f=atof(str_p);
  258. if(p)*((float*)p)=f;
  259. break;
  260. case 'd':
  261. sscanf(str_p,"%d",&d);
  262. if(p)*((int*)p)=d;
  263. break;
  264. default:
  265. gps_err();
  266. ad0x0_err();
  267. }
  268. }
  269. void parse_g(char *s,char *t,void **p){
  270. char b[32],*pb;
  271. uint8_t i=0;
  272. pb=b;
  273. if(!s){
  274. ad0x0_err();
  275. return;
  276. }
  277. memset(b,'x',sizeof(b));
  278. while((i<75)&&(*s!='*')&&(*s)&&(*t)){
  279. if(*s==','){
  280. *pb++=0;
  281. if(*t && *b)setval(*t,*p,b);
  282. pb=b;
  283. p++;
  284. t++;
  285. }else{
  286. *pb++=*s;
  287. }
  288. s++;
  289. i++;
  290. }
  291. }
  292. void GPS_parse_ad0x0(char *s){
  293. //$GNRMC,180159.00,A,5137.81278,N,03815.19037,E,2.468,71.94,050119,,,A*4C
  294. if(!strncmp(s, "$GNRMC", 6)){//ad0x0
  295. char t[]="sfcfcfcffd\0";
  296. void *p[]={NULL,&GPS.utc_time, NULL, &GPS.nmea_latitude, &GPS.ns, &GPS.nmea_longitude, &GPS.ew, &GPS.speed_k, &GPS.course_d, &GPS.date};
  297. parse_g(s,t,p);
  298. GPS.dec_latitude = GPS_nmea_to_dec(GPS.nmea_latitude, GPS.ns);
  299. GPS.dec_longitude = GPS_nmea_to_dec(GPS.nmea_longitude, GPS.ew);
  300. update_gps_data();
  301. }else
  302. if(!strncmp(s, "$GNGGA", 6)){
  303. char t[]="sffcfcddffc\0";
  304. void *p[]={NULL,&GPS.utc_time, &GPS.nmea_latitude, &GPS.ns, &GPS.nmea_longitude, &GPS.ew, &GPS.lock, &GPS.satelites, &GPS.hdop, &GPS.msl_altitude, &GPS.msl_units};
  305. parse_g(s,t,p);
  306. GPS.dec_latitude = GPS_nmea_to_dec(GPS.nmea_latitude, GPS.ns);
  307. GPS.dec_longitude = GPS_nmea_to_dec(GPS.nmea_longitude, GPS.ew);
  308. update_gps_data();
  309. }
  310. }
  311. void GPS_parse(char *GPSstrParse){
  312. char m;
  313. if (!strncmp(GPSstrParse, "$GNRMC", 6)){//ad0x0
  314. //$GNRMC,180159.00,A,5137.81278,N,03815.19037,E,2.468,71.94,050119,,,A*4C
  315. if(sscanf(GPSstrParse, "$GNRMC,%f,%c,%f,%c,%f,%c,%f,%f,%d", &GPS.utc_time, &m, &GPS.nmea_latitude, &GPS.ns, &GPS.nmea_longitude, &GPS.ew, &GPS.speed_k, &GPS.course_d, &GPS.date) >= 1){
  316. GPS.dec_latitude = GPS_nmea_to_dec(GPS.nmea_latitude, GPS.ns);
  317. GPS.dec_longitude = GPS_nmea_to_dec(GPS.nmea_longitude, GPS.ew);
  318. update_gps_data();
  319. return;
  320. }
  321. }else
  322. if(!strncmp(GPSstrParse, "$GNGGA", 6)){
  323. if (sscanf(GPSstrParse, "$GNGGA,%f,%f,%c,%f,%c,%d,%d,%f,%f,%c", &GPS.utc_time, &GPS.nmea_latitude, &GPS.ns, &GPS.nmea_longitude, &GPS.ew, &GPS.lock, &GPS.satelites, &GPS.hdop, &GPS.msl_altitude, &GPS.msl_units) >= 1){
  324. GPS.dec_latitude = GPS_nmea_to_dec(GPS.nmea_latitude, GPS.ns);
  325. GPS.dec_longitude = GPS_nmea_to_dec(GPS.nmea_longitude, GPS.ew);
  326. update_gps_data();
  327. return;
  328. }
  329. }else
  330. if(!strncmp(GPSstrParse, "$GPGGA", 6)){
  331. if (sscanf(GPSstrParse, "$GPGGA,%f,%f,%c,%f,%c,%d,%d,%f,%f,%c", &GPS.utc_time, &GPS.nmea_latitude, &GPS.ns, &GPS.nmea_longitude, &GPS.ew, &GPS.lock, &GPS.satelites, &GPS.hdop, &GPS.msl_altitude, &GPS.msl_units) >= 1){
  332. GPS.dec_latitude = GPS_nmea_to_dec(GPS.nmea_latitude, GPS.ns);
  333. GPS.dec_longitude = GPS_nmea_to_dec(GPS.nmea_longitude, GPS.ew);
  334. update_gps_data();
  335. return;
  336. }
  337. }
  338. else if (!strncmp(GPSstrParse, "$GPRMC", 6)){
  339. if(sscanf(GPSstrParse, "$GPRMC,%f,%f,%c,%f,%c,%f,%f,%d", &GPS.utc_time, &GPS.nmea_latitude, &GPS.ns, &GPS.nmea_longitude, &GPS.ew, &GPS.speed_k, &GPS.course_d, &GPS.date) >= 1){
  340. update_gps_data();
  341. return;
  342. }
  343. }
  344. else if (!strncmp(GPSstrParse, "$GPGLL", 6)){
  345. if(sscanf(GPSstrParse, "$GPGLL,%f,%c,%f,%c,%f,%c", &GPS.nmea_latitude, &GPS.ns, &GPS.nmea_longitude, &GPS.ew, &GPS.utc_time, &GPS.gll_status) >= 1){
  346. update_gps_data();
  347. return;
  348. }
  349. }
  350. else if (!strncmp(GPSstrParse, "$GPVTG", 6)){
  351. if(sscanf(GPSstrParse, "$GPVTG,%f,%c,%f,%c,%f,%c,%f,%c", &GPS.course_t, &GPS.course_t_unit, &GPS.course_m, &GPS.course_m_unit, &GPS.speed_k, &GPS.speed_k_unit, &GPS.speed_km, &GPS.speed_km_unit) >= 1)
  352. update_gps_data();
  353. return;
  354. }
  355. }
  356. float GPS_nmea_to_dec(float deg_coord, char nsew) {
  357. int degree = (int)(deg_coord/100);
  358. float minutes = deg_coord - degree*100;
  359. float dec_deg = minutes / 60;
  360. float decimal = degree + dec_deg;
  361. if (nsew == 'S' || nsew == 'W') { // return negative
  362. decimal *= -1;
  363. }
  364. return decimal;
  365. }
  366. void update_gps_data(void){
  367. gps_data.latitude=GPS.dec_latitude;
  368. gps_data.longitude=GPS.dec_longitude;
  369. gps_data.satelites=GPS.satelites;
  370. gps_data.speed_km=GPS.utc_time;
  371. if(gps_data_ready_func)gps_data_ready_func(&gps_data);
  372. }