# 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