#include "gps.h" /** 提示: 虽然 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; // TEST 是进行逻辑测试时候的代码,else之后的是加入到Thread X的实际控制代码 #ifdef TEST //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 GPS_Init(void) { HAL_UARTEx_ReceiveToIdle_DMA(&huart2, GPS_DMA_RX_BUF, GPS_DMA_RX_BUF_LEN); __HAL_DMA_DISABLE_IT(&handle_GPDMA1_Channel3, DMA_IT_HT); // 禁用半传输 } 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 //重新开启接收 HAL_UARTEx_ReceiveToIdle_DMA(&huart2,GPS_DMA_RX_BUF,GPS_DMA_RX_BUF_LEN); __HAL_DMA_DISABLE_IT(&handle_GPDMA1_Channel3,DMA_IT_HT); } } // 串口数据清除 void GPS_Data_CLR(void) { memset(GPS_DMA_RX_BUF,0,GPS_DMA_RX_BUF_LEN); } #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); } #else // 这部分是留给后续的 Thread X #endif