generated from Template/H563ZI-HAL-CMake-Template
369 lines
9.9 KiB
C
369 lines
9.9 KiB
C
#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';
|
||
|
||
|
||
/* A. 如果不是 '$' 开头,说明它只是上一句的后半截 → 直接拼接 */
|
||
if (line_buf[0] != '$' && GPS.isGetData == 0 && GPS.GPS_Buffer[0] == '$')
|
||
{
|
||
strncat(GPS.GPS_Buffer, line_buf, GPS_Buffer_Length - strlen(GPS.GPS_Buffer) - 1);
|
||
}
|
||
else /* B. 正常完整新句 */
|
||
{
|
||
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;
|
||
}
|
||
}
|
||
|
||
/* === ② 新解析器:只要经纬度 === */
|
||
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);
|
||
BleMessage msg = current_location;
|
||
tx_queue_send(&ble_tx_queue, &msg, TX_WAIT_FOREVER);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
#endif
|
||
|
||
|