Files
ManGoWalk_STM32/fun/gps.c

359 lines
9.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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_UARTEx_ReceiveToIdle_DMA(&huart2,GPS_DMA_RX_BUF,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;
// }
//
//}
//void parseGpsBuffer(void)
//{
// if (!GPS.isGetData) return;
// GPS.isGetData = 0;
// /* ----------- 句型判别 ------------ */
// const char *p = GPS.GPS_Buffer;
// /* ★ RMC ----------------------------------------------------- */
// if (!strncmp(p, "$GNRMC", 6) || !strncmp(p, "$GPRMC", 6))
// {
// char status, lat[16], ns[3], lon[16], ew[3];
// if (sscanf(p,
// "$%*[^,],%*[^,],%c,%15[^,],%2[^,],%15[^,],%2[^,],",
// &status, lat, ns, lon, ew) == 5)
// {
// if (status == 'A') /* 定位有效 */
// {
// strcpy(GPS.latitude, lat);
// strcpy(GPS.N_S, ns);
// strcpy(GPS.longitude, lon);
// strcpy(GPS.E_W, ew);
// GPS.isParseData = 1;
// GPS.isUsefull = 1;
// }
// }
// return;
// }
// /* ★ GGA ----------------------------------------------------- */
// if (!strncmp(p, "$GNGGA", 6) || !strncmp(p, "$GPGGA", 6))
// {
// int q; char lat[16], ns[3], lon[16], ew[3];
// if (sscanf(p,
// "$%*[^,],%*[^,],%15[^,],%2[^,],%15[^,],%2[^,],%d,",
// lat, ns, lon, ew, &q) == 5)
// {
// if (q > 0) /* q=0 无定位 */
// {
// strcpy(GPS.latitude, lat);
// strcpy(GPS.N_S, ns);
// strcpy(GPS.longitude, lon);
// strcpy(GPS.E_W, ew);
// GPS.isParseData = 1;
// GPS.isUsefull = 1;
// }
// }
// return;
// }
// /* ★ GLL ----------------------------------------------------- */
// if (!strncmp(p, "$GNGLL", 6) || !strncmp(p, "$GPGLL", 6))
// {
// char status, lat[16], ns[3], lon[16], ew[3];
// if (sscanf(p,
// "$%*[^,],%15[^,],%2[^,],%15[^,],%2[^,],%*[^,],%c",
// lat, ns, lon, ew, &status) == 5)
// {
// if (status == 'A')
// {
// strcpy(GPS.latitude, lat);
// strcpy(GPS.N_S, ns);
// strcpy(GPS.longitude, lon);
// strcpy(GPS.E_W, ew);
// GPS.isParseData = 1;
// GPS.isUsefull = 1;
// }
// }
// }
//}
/* === ① 行缓存区 & 推送函数 === */
static char line_buf[GPS_Buffer_Length];
static uint16_t line_w = 0;
void GPS_LinePush(uint8_t ch)
{
if (ch == '\n') { /* 一句结束 */
line_buf[line_w] = '\0';
strncpy(GPS.GPS_Buffer, line_buf, GPS_Buffer_Length);
line_w = 0;
GPS.isGetData = 1;
tx_event_flags_set(&system_events, EVENT_GPS_DATA_READY, TX_OR);
return;
}
if (line_w < GPS_Buffer_Length - 1)
line_buf[line_w++] = ch; /* 普通字符 */
}
/* === ② 新解析器:只要经纬度 === */
void parseGpsBuffer(void)
{
if (!GPS.isGetData) return;
GPS.isGetData = 0;
GPS.isParseData = 0;
GPS.isUsefull = 0;
const char *p = GPS.GPS_Buffer;
/* ---- $GxRMC ---- */
if (!strncmp(p, "$GNRMC", 6) || !strncmp(p, "$GPRMC", 6)) {
char s, lat[16], ns[3], lon[16], ew[3];
if (sscanf(p,
"$%*[^,],%*[^,],%c,%15[^,],%2[^,],%15[^,],%2[^,],",
&s, lat, ns, lon, ew) == 5 && s == 'A') {
strcpy(GPS.latitude, lat); strcpy(GPS.N_S, ns);
strcpy(GPS.longitude, lon); strcpy(GPS.E_W, ew);
GPS.isParseData = GPS.isUsefull = 1;
}
return;
}
/* ---- $GxGGA ---- */
if (!strncmp(p, "$GNGGA", 6) || !strncmp(p, "$GPGGA", 6)) {
int q; char lat[16], ns[3], lon[16], ew[3];
if (sscanf(p,
"$%*[^,],%*[^,],%15[^,],%2[^,],%15[^,],%2[^,],%d,",
lat, ns, lon, ew, &q) == 5 && q > 0) {
strcpy(GPS.latitude, lat); strcpy(GPS.N_S, ns);
strcpy(GPS.longitude, lon); strcpy(GPS.E_W, ew);
GPS.isParseData = GPS.isUsefull = 1;
}
return;
}
/* ---- $GxGLL ---- */
if (!strncmp(p, "$GNGLL", 6) || !strncmp(p, "$GPGLL", 6)) {
char s, lat[16], ns[3], lon[16], ew[3];
if (sscanf(p,
"$%*[^,],%15[^,],%2[^,],%15[^,],%2[^,],%*[^,],%c",
lat, ns, lon, ew, &s) == 5 && s == 'A') {
strcpy(GPS.latitude, lat); strcpy(GPS.N_S, ns);
strcpy(GPS.longitude, lon); strcpy(GPS.E_W, ew);
GPS.isParseData = GPS.isUsefull = 1;
}
}
}
#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 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_IT(&huart2,GPS_DMA_RX_BUF,GPS_DMA_RX_BUF_LEN);
// }
//
//}
// 如果需要使用到ThreadX 就把gps.h中的 TEST 宏定义加入
#ifdef TEST
void gps_thread_entry(ULONG thread_input)
{
GPS_Init();
static int gps_first_fix_sent = 0;
BleMessage msg;
while (1)
{
ULONG events;
tx_event_flags_get(&system_events, EVENT_GPS_DATA_READY, TX_OR_CLEAR, &events, TX_WAIT_FOREVER);
parseGpsBuffer();
HCBle_SendData("[GPS] isGetData=%d, isParseData=%d, isUsefull=%d, Buffer=%s\r\n",
GPS.isGetData, GPS.isParseData, GPS.isUsefull, GPS.GPS_Buffer);
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);
msg.lat = current_location.lat;
msg.lon = current_location.lon;
// 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