基于STM32与LabVIEW的GPS定位系统设计与实现
STM32系列微控制器基于ARM Cortex-M内核,广泛应用于嵌入式系统中,凭借其高性能、低功耗与丰富的外设资源,成为物联网与智能硬件开发的首选平台。本章将深入介绍STM32的架构特点,包括内存结构、时钟系统、中断机制与常用外设模块。同时,将解析GPS全球定位系统的基本组成,涵盖卫星星座、地面监控与用户设备三大部分,并讲解其三角定位原理与数据输出格式。通过本章学习,读者将掌握STM32在定位系
简介:本项目为一个结合STM32嵌入式系统与LabVIEW上位机的GPS定位系统,涵盖硬件开发与图形化界面设计。STM32作为主控芯片负责接收并解析GPS模块数据,LabVIEW用于构建可视化界面以实时显示位置信息。项目已实现基础数据通信与展示功能,后续可扩展实时追踪、轨迹回放、地理围栏等功能,适用于物联网、无人机、车辆监控等应用场景。 
1. STM32与GPS系统概述
STM32系列微控制器基于ARM Cortex-M内核,广泛应用于嵌入式系统中,凭借其高性能、低功耗与丰富的外设资源,成为物联网与智能硬件开发的首选平台。本章将深入介绍STM32的架构特点,包括内存结构、时钟系统、中断机制与常用外设模块。同时,将解析GPS全球定位系统的基本组成,涵盖卫星星座、地面监控与用户设备三大部分,并讲解其三角定位原理与数据输出格式。通过本章学习,读者将掌握STM32在定位系统中的核心作用,为后续实现GPS通信与数据解析奠定基础。
2. GPS模块与STM32的接口通信
2.1 GPS模块的硬件接口
2.1.1 常见GPS模块的选型与参数
在嵌入式系统中,GPS模块作为获取定位信息的关键组件,其选型直接影响系统的稳定性与性能。常见的GPS模块包括 u-blox NEO-6M、LSI LS6111、SiRFstar IV、MTK MT3339 等,其中 u-blox 的 NEO-6M 因其高灵敏度、低功耗和广泛的兼容性而广泛应用于嵌入式项目中。
| 模块型号 | 通信接口 | 最大定位精度 | 启动时间(冷启动) | 功耗(典型) | 天线类型 | 是否支持差分 |
|---|---|---|---|---|---|---|
| u-blox NEO-6M | UART/SPI | 2.5米 | 26秒 | 45mA | 陶瓷天线 | 不支持 |
| LSI LS6111 | UART | 1.5米 | 28秒 | 40mA | 内置天线 | 支持 |
| SiRFstar IV | UART/SPI | 3米 | 30秒 | 50mA | 外置天线 | 支持 |
| MTK MT3339 | UART | 2.8米 | 25秒 | 38mA | 陶瓷天线 | 不支持 |
选型建议:
- 应用场景 :若用于车载导航、无人机或移动机器人,推荐选用支持差分定位的模块(如LS6111),以提升精度。
- 功耗考虑 :若为电池供电系统,建议选择功耗低于40mA的模块。
- 通信方式 :若STM32主控具备多个UART接口,优先使用UART;若需高速数据传输,可考虑SPI接口。
2.1.2 UART与SPI通信接口对比
在嵌入式系统中,GPS模块与STM32之间的通信通常采用 UART 或 SPI 接口。两者在通信速率、硬件资源占用、数据格式等方面存在显著差异。
| 特性 | UART | SPI |
|---|---|---|
| 通信方式 | 异步串行通信 | 同步串行通信 |
| 引脚数量 | TXD、RXD(2根) | SCLK、MOSI、MISO、CS(4根) |
| 通信速率 | 一般在 9600~115200 bps | 可达几 Mbps |
| 数据格式 | 固定起始位+数据位+校验位+停止位 | 用户自定义帧格式 |
| 主从模式 | 半双工或全双工 | 支持多主多从结构 |
| STM32支持 | 每个USART模块均可支持 | 需启用SPI模块并配置时钟极性等参数 |
UART 的优势:
- 接口简单,仅需两根引脚即可实现通信。
- 支持全双工通信,适合长距离数据传输。
- GPS模块普遍默认使用UART通信,兼容性好。
SPI 的优势:
- 通信速率高,适合需要快速传输大量数据的场景。
- 支持DMA操作,减少CPU负担。
- 可连接多个从设备,适合复杂系统架构。
结论:
- 对于一般定位应用, UART 是首选接口 ,因其配置简单、兼容性好。
- 若系统需要高速数据采集或连接多个传感器, SPI 更具优势 ,但需额外配置STM32的SPI模块。
2.2 STM32串口通信配置
2.2.1 UART通信的初始化配置
STM32系列微控制器(如STM32F103C8T6)内置多个USART模块,支持标准UART通信。配置UART通信需完成以下步骤:
- GPIO引脚配置 :将指定的GPIO配置为复用推挽输出(TXD)和浮空输入(RXD)。
- USART模块初始化 :设置波特率、数据位、停止位、校验方式等参数。
- 中断或DMA使能 :根据需求启用接收中断或DMA传输。
以下为使用 STM32 HAL库 初始化 UART 的示例代码:
UART_HandleTypeDef huart1;
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600; // 波特率设置
huart1.Init.WordLength = UART_WORDLENGTH_8B; // 数据位长度
huart1.Init.StopBits = UART_STOPBITS_1; // 停止位
huart1.Init.Parity = UART_PARITY_NONE; // 校验位
huart1.Init.Mode = UART_MODE_TX_RX; // 模式:收发双向
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 无硬件流控
huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 过采样方式
if (HAL_UART_Init(&huart1) != HAL_OK)
{
// 初始化失败处理
}
}
逐行分析:
huart1.Instance = USART1;:选择使用USART1模块。huart1.Init.BaudRate = 9600;:设置通信波特率为9600 bps。huart1.Init.WordLength = UART_WORDLENGTH_8B;:数据位为8位,即每次传输1字节。huart1.Init.StopBits = UART_STOPBITS_1;:停止位为1位。huart1.Init.Parity = UART_PARITY_NONE;:无校验位。huart1.Init.Mode = UART_MODE_TX_RX;:配置为收发双向模式。huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;:不启用硬件流控(RTS/CTS)。huart1.Init.OverSampling = UART_OVERSAMPLING_16;:采用16倍过采样以提高接收稳定性。
2.2.2 波特率设置与数据格式匹配
波特率设置必须与GPS模块的通信参数一致,否则将导致数据丢失或乱码。常见的波特率值包括:9600、19200、38400、57600、115200 bps。
波特率计算公式(以STM32F103为例):
BaudRate = f_CLK / (16 * USARTDIV)
其中:
f_CLK:USART外设的时钟频率(通常为72MHz)。USARTDIV:分频系数,由寄存器自动计算。
例如,设置波特率为 9600:
USARTDIV = 72000000 / (16 * 9600) ≈ 468.75
HAL库在初始化时会自动配置分频寄存器,开发者无需手动计算。
数据格式匹配:
- 数据位 :一般为8位,对应
UART_WORDLENGTH_8B。 - 停止位 :1位(
UART_STOPBITS_1)或2位(UART_STOPBITS_2)。 - 校验位 :无(
UART_PARITY_NONE)、偶校验(UART_PARITY_EVEN)、奇校验(UART_PARITY_ODD)。
注意事项:
- GPS模块默认波特率可能为9600或115200,需通过AT指令或配置工具更改。
- 若波特率不一致,接收端将无法正确解析数据。
2.2.3 接收中断与DMA传输机制
在实际应用中,若使用轮询方式接收GPS数据,会导致CPU资源浪费。因此,推荐使用 接收中断 或 DMA传输 提高效率。
1. 使用接收中断方式:
// 开启接收中断
HAL_UART_Receive_IT(&huart1, rx_buffer, 1);
// 中断回调函数
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart1)
{
// 将接收到的字符存入缓冲区
gps_buffer[gps_index++] = rx_buffer[0];
// 判断是否接收到换行符 '\n'
if (rx_buffer[0] == '\n')
{
// 处理完整NMEA语句
process_gps_data(gps_buffer);
gps_index = 0; // 重置索引
}
}
}
逻辑说明:
HAL_UART_Receive_IT:开启中断接收,每次接收1字节。USART1_IRQHandler:中断服务函数,调用HAL库处理。HAL_UART_RxCpltCallback:回调函数,处理接收到的数据。
2. 使用DMA方式(更高效):
// 启动DMA接收
HAL_UART_Receive_DMA(&huart1, dma_buffer, DMA_BUFFER_SIZE);
DMA优势:
- 数据直接由DMA控制器搬运,CPU无需参与。
- 减少中断响应次数,提高系统实时性。
- 适用于大数据量连续接收场景。
DMA中断回调函数:
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
// 半满中断处理
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// 全满中断处理
}
流程图示意:
graph TD
A[开始] --> B{是否启用DMA?}
B -- 是 --> C[配置DMA通道]
B -- 否 --> D[启用UART接收中断]
C --> E[启动DMA接收]
D --> F[启动中断接收]
E --> G[数据自动搬运到缓冲区]
F --> H[进入中断处理函数]
G --> I[触发DMA中断回调]
H --> J[处理接收到的数据]
I --> K[解析GPS数据]
J --> K
2.3 GPS数据的获取与初步验证
2.3.1 初始化GPS模块并获取原始数据
GPS模块通常通过UART发送 NMEA 0183 格式的ASCII字符串,例如:
$GPGGA,123456.00,4042.6142,N,07400.4168,W,1,08,0.9,545.4,M,46.9,M,,*47
该语句表示时间、纬度、经度、状态等信息。
初始化流程:
- 上电初始化 :给GPS模块供电,等待模块搜星。
- 配置波特率 :若默认波特率不匹配,发送配置指令更改。
- 发送指令启用/禁用特定语句 (可选):
-$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29:启用 $GPRMC 语句。
-$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29:关闭所有语句。
获取原始数据示例代码:
// 发送指令配置模块
uint8_t cmd[] = "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n";
HAL_UART_Transmit(&huart1, cmd, sizeof(cmd)-1, HAL_MAX_DELAY);
// 启动DMA接收
HAL_UART_Receive_DMA(&huart1, gps_buffer, GPS_BUFFER_SIZE);
2.3.2 使用串口调试工具验证数据完整性
在实际开发中,推荐使用 串口调试助手(如XCOM、SSCOM、Tera Term) 来查看GPS模块发送的原始数据。
步骤如下:
- 连接硬件 :将GPS模块的TXD连接到STM32的RXD,或通过USB转TTL模块直连PC。
- 打开串口调试工具 ,设置波特率与模块一致(如9600)。
- 观察数据输出 :查看是否输出NMEA语句,如
$GPGGA、$GPRMC等。 - 验证数据格式 :
- 每条语句以$开始,以\r\n结尾。
- 校验字段(*xx)是否正确。
- 数据字段是否完整,如时间、经纬度、状态等。
示例输出:
$GPGGA,123456.00,4042.6142,N,07400.4168,W,1,08,0.9,545.4,M,46.9,M,,*47
$GPRMC,123456.00,A,4042.6142,N,07400.4168,W,0.0,0.0,010180,,,D*7A
数据验证要点:
- 语句完整性 :每条语句是否完整接收,无断句或缺失。
- 校验和验证 :校验字段是否与计算结果一致(如
*47)。 - 数据内容合理性 :经纬度、时间是否合理,是否为当前地理位置。
通过本章的学习,我们了解了GPS模块的选型、通信接口(UART与SPI)的差异、STM32的UART初始化配置与中断/DMA接收机制,并掌握了如何获取和验证GPS原始数据。下一章我们将深入解析NMEA协议,并在STM32中实现数据解析与处理。
3. NMEA协议解析与数据处理
3.1 NMEA协议基础
3.1.1 NMEA 0183协议格式与常见语句
NMEA 0183 是一种广泛应用于 GPS 模块的标准通信协议,它定义了多种以 ASCII 格式传输的语句类型,用于描述位置、时间、速度等信息。每条 NMEA 语句以 $ 开头,以 * 分隔校验和字段,并以回车换行符( \r\n )结束。NMEA 语句的通用结构如下:
$ttsss,data1,data2,...,dataN*hh
- ttsss :语句标识符,前两位为设备类型,后三位为语句类型,如
GPGGA表示全球定位系统固定数据。 - data1…dataN :逗号分隔的数据字段。
- hh :十六进制的校验和,为从
ttsss到dataN的所有字符的异或结果。
常见的 NMEA 语句包括:
| 语句类型 | 含义说明 |
|---|---|
| $GPGGA | GPS定位信息,包括时间、纬度、经度、海拔等 |
| $GPGLL | 地理位置信息,仅包含纬度、经度和定位状态 |
| $GPRMC | 推荐最小定位信息,包含速度、航向等 |
| $GPVTG | 地面速度和航向信息 |
| $GPZDA | 时间与日期信息 |
这些语句在嵌入式系统中常被用于实时定位数据的获取和处理。理解其格式和字段含义是后续数据解析的基础。
3.1.2 $GPGGA与$GPGLL等关键语句解析
以 $GPGGA 为例,它提供了 GPS 接收器的当前定位信息,其字段结构如下:
$GPGGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh
| 字段编号 | 内容说明 |
|---|---|
| 1 | UTC 时间(hhmmss.ss) |
| 2 | 纬度(度分格式,如4807.32) |
| 3 | 纬度方向(N/S) |
| 4 | 经度(度分格式,如01131.12) |
| 5 | 经度方向(E/W) |
| 6 | 定位质量指示(0=无效,1=GPS定位,2=DGPS定位等) |
| 7 | 使用的卫星数量 |
| 8 | HDOP(水平精度因子) |
| 9 | 海拔高度(单位:米) |
| 10 | 高度单位(M=米) |
| 11 | 地球椭球面相对高度(单位:米) |
| 12 | 单位标识(M) |
| 13 | 差分GPS数据龄期 |
| 14 | 差分基准站ID |
| 15 | 校验和 |
解析 $GPGGA 时,需要逐字段提取信息,并进行格式转换(如将度分格式转换为十进制度数),同时验证校验和是否正确。
而 $GPGLL 的结构更为简洁:
$GPGLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,A*hh
| 字段编号 | 内容说明 |
|---|---|
| 1 | 纬度 |
| 2 | 纬度方向 |
| 3 | 经度 |
| 4 | 经度方向 |
| 5 | UTC时间 |
| 6 | 定位状态(A=有效,V=无效) |
| 7 | 校验和 |
这两个语句的解析构成了嵌入式系统获取 GPS 信息的核心逻辑。
3.1.3 NMEA协议解析流程图
graph TD
A[开始接收NMEA数据流] --> B{是否以$开头?}
B -->|否| C[丢弃当前字符]
B -->|是| D[读取语句头]
D --> E{是否为支持的语句类型?}
E -->|否| F[跳过该语句]
E -->|是| G[读取逗号分隔的数据字段]
G --> H[计算校验和]
H --> I{校验和是否匹配?}
I -->|否| J[丢弃并记录错误]
I -->|是| K[解析字段内容]
K --> L[转换数据格式]
L --> M[保存有效定位数据]
3.2 STM32中的协议解析实现
3.2.1 数据帧的接收与缓存机制
STM32 通常通过 UART 接口与 GPS 模块通信。为了高效处理 NMEA 数据,需要设计一个缓冲机制来暂存接收到的字符,直到一个完整的 NMEA 语句接收完成。
一个常用的实现方式是使用环形缓冲区(Ring Buffer)配合中断接收机制:
#define RX_BUFFER_SIZE 128
uint8_t rx_buffer[RX_BUFFER_SIZE];
uint8_t rx_byte;
uint8_t nmea_buffer[RX_BUFFER_SIZE];
uint8_t nmea_index = 0;
void USART2_IRQHandler(void) {
if (LL_USART_IsActiveFlag_RXNE(USART2)) {
rx_byte = LL_USART_ReceiveData8(USART2);
if (rx_byte == '$') {
nmea_index = 0; // 开始新语句
}
nmea_buffer[nmea_index++] = rx_byte;
if (rx_byte == '\n') {
nmea_buffer[nmea_index] = '\0'; // 结束语句
parse_nmea_sentence(nmea_buffer); // 调用解析函数
}
if (nmea_index >= RX_BUFFER_SIZE) {
nmea_index = 0; // 防止溢出
}
}
}
代码逻辑分析:
- 当接收到一个
$字符时,表示一个新的 NMEA 语句开始,重置索引nmea_index。 - 将字符逐个存入
nmea_buffer中。 - 当遇到
\n字符时,表示一条完整的 NMEA 语句接收完毕,调用parse_nmea_sentence()函数进行解析。 - 如果缓冲区满,重置索引防止溢出。
3.2.2 字符串处理与数值提取算法
在 STM32 中,对 NMEA 语句的解析需要将字符串按逗号分割,并提取其中的数值。常用字符串处理函数包括 strtok() 和 atof() (用于浮点数转换)或 atoi() (整数转换)。
以下是一个简单的解析函数示例:
void parse_nmea_sentence(uint8_t *sentence) {
char *token = strtok((char *)sentence, ",*"); // 按逗号和*分割
int field_index = 0;
while (token != NULL) {
switch (field_index++) {
case 0:
// 语句标识符(如$GPGGA)
break;
case 1:
// 时间(UTC)
break;
case 2:
// 纬度(字符串)
break;
case 3:
// 纬度方向(N/S)
break;
case 4:
// 经度(字符串)
break;
case 5:
// 经度方向(E/W)
break;
case 6:
// 定位质量
break;
case 7:
// 使用的卫星数量
break;
case 8:
// HDOP
break;
case 9:
// 海拔高度
break;
default:
break;
}
token = strtok(NULL, ",*");
}
}
代码参数说明:
strtok():用于按指定分隔符(逗号,和*)将字符串分割成多个字段。field_index:记录当前处理的字段序号,用于定位提取对应数据。- 在每个
case分支中,可以将字段内容转换为对应的数值类型并保存到结构体中,供后续使用。
3.2.3 校验和验证与错误处理
NMEA 协议中的校验和字段用于验证数据的完整性。其计算方法是对从语句标识符开始到 * 前的所有字符进行异或(XOR)运算。
以下是一个校验和验证函数的实现:
int validate_checksum(const char *nmea, uint8_t checksum) {
uint8_t calculated = 0;
const char *p = nmea + 1; // 跳过$符号
while (*p != '*' && p < nmea + strlen(nmea)) {
calculated ^= (uint8_t)*p;
p++;
}
return calculated == checksum;
}
代码逻辑分析:
- 从
$后一个字符开始计算异或。 - 遇到
*或字符串结束时停止。 - 返回计算值与接收到的校验和是否一致的结果。
- 若不一致,可记录错误或丢弃该条语句。
错误处理建议:
- 记录错误语句及其出现频率。
- 若连续多条语句校验失败,应检查硬件连接或波特率设置。
- 可加入超时机制,防止死锁。
3.3 定位信息的逻辑处理
3.3.1 经纬度、时间与状态信息的提取
在完成协议解析后,需对提取的原始数据进行格式转换和逻辑判断,以获得可用的定位信息。
以纬度字段为例,格式为 ddmm.mmmm ,表示度分格式,需将其转换为十进制度数:
double convert_degrees_minutes(const char *deg_min_str) {
double deg_min = atof(deg_min_str);
int degrees = (int)(deg_min / 100);
double minutes = deg_min - degrees * 100;
return degrees + minutes / 60.0;
}
逻辑分析:
- 将字符串转换为浮点数。
- 分离度和分部分。
- 将分部分转换为十进制度,并加到度部分上。
此外,还需处理方向信息(N/S/E/W),例如:
double apply_direction(double value, char direction) {
if (direction == 'S' || direction == 'W') {
return -value;
}
return value;
}
时间字段处理:
UTC 时间字段格式为 hhmmss.ss ,可拆分为小时、分钟、秒:
void parse_utc_time(const char *time_str, int *hour, int *min, float *sec) {
*hour = atoi(time_str); time_str += 2;
*min = atoi(time_str); time_str += 2;
*sec = atof(time_str);
}
3.3.2 地理坐标转换与单位换算
在实际应用中,常需将经纬度转换为地心坐标系(ECEF)、UTM坐标或地图坐标。以下是一个将经纬度转换为十进制度的示例:
typedef struct {
double latitude;
double longitude;
double altitude;
} GPSData;
GPSData gps_data;
// 示例解析函数
void process_gpgga(const char **fields) {
gps_data.latitude = convert_degrees_minutes(fields[2]);
gps_data.latitude = apply_direction(gps_data.latitude, *fields[3]);
gps_data.longitude = convert_degrees_minutes(fields[4]);
gps_data.longitude = apply_direction(gps_data.longitude, *fields[5]);
gps_data.altitude = atof(fields[9]);
}
单位换算示例:
- 海拔高度单位统一为米。
- 速度单位转换:节(knots)→ km/h(1 knot = 1.852 km/h)。
- 坐标系统转换(如 WGS84 转 UTM)可使用开源库(如 Proj4)或自行实现。
本章从 NMEA 协议的基础结构入手,详细解析了常见语句的字段含义,并在 STM32 平台上实现了完整的协议解析与数据处理流程。通过环形缓冲、字符串处理、校验和验证、数据提取与格式转换等关键步骤,构建了 GPS 数据解析的完整逻辑框架,为后续上位机开发和系统集成打下了坚实基础。
4. LabVIEW上位机开发与数据可视化
在嵌入式系统与物联网应用中,上位机软件的开发不仅提升了系统交互性,也增强了数据可视化与实时监控的能力。LabVIEW(Laboratory Virtual Instrument Engineering Workbench)作为一款图形化编程平台,广泛应用于数据采集、仪器控制与系统开发领域。本章将围绕LabVIEW平台,介绍其在STM32与GPS系统中的上位机开发流程,涵盖串口通信、数据解析、可视化展示以及数据存储与导出等核心功能的实现。通过LabVIEW构建的上位机界面,用户可以直观地查看GPS定位信息、轨迹变化、速度与方向,并支持数据的本地存储与格式转换导出,为系统功能的完整性与可扩展性奠定基础。
4.1 LabVIEW编程环境概述
LabVIEW采用图形化编程语言G语言(G-Language),其基于数据流的执行机制与模块化设计思想,使得复杂系统的开发变得高效且直观。对于嵌入式通信与数据处理任务而言,LabVIEW提供了丰富的库函数与工具包,尤其在串口通信、数据可视化和文件操作方面具有显著优势。
4.1.1 LabVIEW基本结构与开发流程
LabVIEW程序由两大部分组成: 前面板(Front Panel) 和 程序框图(Block Diagram) 。
- 前面板 :用于设计用户界面,包括控件(如按钮、指示灯、图表)和显示元素。
- 程序框图 :是程序逻辑的实现部分,使用图形化节点(Node)与连线(Wire)表示数据流和控制流。
开发流程通常包括以下几个步骤:
1. 需求分析与界面设计 :确定功能模块与交互方式。
2. 程序逻辑构建 :使用函数库和结构化控制语句搭建程序流程。
3. 调试与测试 :利用探针(Probe)与调试工具检查数据流。
4. 打包与部署 :将VI(Virtual Instrument)打包为独立可执行程序或库文件。
4.1.2 串口通信模块的配置与使用
LabVIEW提供了专门的 串口通信工具包 (VISA Serial),支持与STM32等嵌入式设备进行串口通信。其核心函数包括:
| 函数名称 | 功能说明 |
|---|---|
VISA Configure Serial Port |
配置串口参数(波特率、数据位、停止位等) |
VISA Read |
从串口读取数据 |
VISA Write |
向串口发送数据 |
VISA Close |
关闭串口连接 |
示例代码(程序框图逻辑) :
[VISA Configure Serial Port]
Resource Name: "ASRL1::INSTR" // 串口号
Baud Rate: 9600
Data Bits: 8
Parity: None
Stop Bits: 1
[VISA Read]
Bytes Num: 1024 // 每次读取1024字节
逻辑分析 :
- VISA Configure Serial Port 设置串口参数,必须与STM32端一致。
- VISA Read 用于持续读取GPS模块发送的NMEA数据帧。
- 使用While循环结构实现持续监听,确保数据实时获取。
- 数据接收后可通过字符串处理函数解析并显示。
4.2 GPS数据的接收与解析
在STM32端完成GPS数据采集与串口传输后,LabVIEW作为上位机负责接收并解析NMEA协议格式的数据帧,提取关键定位信息。
4.2.1 数据帧的接收与协议解析
NMEA协议中,每条语句以 $ 开头,以 * 后跟两个十六进制字符的校验码结尾。典型语句如 $GPGGA 包含时间、纬度、经度、高度等信息。
解析流程如下 :
1. 接收完整的NMEA语句。
2. 拆分字段,验证校验码。
3. 提取关键数据并格式化输出。
[Case Structure]
Condition: 接收到的数据是否以 "$" 开头
True:
[String Subset] 截取数据帧
[Search String] 查找 "*" 位置
[Formula Node] 校验和计算
[Conditional Check] 校验是否通过
If Yes:
[Tokenize String] 拆分字段
[Select Case] 判断语句类型(GPGGA, GPGLL等)
If No:
[Error Handling] 丢弃或记录错误帧
逻辑分析 :
- String Subset 截取完整数据帧。
- Search String 定位校验码位置,便于提取和比对。
- Formula Node 中使用公式计算校验和,例如: $GPGGA,123456.00,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,* 的校验和为 47 。
- Tokenize String 将逗号分隔的字段拆分为数组,便于后续提取。
4.2.2 实时数据显示与状态监测
解析后的数据可通过LabVIEW的控件实现动态显示,例如:
- 数值显示控件(Numeric Indicator) :显示经纬度、海拔、时间。
- 字符串控件(String Indicator) :显示原始数据帧。
- 布尔指示灯(LED) :表示GPS是否定位成功(如 GPGGA 中第6字段为0表示无效定位)。
[Build Array]
Input 1: Latitude (数值)
Input 2: Longitude (数值)
Input 3: Altitude (数值)
[Waveform Chart]
Plot the above values in real time
逻辑分析 :
- 使用 Build Array 组合多个数据字段。
- 通过 Waveform Chart 实时绘制经纬度变化曲线。
- 添加状态判断逻辑,若GPS定位无效,点亮红色LED灯。
4.3 GPS数据可视化设计
数据可视化是LabVIEW的强项之一,尤其在地理信息展示方面,可通过地图控件、方向箭头、轨迹绘制等方式增强用户体验。
4.3.1 地图显示模块的实现
LabVIEW本身不内置地图控件,但可以通过 ActiveX控件集成 (如Google Maps或OpenStreetMap)实现地图显示。另一种方式是使用第三方工具包,如NI的 Report Generation Toolkit 或社区提供的 地图插件 。
步骤如下 :
1. 安装地图插件(如LabVIEW GIS Toolkit)。
2. 在前面板中放置地图控件。
3. 将经纬度数据转换为地图坐标。
4. 调用API更新地图位置。
[Map Control]
Property Node: Set Latitude and Longitude
Method: Update Map
逻辑分析 :
- 使用Property Node设置地图中心点坐标。
- 通过定时器定期更新位置,实现轨迹移动效果。
- 可叠加多个标记点,形成轨迹路径。
4.3.2 速度、方向与轨迹的图形化展示
除了地图,还可以使用以下方式展示GPS数据:
- 速度表(Meter) :实时显示当前速度。
- 方向罗盘(Compass) :指示移动方向。
- XY Graph :绘制轨迹路径,X轴为经度,Y轴为纬度。
[XY Graph]
X Data: Longitude Array
Y Data: Latitude Array
Plot: Line
逻辑分析 :
- 使用数组累积经纬度值,构建轨迹点集合。
- 每次新增坐标点后更新图形,形成动态轨迹。
- 设置图形缩放与刷新频率,保证显示流畅。
4.4 数据存储与导出功能
为了实现数据的持久化存储与后续分析,上位机应具备日志记录、文件存储与格式导出功能。
4.4.1 数据日志记录与文件存储
LabVIEW提供多种文件操作函数,支持文本、CSV、TDMS等格式的写入。
[Open/Create/Replace File]
File Path: "C:\GPS_Data\log.txt"
[Write to Text File]
Data: "$GPGGA,123456.00,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"
[Close File]
逻辑分析 :
- Open/Create/Replace File 打开或创建日志文件。
- Write to Text File 将解析后的GPS语句写入文件。
- Close File 确保数据写入磁盘,避免数据丢失。
4.4.2 支持CSV与KML格式导出
- CSV格式 :适合导入Excel或Python等工具进行分析。
- KML格式 :可导入Google Earth查看轨迹。
[Build CSV Line]
Fields: Time, Latitude, Longitude, Speed, Altitude
[Write to CSV File]
File Path: "C:\GPS_Data\track.csv"
[Build KML Header]
"<?xml version='1.0' encoding='UTF-8'?>..."
[Build KML Body]
"<coordinates>" + Longitude + "," + Latitude + ",0</coordinates>"
[Write to KML File]
File Path: "C:\GPS_Data\track.kml"
逻辑分析 :
- 使用字符串拼接构建CSV与KML格式内容。
- 在程序中添加按钮控件,触发文件导出动作。
- 提供文件路径选择对话框,提升用户交互体验。
本章小结
本章系统地介绍了基于LabVIEW平台的上位机开发流程,涵盖串口通信配置、NMEA协议解析、数据可视化设计以及数据存储与导出功能的实现。通过LabVIEW强大的图形化编程能力和丰富的函数库,能够高效构建功能完善的GPS数据监控系统。下一章将深入探讨STM32与LabVIEW之间的通信协议设计与系统整体调试优化,进一步提升系统的稳定性与扩展性。
5. 系统集成与扩展功能实现
在完成STM32端的GPS数据获取与解析、LabVIEW上位机的数据显示与可视化之后,接下来的步骤是将整个系统进行集成,并在此基础上实现一些扩展功能,如轨迹回放、地理围栏等。本章将重点讲解STM32与LabVIEW之间的通信协议设计、系统调试优化方法以及功能扩展的具体实现方式。
5.1 STM32与LabVIEW的通信协议设计
为了实现STM32与LabVIEW之间的稳定通信,需要设计一套自定义的通信协议,以确保数据结构清晰、校验机制可靠。
5.1.1 自定义通信协议的制定
协议格式如下(基于ASCII字符传输):
$STM,latitude,longitude,speed,direction,altitude,status*checksum<CR><LF>
latitude:纬度,十进制度数格式longitude:经度,十进制度数格式speed:速度,单位 km/hdirection:方向,单位度altitude:海拔,单位米status:状态信息(如定位有效/无效)checksum:校验和(异或校验)<CR><LF>:回车换行符,表示数据包结束
5.1.2 数据包结构与校验机制
校验逻辑代码示例:
// 计算校验和
uint8_t calculate_checksum(char *data, int len) {
uint8_t checksum = 0;
for(int i = 0; i < len; i++) {
checksum ^= data[i]; // 异或每一位
}
return checksum;
}
数据发送示例:
// 构造并发送数据包
void send_gps_data(float latitude, float longitude, float speed, float direction, float altitude, uint8_t status) {
char buffer[128];
sprintf(buffer, "$STM,%.6f,%.6f,%.2f,%.2f,%.2f,%d", latitude, longitude, speed, direction, altitude, status);
uint8_t checksum = calculate_checksum(buffer + 4, strlen(buffer) - 4); // 从$后开始计算
char final[150];
sprintf(final, "%s*%02X\r\n", buffer, checksum); // 添加校验和和换行符
HAL_UART_Transmit(&huart2, (uint8_t*)final, strlen(final), HAL_MAX_DELAY);
}
说明: 以上代码使用了STM32 HAL库进行串口发送,
$STM为数据包标识,*后为校验和,checksum以十六进制表示。
5.2 系统整体调试与优化
在完成协议设计后,需将STM32与LabVIEW端进行整体联调,确保通信稳定、数据准确、界面响应及时。
5.2.1 系统功能模块的联调
联调步骤:
- 使用串口调试助手(如XCOM)验证STM32是否能稳定发送协议格式数据;
- 在LabVIEW中配置串口通信模块,接收并解析STM32发送的数据;
- 使用LabVIEW的 字符串处理函数 提取字段值;
- 将提取后的数据绑定至地图、仪表盘等控件中;
- 观察数据刷新频率与显示延迟。
5.2.2 性能测试与稳定性优化
性能测试内容:
| 测试项 | 内容 | 工具 |
|---|---|---|
| 数据发送频率 | 每秒发送GPS数据包数量 | 示波器/串口调试工具 |
| 数据丢包率 | 在1分钟内接收数据包总数与丢失数量 | LabVIEW日志记录 |
| CPU占用率 | STM32主循环运行时的负载情况 | STM32CubeMonitor |
| 响应延迟 | LabVIEW接收数据到界面刷新的时间差 | 时间戳对比 |
优化策略:
- 使用DMA+中断方式接收数据,减少CPU负担;
- 设置合理的串口缓冲区大小;
- 在LabVIEW中使用队列机制处理接收数据;
- 增加重传机制(可选);
- 使用定时器控制数据发送频率。
5.3 扩展功能实现
在系统稳定运行后,可进一步实现一些扩展功能,提升系统的实用性与智能化程度。
5.3.1 轨迹回放功能的设计与实现
轨迹回放功能允许用户回溯某一时间段内的移动路径。实现方式如下:
- 数据存储 :在LabVIEW中开启数据记录功能,保存每帧GPS数据(含时间戳);
- 时间轴控件 :添加时间轴控件用于选择回放时间段;
- 数据加载与播放 :根据时间轴选择的数据区间,逐帧加载并更新地图与状态控件;
- 播放控制 :实现“播放”、“暂停”、“快进”等按钮逻辑。
LabVIEW实现流程图:
graph TD
A[开始] --> B[加载历史数据]
B --> C[初始化时间轴控件]
C --> D[用户选择时间范围]
D --> E[提取对应数据帧]
E --> F[逐帧更新地图与仪表]
F --> G{播放状态?}
G -->|是| H[延迟后继续播放下一帧]
H --> F
G -->|否| I[暂停等待]
I --> F
F --> J[结束或重新播放]
5.3.2 地理围栏功能的逻辑与触发机制
地理围栏是一种基于地理区域的警报机制。当GPS定位点进入或离开预设区域时,系统触发通知。
实现步骤:
- 用户在地图上绘制一个或多个地理围栏区域(如圆形、多边形);
- 系统实时检测当前位置是否进入围栏;
- 若触发条件成立,则弹出告警提示或发送通知;
- 可配置围栏触发方式(进入/离开/两者)。
地理围栏判断逻辑示例(圆形):
def is_inside_geofence(lat, lon, center_lat, center_lon, radius_km):
# 使用Haversine公式计算两点之间的距离
R = 6371 # 地球半径,单位km
dlat = math.radians(lat - center_lat)
dlon = math.radians(lon - center_lon)
a = math.sin(dlat/2)**2 + math.cos(math.radians(center_lat)) * math.cos(math.radians(lat)) * math.sin(dlon/2)**2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
distance = R * c
return distance <= radius_km
说明: 此函数返回布尔值,表示当前位置是否在指定围栏范围内。可在LabVIEW中通过调用DLL或使用Python脚本节点实现。
(本章后续内容将继续探讨项目总结与未来发展方向,敬请期待)
简介:本项目为一个结合STM32嵌入式系统与LabVIEW上位机的GPS定位系统,涵盖硬件开发与图形化界面设计。STM32作为主控芯片负责接收并解析GPS模块数据,LabVIEW用于构建可视化界面以实时显示位置信息。项目已实现基础数据通信与展示功能,后续可扩展实时追踪、轨迹回放、地理围栏等功能,适用于物联网、无人机、车辆监控等应用场景。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐




所有评论(0)