stm32单片机 北斗GPS 定位 vb上位机显示。 蓝牙主从级通信。 主单片机获取GPS北斗模块定位信息后,通过蓝牙发送给从模块。 从蓝牙模块,从模块通过串口讲定位信息发送给vb上位机。 上位机实时显示位置信息。 基本接线信息,相关原理已经包含在资料内。

最近在捣鼓一个基于STM32的北斗/GPS定位项目,核心功能是通过蓝牙主从机把定位数据传到VB开发的上位机显示。整个过程踩了不少坑,这里把关键实现点梳理下,顺便分享些实战代码。

先说硬件架构:主控用的STM32F103C8T6,挂载中科微的ATGM332D双模定位模块(同时支持北斗和GPS)。蓝牙模块是汇承的HC-05主从一体模块,这里需要特别注意主从模式配置——主机焊跳线进AT指令模式改角色,从机保持默认就行。

stm32单片机 北斗GPS 定位 vb上位机显示。 蓝牙主从级通信。 主单片机获取GPS北斗模块定位信息后,通过蓝牙发送给从模块。 从蓝牙模块,从模块通过串口讲定位信息发送给vb上位机。 上位机实时显示位置信息。 基本接线信息,相关原理已经包含在资料内。

主控端的GPS数据解析是关键。定位模块通过串口2发送NMEA协议数据,需要实时抓取GPRMC语句。代码里用了环形缓冲区处理串口接收:

//串口中断接收回调
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
    if(huart->Instance == USART2){
        gpsBuffer[rxCounter++] = rxData;
        if(rxCounter >= BUFFER_SIZE) rxCounter = 0;
        HAL_UART_Receive_IT(&huart2, &rxData, 1);
    }
}

解析部分用状态机处理效率更高。当检测到$GPRMC头时开始记录,遇到星号*进入校验计算阶段。提取出的经纬度数据需要做格式转换:

//纬度格式转换示例
double convert_coordinate(char *data, char direction){
    double minutes = atof(data+2);
    double degrees = atoi(data)/100;
    double decimal_deg = degrees + minutes/60.0;
    return (direction == 'S' || direction == 'W') ? -decimal_deg : decimal_deg;
}

蓝牙传输协议自己定了简单格式:$POS,纬度,经度,速度,校验和\r\n。主机会每1秒通过SPI接口读取HC-05状态,确认连接正常后发送数据包。这里用了CRC8校验防止传输错误:

uint8_t crc8(const uint8_t *data, size_t len){
    uint8_t crc = 0x00;
    while(len--){
        crc ^= *data++;
        for(uint8_t i=0; i<8; i++) 
            crc = (crc & 0x80) ? (crc << 1)^0x07 : crc << 1;
    }
    return crc;
}

从机端的VB上位机用SerialPort控件实现数据接收。这里有个坑点——.NET的串口缓存机制可能导致数据粘包,需要做报文分割:

Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    Dim buffer As String = SerialPort1.ReadExisting()
    Me.Invoke(Sub()
                 rxBuffer.Append(buffer)
                 Dim packets As String() = rxBuffer.ToString().Split("$"c)
                 For Each packet In packets
                     If packet.StartsWith("POS,") AndAlso packet.Contains("*") Then
                         ParsePacket(packet)
                     End If
                 Next
             End Sub)
End Sub

地图显示用的GMap.NET控件,需要特别注意坐标系转换。国内地图建议使用GCJ-02加密算法:

Private Function Wgs84ToGcj02(lat As Double, lng As Double) As PointLatLng
    '...坐标系转换算法实现...
    Return New PointLatLng(calcLat, calcLng)
End Function

调试时发现蓝牙传输距离影响稳定性,后来加了信号强度检测。当RSSI低于-85dBm时触发预警,上位机显示红色边框。实际测试在办公楼环境下,10米内传输稳定,超过15米开始出现丢包。

完整项目里还做了历史轨迹存储功能,用的SQLite本地数据库。有个优化点是采用WAL写入模式,避免界面卡顿:

Using cmd As New SQLiteCommand("PRAGMA journal_mode=WAL;", conn)
    cmd.ExecuteNonQuery()
End Using

这个项目最麻烦的部分其实是多设备时间同步。后来在数据包里加入了GPS的UTC时间戳,上位机用NTP服务器做时间校准才算解决。下次准备尝试加入LORA远传模块,把传输距离扩展到公里级。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐