- 新增GPS驱动模块,支持NMEA GPGGA/GNGGA语句解析 - 修改USART3配置,波特率从2000000调整为115200用于GPS数据接收 - 新增带GPS信息的校正数据包结构`CorrectedDataPacketWithGPS_t` - 在ADC数据处理流程中集成GPS数据获取和打包 - 更新数据包处理函数,支持GPS时间戳和经纬度信息 - 新增GPS驱动使用指南和集成说明文档 - 修改主循环,添加GPS数据处理调用 - 更新中断处理,添加GPS UART接收回调支持 📝 docs(gps): 添加GPS驱动和集成说明文档 - 新增`GPS_Driver_Guide.md`详细说明GPS驱动API和使用方法 - 新增`GPS_Integration_Guide.md`说明GPS数据集成到采集系统的实现细节 - 文档包含硬件连接、数据格式、使用示例和故障排除等内容 ♻️ refactor(data): 重构数据包结构以支持GPS信息 - 修改`DataPacket_t`和`CorrectedDataPacket_t`结构,添加GPS时间戳和经纬度字段 - 新增`CorrectedDataPacketWithGPS_t`结构用于带完整GPS信息的数据包 - 更新数据打包函数,支持GPS参数传递 - 简化数据包验证逻辑,移除校验和检查以提高处理速度 🔧 chore(config): 更新硬件配置文件 - 更新STM32CubeMX项目文件,修改USART3波特率配置 - 在中断处理文件中添加GPS驱动头文件包含
323 lines
8.9 KiB
Markdown
323 lines
8.9 KiB
Markdown
# GPS驱动使用指南
|
||
|
||
## 概述
|
||
|
||
本GPS驱动用于通过USART3接收GPS模块的NMEA数据,主要解析GPGGA语句,提取时间、经纬度、海拔高度等信息。
|
||
|
||
## 硬件连接
|
||
|
||
- **USART3 TX (PB10)**: 连接到GPS模块的RX(可选,如果需要向GPS发送配置命令)
|
||
- **USART3 RX (PB11)**: 连接到GPS模块的TX(接收GPS数据)
|
||
- **波特率**: 9600(GPS标准波特率)
|
||
- **数据格式**: 8位数据位,1位停止位,无校验位
|
||
|
||
## 功能特性
|
||
|
||
### 1. 支持的NMEA语句
|
||
- **GPGGA**: GPS定位数据(主要解析)
|
||
- **GNGGA**: 北斗+GPS组合定位数据(主要解析)
|
||
- 可扩展支持其他NMEA语句(如GPRMC等)
|
||
|
||
### 2. 解析的数据
|
||
- **时间信息**:
|
||
- UTC时间(时、分、秒、毫秒)
|
||
|
||
- **位置信息**:
|
||
- 纬度(十进制度数)
|
||
- 纬度方向(N/S)
|
||
- 经度(十进制度数)
|
||
- 经度方向(E/W)
|
||
- 海拔高度(米)
|
||
|
||
- **定位质量**:
|
||
- 定位状态(无效、GPS、DGPS、RTK等)
|
||
- 使用的卫星数量
|
||
- 水平精度因子(HDOP)
|
||
|
||
### 3. 数据有效性管理
|
||
- 自动检测GPS定位状态
|
||
- 数据超时检测(2秒无更新则标记为无效)
|
||
- 数据有效标志位
|
||
|
||
## API接口
|
||
|
||
### 初始化函数
|
||
|
||
```c
|
||
HAL_StatusTypeDef GPS_Init(void);
|
||
```
|
||
- **功能**: 初始化GPS驱动,启动UART接收
|
||
- **返回值**: HAL_OK表示成功,HAL_ERROR表示失败
|
||
- **调用位置**: 在main()函数的初始化部分调用
|
||
|
||
### 数据处理函数
|
||
|
||
```c
|
||
void GPS_Process(void);
|
||
```
|
||
- **功能**: GPS数据处理,检查数据超时
|
||
- **调用位置**: 在主循环中定期调用
|
||
|
||
### 获取GPS数据
|
||
|
||
```c
|
||
uint8_t GPS_GetData(GPS_Data_t *gps_data);
|
||
```
|
||
- **功能**: 获取当前GPS数据
|
||
- **参数**: gps_data - 指向GPS数据结构体的指针
|
||
- **返回值**: 1表示数据有效,0表示数据无效或超时
|
||
|
||
### 检查数据有效性
|
||
|
||
```c
|
||
uint8_t GPS_IsDataValid(void);
|
||
```
|
||
- **功能**: 检查GPS数据是否有效
|
||
- **返回值**: 1表示有效,0表示无效
|
||
|
||
### 获取格式化字符串
|
||
|
||
```c
|
||
void GPS_GetTimeString(char *buffer, uint16_t size);
|
||
void GPS_GetPositionString(char *buffer, uint16_t size);
|
||
```
|
||
- **功能**: 获取格式化的GPS时间和位置字符串
|
||
- **参数**:
|
||
- buffer - 输出缓冲区
|
||
- size - 缓冲区大小
|
||
|
||
## 使用示例
|
||
|
||
### 基本使用流程
|
||
|
||
```c
|
||
// 1. 在main()函数中初始化GPS
|
||
GPS_Init();
|
||
|
||
// 2. 在主循环中处理GPS数据
|
||
while (1) {
|
||
// 处理GPS数据(检查超时)
|
||
GPS_Process();
|
||
|
||
// 定期获取GPS数据(例如每5秒)
|
||
if (current_tick - last_gps_check >= 5000) {
|
||
GPS_Data_t gps_data;
|
||
if (GPS_GetData(&gps_data)) {
|
||
// GPS数据有效,可以使用
|
||
printf("Time: %02d:%02d:%02d.%03d UTC\n",
|
||
gps_data.time.hour,
|
||
gps_data.time.minute,
|
||
gps_data.time.second,
|
||
gps_data.time.millisec);
|
||
|
||
printf("Position: %.6f%c, %.6f%c\n",
|
||
gps_data.position.latitude,
|
||
gps_data.position.lat_direction,
|
||
gps_data.position.longitude,
|
||
gps_data.position.lon_direction);
|
||
|
||
printf("Altitude: %.1f m\n", gps_data.position.altitude);
|
||
printf("Satellites: %d\n", gps_data.position.satellites);
|
||
} else {
|
||
printf("GPS data not available\n");
|
||
}
|
||
last_gps_check = current_tick;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 获取格式化字符串
|
||
|
||
```c
|
||
char time_str[64];
|
||
char pos_str[128];
|
||
|
||
GPS_GetTimeString(time_str, sizeof(time_str));
|
||
GPS_GetPositionString(pos_str, sizeof(pos_str));
|
||
|
||
// 通过串口发送
|
||
HAL_UART_Transmit(&huart1, (uint8_t*)time_str, strlen(time_str), 100);
|
||
HAL_UART_Transmit(&huart1, (uint8_t*)pos_str, strlen(pos_str), 100);
|
||
```
|
||
|
||
## 数据结构
|
||
|
||
### GPS_Time_t - GPS时间结构体
|
||
|
||
```c
|
||
typedef struct {
|
||
uint8_t hour; // 时 (UTC)
|
||
uint8_t minute; // 分
|
||
uint8_t second; // 秒
|
||
uint16_t millisec; // 毫秒
|
||
} GPS_Time_t;
|
||
```
|
||
|
||
### GPS_Position_t - GPS位置结构体
|
||
|
||
```c
|
||
typedef struct {
|
||
double latitude; // 纬度 (度)
|
||
char lat_direction; // 纬度方向 ('N' or 'S')
|
||
double longitude; // 经度 (度)
|
||
char lon_direction; // 经度方向 ('E' or 'W')
|
||
double altitude; // 海拔高度 (米)
|
||
GPS_FixStatus_t fix_status; // 定位状态
|
||
uint8_t satellites; // 使用的卫星数量
|
||
float hdop; // 水平精度因子
|
||
} GPS_Position_t;
|
||
```
|
||
|
||
### GPS_Data_t - GPS数据结构体
|
||
|
||
```c
|
||
typedef struct {
|
||
GPS_Time_t time; // GPS时间
|
||
GPS_Position_t position; // GPS位置
|
||
uint8_t data_valid; // 数据有效标志 (1=有效, 0=无效)
|
||
uint32_t last_update_tick; // 最后更新时间戳
|
||
} GPS_Data_t;
|
||
```
|
||
|
||
### GPS_FixStatus_t - GPS定位状态枚举
|
||
|
||
```c
|
||
typedef enum {
|
||
GPS_FIX_INVALID = 0, // 无效定位
|
||
GPS_FIX_GPS = 1, // GPS定位
|
||
GPS_FIX_DGPS = 2, // 差分GPS定位
|
||
GPS_FIX_PPS = 3, // PPS定位
|
||
GPS_FIX_RTK = 4, // RTK固定解
|
||
GPS_FIX_RTK_FLOAT = 5, // RTK浮点解
|
||
GPS_FIX_ESTIMATED = 6, // 估算
|
||
GPS_FIX_MANUAL = 7, // 手动输入
|
||
GPS_FIX_SIMULATION = 8 // 模拟模式
|
||
} GPS_FixStatus_t;
|
||
```
|
||
|
||
## NMEA GPGGA语句格式
|
||
|
||
GPGGA语句示例:
|
||
```
|
||
$GPGGA,123519.00,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
|
||
```
|
||
|
||
字段说明:
|
||
- **字段0**: $GPGGA - 语句标识符
|
||
- **字段1**: 123519.00 - UTC时间 (hhmmss.ss)
|
||
- **字段2**: 4807.038 - 纬度 (ddmm.mmmm)
|
||
- **字段3**: N - 纬度方向 (N/S)
|
||
- **字段4**: 01131.000 - 经度 (dddmm.mmmm)
|
||
- **字段5**: E - 经度方向 (E/W)
|
||
- **字段6**: 1 - 定位质量 (0=无效, 1=GPS, 2=DGPS, etc.)
|
||
- **字段7**: 08 - 使用的卫星数量
|
||
- **字段8**: 0.9 - HDOP水平精度因子
|
||
- **字段9**: 545.4 - 海拔高度
|
||
- **字段10**: M - 高度单位 (米)
|
||
- **字段11-14**: 其他信息
|
||
- **字段15**: *47 - 校验和
|
||
|
||
## 坐标转换
|
||
|
||
GPS模块输出的坐标格式为度分格式(ddmm.mmmm),驱动会自动转换为十进制度数格式:
|
||
|
||
**转换公式**:
|
||
```
|
||
十进制度数 = 度 + (分 / 60)
|
||
```
|
||
|
||
**示例**:
|
||
- 输入: 4807.038 N
|
||
- 度数: 48
|
||
- 分钟: 07.038
|
||
- 输出: 48 + (7.038 / 60) = 48.1173°N
|
||
|
||
## 注意事项
|
||
|
||
1. **USART3占用**: GPS驱动使用USART3,因此USART3不能再用于其他功能(如调试输出)
|
||
|
||
2. **波特率配置**: GPS模块的波特率已配置为9600,如果您的GPS模块使用其他波特率,需要在[`usart.c`](../Core/Src/usart.c:73)中修改
|
||
|
||
3. **数据更新频率**: GPS模块通常每秒更新一次数据(1Hz),部分模块支持更高频率
|
||
|
||
4. **冷启动时间**: GPS模块首次启动或长时间未使用后,可能需要30秒到几分钟才能获得有效定位
|
||
|
||
5. **室内定位**: GPS信号在室内通常无法接收,需要在室外或窗边测试
|
||
|
||
6. **数据有效性**: 使用前务必检查[`GPS_IsDataValid()`](gps_driver.h:95)或[`GPS_GetData()`](gps_driver.h:89)的返回值
|
||
|
||
7. **中断优先级**: USART3中断优先级设置为15(最低优先级),如需调整请在[`usart.c`](../Core/Src/usart.c:161)中修改
|
||
|
||
## 扩展功能
|
||
|
||
### 添加其他NMEA语句解析
|
||
|
||
如需解析其他NMEA语句(如GPRMC),可以在[`GPS_ParseNMEA()`](gps_driver.c:213)函数中添加:
|
||
|
||
```c
|
||
static void GPS_ParseNMEA(char *nmea)
|
||
{
|
||
if (nmea == NULL || nmea[0] != '$') {
|
||
return;
|
||
}
|
||
|
||
// 解析GPGGA
|
||
if (strncmp(nmea, "$GPGGA", 6) == 0 || strncmp(nmea, "$GNGGA", 6) == 0) {
|
||
GPS_ParseGPGGA(nmea);
|
||
}
|
||
// 添加GPRMC解析
|
||
else if (strncmp(nmea, "$GPRMC", 6) == 0) {
|
||
GPS_ParseGPRMC(nmea); // 需要实现此函数
|
||
}
|
||
}
|
||
```
|
||
|
||
### 向GPS模块发送配置命令
|
||
|
||
如需向GPS模块发送配置命令,可以使用:
|
||
|
||
```c
|
||
char cmd[] = "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n";
|
||
HAL_UART_Transmit(&huart3, (uint8_t*)cmd, strlen(cmd), 100);
|
||
```
|
||
|
||
## 故障排除
|
||
|
||
### 问题1: 无法接收GPS数据
|
||
- 检查GPS模块电源是否正常
|
||
- 检查USART3引脚连接是否正确
|
||
- 检查GPS模块波特率是否为9600
|
||
- 确认GPS模块在室外或窗边,能接收到卫星信号
|
||
|
||
### 问题2: 数据一直显示无效
|
||
- GPS模块可能需要冷启动时间(30秒到几分钟)
|
||
- 检查GPS模块天线连接
|
||
- 确认在室外或窗边测试
|
||
- 检查GPS模块LED指示灯状态
|
||
|
||
### 问题3: 坐标数据不准确
|
||
- 检查卫星数量是否足够(至少4颗)
|
||
- 检查HDOP值(小于2为良好)
|
||
- 等待GPS模块完全定位(通常需要几分钟)
|
||
|
||
## 文件列表
|
||
|
||
- [`gps_driver.h`](gps_driver.h:1) - GPS驱动头文件
|
||
- [`gps_driver.c`](gps_driver.c:1) - GPS驱动源文件
|
||
- [`main.c`](../Core/Src/main.c:1) - 主程序(包含GPS初始化和使用示例)
|
||
- [`usart.c`](../Core/Src/usart.c:1) - USART配置文件
|
||
- [`stm32f4xx_it.c`](../Core/Src/stm32f4xx_it.c:1) - 中断处理文件
|
||
|
||
## 版本历史
|
||
|
||
- **v1.0** (2026-02-07)
|
||
- 初始版本
|
||
- 支持GPGGA/GNGGA语句解析
|
||
- 提取时间、经纬度、海拔高度等信息
|
||
- 数据有效性管理和超时检测
|
||
|
||
## 作者
|
||
|
||
- 开发者: Your Name
|
||
- 日期: 2026-02-07
|