#include "gps.h" //#define TEST 1 //测试使用,去除的时候可以接触代码的调用 #define parse 1 // 测试使用 /** 提示: 虽然 BLE 以及 GPS都是DMA+ UART接收,但是它们都有所不同 BLE --- DMA + IDLE 中断 循环 DMA + 空闲中断触发处理 UART IDLE GPS --- DMA +固定长度 + TC中断 设置固定长度 DMA DMA传输完成中断 **/ //外部引入 extern UART_HandleTypeDef huart2; extern DMA_HandleTypeDef handle_GPDMA1_Channel3; //全局数据变量定义 uint8_t GPS_DMA_RX_BUF[GPS_DMA_RX_BUF_LEN]; //用于DMA接收缓冲 _GPSData GPS; void GPS_Init(void) { HAL_UARTEx_ReceiveToIdle_IT(&huart2, GPS_DMA_RX_BUF, GPS_DMA_RX_BUF_LEN); // __HAL_DMA_DISABLE_IT(&handle_GPDMA1_Channel3, DMA_IT_HT); // 禁用半传输 } #ifdef parse // GPS数据解析 void parseGpsBuffer() { char *subString; char *subStringNext; char i = 0; if(GPS.isGetData) { GPS.isGetData = 0; // 把标志位置为1 char usefullBuffer[2] = {0}; for(i = 0; i <= 6; i++) { if(i == 0) { subString = strstr(GPS.GPS_Buffer,","); if(!subString)return; } else { subString++; subStringNext = strstr(subString,","); if(!subStringNext)return; switch(i) { case 1: memcpy(GPS.UTCTime,subString,subStringNext - subString); break; case 2: memcpy(usefullBuffer,subString,subStringNext - subString); break; case 3: memcpy(GPS.latitude,subString,subStringNext - subString); break; case 4: memcpy(GPS.N_S,subString,subStringNext - subString); break; case 5: memcpy(GPS.longitude,subString,subStringNext - subString); break; case 6: memcpy(GPS.E_W,subString,subStringNext - subString); break; default:break; } subString = subStringNext; } } GPS.isParseData = 1; GPS.isUsefull = (usefullBuffer[0] == 'A') ? 1 : 0; } } #else // 这里是对于改进后的parse 解析 两个都需要进行测试 void parseGpsBuffer() { char *fields[7]; char *token; int fieldIndex = 0; if (GPS.isGetData) { GPS.isGetData = 0; // 把标志位置为0 token = strtok(GPS.GPS_Buffer, ","); while (token != NULL && fieldIndex < 7) { fields[fieldIndex++] = token; token = strtok(NULL, ","); } if (fieldIndex == 7) { memcpy(GPS.UTCTime, fields[1], sizeof(GPS.UTCTime) - 1); GPS.UTCTime[sizeof(GPS.UTCTime) - 1] = '\0'; memcpy(GPS.latitude, fields[3], sizeof(GPS.latitude) - 1); GPS.latitude[sizeof(GPS.latitude) - 1] = '\0'; memcpy(GPS.N_S, fields[4], sizeof(GPS.N_S) - 1); GPS.N_S[sizeof(GPS.N_S) - 1] = '\0'; memcpy(GPS.longitude, fields[5], sizeof(GPS.longitude) - 1); GPS.longitude[sizeof(GPS.longitude) - 1] = '\0'; memcpy(GPS.E_W, fields[6], sizeof(GPS.E_W) - 1); GPS.E_W[sizeof(GPS.E_W) - 1] = '\0'; GPS.isParseData = 1; GPS.isUsefull = (fields[2][0] == 'A') ? 1 : 0; } } } /* 改进点总结 使用 strtok 进行分隔: 更加简洁地分割字符串。 数组存储字段: 使用数组存储每个字段的指针,减少重复代码。 边界检查: 确保字段数量足够,避免数组越界。 字符串截断: 确保复制的字符串以 null 结尾,避免潜在的字符串处理问题。 */ #endif // 转换角度 double Convert_to_degrees(char *data) { double temp = atof(data); int deg = (int)(temp / 100); double min = temp - deg * 100; return deg + (min / 60.0); } // 串口数据清除 void GPS_Data_CLR(void) { memset(GPS_DMA_RX_BUF,0,GPS_DMA_RX_BUF_LEN); } void GPS_DMA_Start(void) { HAL_UART_Receive_DMA(&huart2,GPS_DMA_RX_BUF,GPS_DMA_RX_BUF_LEN); __HAL_DMA_ENABLE_IT(huart2.hdmarx,DMA_IT_HT); //半传输中断 __HAL_DMA_ENABLE_IT(huart2.hdmarx,DMA_IT_TC); //全传输中断 } //void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) //{ // if(huart->Instance == USART2) // { // // 根据 Size 拷贝接收到的数据 // memcpy(GPS.GPS_Buffer,GPS_DMA_RX_BUF,Size); // GPS.GPS_Buffer[Size] = '\0'; // GPS.isGetData = 1; //数据接收标志位置为1 // // tx_event_flags_set(&system_events, EVENT_GPS_DATA_READY, TX_OR); // //重新开启接收 // HAL_UARTEx_ReceiveToIdle_DMA(&huart2,GPS_DMA_RX_BUF,GPS_DMA_RX_BUF_LEN); // __HAL_DMA_DISABLE_IT(&handle_GPDMA1_Channel3,DMA_IT_HT); // } // //} // 如果需要使用到ThreadX 就把gps.h中的 TEST 宏定义加入 #ifdef TEST void gps_thread_entry(ULONG thread_input) { GPS_Init(); static int gps_first_fix_sent = 0; while (1) { ULONG events; tx_event_flags_get(&system_events, EVENT_GPS_DATA_READY, TX_OR_CLEAR, &events, TX_WAIT_FOREVER); parseGpsBuffer(); if (GPS.isParseData && GPS.isUsefull) { current_location.lat = Convert_to_degrees(GPS.latitude); current_location.lon = Convert_to_degrees(GPS.longitude); tx_event_flags_set(&system_events, EVENT_LOCATION_UPDATED, TX_OR); char msg[128]; snprintf(msg, sizeof(msg), "#{\"lat\":%.6f,\"lon\":%.6f,\"angle\":%.2f}\n", current_location.lat, current_location.lon, current_location.angle); tx_queue_send(&ble_tx_queue, &msg, TX_WAIT_FOREVER); } } } #endif