STM32之GPS定位模块(GT-U8)
目录
一、模块概述
二、模块简介
2.1 模块特点
2.2 电气特性
2.3 模块接口说明
2.4 工作原理
2.5 原理图设计
2.6 实际应用注意事项
三、硬件设计
3.1 硬件组成
3.2 硬件连接
四、软件设计
4.1 开发环境配置
4.2 关键代码实现
4.2.1 USART初始化代码
4.2.2 串口中断处理
4.2.3 NMEA数据解析代码
4.2.4 主程序代码
五、功能实现与优化
六、常见问题解决
七、总结
一、模块概述
GPS(全球定位系统)模块在现代嵌入式系统中应用广泛,从车辆导航到物联网设备定位都有重要应用。GT-U8是一款高性能GPS接收模块,具有高灵敏度、低功耗等特点,能够提供精确的位置、速度和时间信息。本文将详细介绍如何使用STM32F103C8T6最小系统板通过标准外设库读取GT-U8 GPS模块的数据。
二、模块简介
模块实物图:
2.1 模块特点
GT-U8 GPS模块具有以下主要特点:
- 采用UBLOX NEO-6M芯片组
- 支持NMEA0183 V3.01协议
- 定位精度:2.5米CEP
- 灵敏度:-161dBm
- 更新速率:最高5Hz
- 工作电压:3.3V-5V DC
- 内置EEPROM保存配置
- 自带陶瓷天线及外接天线接口
2.2 电气特性
参数 | 规格 |
---|---|
工作电压 | 3.3V-5V DC |
工作电流 | 45mA(连续运行) |
通信接口 | UART(TTL电平) |
波特率 | 默认9600bps(可配置) |
工作温度 | -40℃ ~ 85℃ |
2.3 模块接口说明
GT-U8模块通常提供5引脚接口:
1. VCC:电源输入(3.3V-5V)
2. GND:地线
3. TX:串行数据输出
4. RX:串行数据输入
5. PPS:秒脉冲输出(可选)
2.4 工作原理
模块必须在室外空旷地才能定位,天线金属头必须面对天空,天线上方不能有遮挡物!有时候大雾大雨天气也是有影响的,室内是没办法定位成功的。模块定位成功的话红色led会以1S一次的频率闪烁。
GT-U8模块通过接收多颗GPS卫星信号,计算得出当前位置的经纬度、海拔高度、速度、UTC时间等信息,并通过串口以NMEA-0183标准格式输出。STM32通过串口接收这些数据并解析,即可获取所需的定位信息。例如:
1. 原始NMEA数据输出
Received: $GPGGA,082543.00,3956.4567,N,11623.8912,E,1,08,1.2,125.6,M,-12.3,M,,*4A
Received: $GPRMC,082543.00,A,3956.4567,N,11623.8912,E,12.5,45.2,210725,2.3,W*7C
Received: $GPGGA,082544.00,3956.4578,N,11623.8923,E,1,08,1.1,126.1,M,-12.3,M,,*4B
2. 解析后的格式化输出
=== GPS Data ===
Time: 08:25:43 UTC
Latitude: 39.9409° N
Longitude: 116.3982° E
Altitude: 125.6 meters
Fix Quality: 1 (GPS fix)
Satellites: 8
HDOP: 1.2 (High precision)
Speed: 23.15 km/h (from GPRMC)
Course: 45.2° True
Date: 21-07-2025
关键字段说明:
字段 | 示例值 | 说明 |
---|---|---|
Time | 08:25:43 | UTC时间(时:分:秒) |
Latitude | 39.9409° N | 纬度(十进制度数,北纬为正) |
Longitude | 116.3982° E | 经度(十进制度数,东经为正) |
Altitude | 125.6m | 海拔高度(米) |
Fix Quality | 1 | 0=无效,1=GPS定位,2=差分GPS |
Satellites | 8 | 参与定位的卫星数量 |
HDOP | 1.2 | 水平定位精度(值越小精度越高) |
Speed | 23.15 km/h | 地面速度(来自GPRMC语句,换算为km/h) |
Course | 45.2° True | 航向角(表示移动方向相对于真北的角度) |
Data | 210725 | 日月年,各2位 |
2.5 原理图设计
该电路的主要功能是通过GPS模块接收卫星信号,处理位置信息,并通过I2C接口存储数据到EEPROM中。电源管理部分确保系统稳定运行,LED指示灯用于显示电源状态。接口部分提供了与外部设备的连接,方便扩展功能。
2.6 实际应用注意事项
1. 首次定位可能需要较长时间(冷启动约30秒)
2. 室外使用效果最佳,室内可能无法定位
3. 天线应避免被金属物体遮挡
4. 注意电源稳定性,电压波动可能影响模块性能
三、硬件设计
3.1 硬件组成
所需硬件组件:
- STM32F103C8T6最小系统板
- GT-U8 GPS模块
- USB转TTL模块(用于调试)
- 杜邦线若干
- 电源(5V或3.3V)
3.2 硬件连接
连接方式如下:
STM32F103C8T6 | GT-U8模块 |
---|---|
5V或3.3V | VCC |
GND | GND |
PA3(USART2_RX) | TX |
PA2(USART2_TX) | RX(可选) |
注意:如果不需要设置GPS模块,可以只连接TX线。
四、软件设计
4.1 开发环境配置
1. 安装Keil MDK-ARM开发环境
2. 下载STM32标准外设库
3. 创建新工程,添加必要的库文件
4. 配置USART2用于串口通信
4.2 关键代码实现
4.2.1 USART初始化代码
#include "stm32f10x.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"#define GPS_USART USART2
#define GPS_USART_IRQn USART2_IRQnvoid GPS_USART_Init(uint32_t baudrate)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;// 使能时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);// 配置USART2 Tx (PA2)为推挽复用输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置USART2 Rx (PA3)为浮空输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// USART参数配置USART_InitStructure.USART_BaudRate = baudrate;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(GPS_USART, &USART_InitStructure);// 使能接收中断USART_ITConfig(GPS_USART, USART_IT_RXNE, ENABLE);// 配置USART中断NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQHandler;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);// 使能USARTUSART_Cmd(GPS_USART, ENABLE);
}
功能:配置STM32的USART2串口与GPS模块通信。
关键步骤:
-
时钟使能:开启GPIOA和USART2的时钟。
-
GPIO配置:
-
PA2 (USART2_TX) 设置为复用推挽输出(用于发送数据,但GPS模块通常只需接收)。
-
PA3 (USART2_RX) 设置为浮空输入(接收GPS数据)。
-
-
USART参数:
-
波特率:默认9600bps(与GT-U8模块匹配)。
-
数据位:8位,无校验,1位停止位。
-
-
中断配置:
-
使能接收中断 (
USART_IT_RXNE
),当接收到数据时触发中断。 -
设置NVIC中断优先级。
-
4.2.2 串口中断处理
#define GPS_BUFFER_SIZE 256char gpsBuffer[GPS_BUFFER_SIZE];
uint16_t gpsBufferIndex = 0;
volatile uint8_t gpsDataReady = 0;void USART2_IRQHandler(void)
{if(USART_GetITStatus(GPS_USART, USART_IT_RXNE) != RESET){char receivedChar = USART_ReceiveData(GPS_USART);if(receivedChar == '$') // NMEA语句开始{gpsBufferIndex = 0;gpsBuffer[gpsBufferIndex++] = receivedChar;}else if(receivedChar == '\n') // NMEA语句结束{if(gpsBufferIndex < GPS_BUFFER_SIZE - 1){gpsBuffer[gpsBufferIndex++] = receivedChar;gpsBuffer[gpsBufferIndex] = '\0'; // 字符串终止符gpsDataReady = 1;}gpsBufferIndex = 0;}else{if(gpsBufferIndex < GPS_BUFFER_SIZE - 1){gpsBuffer[gpsBufferIndex++] = receivedChar;}}}
}
功能:实时接收GPS模块发送的NMEA协议数据。
关键逻辑:
-
检测中断标志:
USART_IT_RXNE
表示接收到新数据。 -
数据缓冲:
-
遇到
$
符号:视为NMEA语句开始,重置缓冲区索引。 -
遇到
\n
(换行符):视为语句结束,添加字符串终止符\0
,并置位gpsDataReady
标志。 -
其他字符:存入缓冲区,防止溢出。
-
-
注意:NMEA语句以
$
开头,以\r\n
结尾,例如:
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47\r\n
4.2.3 NMEA数据解析代码
void parseGPGGA(const char* nmea)
{// 示例:解析GPGGA语句// $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47char sentence[6];sscanf(nmea, "%5s", sentence);if(strcmp(sentence, "$GPGGA") == 0){float latitude, longitude;int hour, minute, second;char latDir, lonDir;int fixQuality, numSatellites;float hdop, altitude;sscanf(nmea, "$GPGGA,%2d%2d%2d,%f,%c,%f,%c,%d,%d,%f,%f",&hour, &minute, &second, &latitude, &latDir, &longitude, &lonDir,&fixQuality, &numSatellites, &hdop, &altitude);// 转换为度分秒格式float latDeg = (int)(latitude / 100);float latMin = latitude - latDeg * 100;float lat = latDeg + latMin / 60.0f;if(latDir == 'S') lat = -lat;float lonDeg = (int)(longitude / 100);float lonMin = longitude - lonDeg * 100;float lon = lonDeg + lonMin / 60.0f;if(lonDir == 'W') lon = -lon;printf("Time: %02d:%02d:%02d\n", hour, minute, second);printf("Latitude: %.6f %c\n", lat, latDir);printf("Longitude: %.6f %c\n", lon, lonDir);printf("Fix Quality: %d\n", fixQuality);printf("Satellites: %d\n", numSatellites);printf("Altitude: %.1f meters\n", altitude);}
}
功能:解析GPGGA语句(包含时间、经纬度、海拔等关键信息)。
数据格式:
$GPGGA,<时间>,<纬度>,<纬度方向>,<经度>,<经度方向>,<定位质量>,<卫星数>,<HDOP>,<海拔>,...
关键步骤:
-
提取字段:使用
sscanf
分割字符串,获取时间、经纬度、定位质量等。 -
单位转换:
-
经纬度格式为
度度分分.分分
,需转换为十进制度数(如4807.038
→48 + 7.038/60 = 48.1173°
)。 -
方向(N/S/E/W)决定正负值。
-
-
输出信息:解析后的时间、经纬度、海拔等。
4.2.4 主程序代码
int main(void)
{SystemInit();// 初始化调试串口(USART1)USART1_Init(115200);printf("System Initialized\r\n");// 初始化GPS串口(USART2)GPS_USART_Init(9600);printf("GPS USART Initialized\r\n");while(1){if(gpsDataReady){printf("Received: %s", gpsBuffer);parseGPGGA(gpsBuffer);gpsDataReady = 0;}}
}
功能:循环检测gpsDataReady
标志,解析并打印GPS数据。
流程:
-
初始化系统时钟、调试串口(USART1)和GPS串口(USART2)。
-
主循环中,当
gpsDataReady=1
时,调用parseGPGGA
解析数据。
串口打印的结果:
五、功能实现与优化
1. 多语句解析:扩展parseGPGGA函数以支持GPRMC等其他NMEA语句
2. 数据校验:添加NMEA语句的校验和验证
3. 数据过滤:只处理有效的定位数据(fixQuality=1或2)
4. 数据缓存:使用环形缓冲区提高数据接收可靠性
5. 低功耗优化:在不需要定位时关闭GPS模块
6. 数据平滑:对连续定位数据进行滤波处理
优化后的解析函数示例:
typedef struct {float latitude;float longitude;float altitude;float speed;float course;uint8_t fixStatus;uint8_t satellites;uint8_t hour;uint8_t minute;uint8_t second;
} GPS_Data;GPS_Data currentGPSData;uint8_t validateNMEA(const char* nmea)
{// 检查校验和if(strlen(nmea) < 6 || nmea[0] != '$') return 0;const char* asterisk = strchr(nmea, '*');if(asterisk == NULL) return 0;uint8_t checksum = 0;for(const char* p = nmea + 1; p < asterisk; p++){checksum ^= *p;}uint8_t receivedChecksum;sscanf(asterisk + 1, "%02hhx", &receivedChecksum);return checksum == receivedChecksum;
}void parseNMEA(const char* nmea)
{if(!validateNMEA(nmea)) return;char sentenceID[6];sscanf(nmea, "%5s", sentenceID);if(strcmp(sentenceID, "$GPGGA") == 0){// 解析GPGGA语句float latitude, longitude;char latDir, lonDir;int fixQuality, numSatellites;float hdop, altitude;sscanf(nmea, "$GPGGA,%2d%2d%2d,%f,%c,%f,%c,%d,%d,%f,%f",¤tGPSData.hour, ¤tGPSData.minute, ¤tGPSData.second,&latitude, &latDir, &longitude, &lonDir, &fixQuality,&numSatellites, &hdop, &altitude);// 转换为度分秒格式float latDeg = (int)(latitude / 100);float latMin = latitude - latDeg * 100;currentGPSData.latitude = latDeg + latMin / 60.0f;if(latDir == 'S') currentGPSData.latitude = -currentGPSData.latitude;float lonDeg = (int)(longitude / 100);float lonMin = longitude - lonDeg * 100;currentGPSData.longitude = lonDeg + lonMin / 60.0f;if(lonDir == 'W') currentGPSData.longitude = -currentGPSData.longitude;currentGPSData.altitude = altitude;currentGPSData.fixStatus = fixQuality;currentGPSData.satellites = numSatellites;}else if(strcmp(sentenceID, "$GPRMC") == 0){// 解析GPRMC语句获取速度和航向float speedKnots, course;sscanf(nmea, "$GPRMC,%*f,%*c,%*f,%*c,%*f,%*c,%f,%f", &speedKnots, &course);// 转换为km/hcurrentGPSData.speed = speedKnots * 1.852f;currentGPSData.course = course;}
}
-
校验和:NMEA语句末尾的
*47
是校验和,确保数据完整性。 -
结构体存储:将解析后的数据存入
GPS_Data
结构体,便于后续使用。
六、常见问题解决
1. 无法接收GPS数据
- 检查硬件连接是否正确
- 确认波特率设置匹配(默认9600bps)
- 确保GPS天线有良好的天空视野
- 检查STM32串口中断优先级设置
2. 数据解析错误
- 确认NMEA语句格式正确
- 实现校验和验证功能
- 检查缓冲区溢出问题
3. 定位时间过长
- 首次冷启动可能需要30秒以上
- 确保在室外开阔地带使用
- 考虑使用AGPS辅助定位
4. 数据不稳定
- 实现数据滤波算法
- 检查电源稳定性
- 确保天线不被金属物体遮挡
5. 内存不足
- 优化缓冲区大小
- 使用更高效的数据结构
- 考虑使用DMA传输减少CPU负载
七、总结
本文详细介绍了如何使用STM32F103C8T6最小系统板通过标准外设库读取GT-U8 GPS模块的数据。从硬件连接到软件实现,涵盖了USART配置、NMEA协议解析、数据校验等关键环节。通过本文的指导,开发者可以快速实现GPS定位功能,并根据实际需求进行功能扩展和优化。
通过合理的设计和优化,STM32F103C8T6与GT-U8 GPS模块的组合可以为各种嵌入式定位应用提供可靠的解决方案。