如何用STM32读取Adafruit GPS数据并发送至树莓派3?
解决STM32 Nucleo-F334R8 GPS数据无法发送到树莓派的问题
首先,先把你的问题和代码贴出来方便参考:
我使用STM32 Nucleo-F334R8开发板与Adafruit Ultimate GPS Breakout V3模块,先尝试通过串口用Putty读取GPS数据,最终目标是在F334R8上获取GPS数据后,通过串口发送至Raspberry Pi 3。目前在线使用Mbed Compiler开发时遇到诸多问题,附上代码后发现树莓派控制台无数据接收,恳请技术支持。
你的代码:
#include "mbed.h" #include "MTK3339.h" static int waitData = 0; static MTK3339 gps(D8, D2); static float latitude = 0; static float longitude = 0; Serial rasp(D15, D14); // D15 = RX, D14 = TX static void dataAvailable() { waitData |= gps.getAvailableDataType(); } int main(void) { gps.start(&dataAvailable, (MTK3339::NmeaGga|MTK3339::NmeaVtg)); while(1) { while(waitData == 0); if ((waitData & MTK3339::NmeaGga) != 0) { waitData &= ~(MTK3339::NmeaGga); latitude = gps.getLatitudeAsDegrees(); longitude = gps.getLongitudeAsDegrees(); //printf("%f,%f\n", gps.getLatitudeAsDegrees(), gps.getLongitudeAsDegrees()); //printf("lat = %f, long = %f",latitude, longitude); rasp.printf("%f\n", latitude); } waitData &= (MTK3339::NmeaGga|MTK3339::NmeaVtg); } }
接下来一步步排查和解决问题:
一、先确认GPS模块是否正常给Nucleo输出数据
这是基础,如果Nucleo都没拿到GPS数据,树莓派肯定收不到:
- 先做本地调试:把代码里的
rasp.printf换成printf,然后用Putty连接Nucleo的USB虚拟调试串口(波特率默认9600),看能不能打印出经纬度。如果没输出:- 检查接线:Adafruit GPS的TX要接Nucleo的D8(你的代码里gps对象的RX引脚),GPS的RX接Nucleo的D2(gps的TX引脚),别搞反了!另外VCC接3.3V(Nucleo的3.3V引脚),GND必须和开发板共地。
- 确认波特率:MTK3339默认是9600波特率,你可以在初始化gps时明确指定,改成
static MTK3339 gps(D8, D2, 9600);避免库默认值不一致。 - 给GPS足够定位时间:第一次定位需要在开阔地方(窗边或户外)等几分钟,看模块的LED灯——定位成功后会每秒闪一次,未定位是每10秒闪一次。
二、确认Nucleo和树莓派的串口通信本身正常
跳过GPS,先测试串口链路是否通畅:
- 写个极简测试代码:
#include "mbed.h" Serial rasp(D15, D14); int main() { rasp.baud(9600); // 和树莓派端波特率保持一致 while(1) { rasp.printf("Hello from Nucleo!\n"); thread_sleep_for(1000); // 每秒发一次测试消息 } } - 树莓派端操作:
- 先通过
raspi-config启用硬件UART:进入Interface Options → Serial,关掉"Serial port login shell",打开"Serial port hardware",重启树莓派。 - 用
screen /dev/ttyAMA0 9600或者minicom打开串口,看能不能收到"Hello from Nucleo!"。如果收不到:- 检查接线:Nucleo的D14(TX)要接树莓派的RX(GPIO15),D15(RX)接树莓派的TX(GPIO14),别接反!
- 确认树莓派串口设备:如果禁用了蓝牙,可能是
/dev/ttyS0,可以用ls /dev/tty*查看可用的串口设备。
- 先通过
三、修改你的GPS代码,提升可靠性
解决上面两个环节后,再优化你的代码:
- 给rasp串口明确设置波特率,在main开头加
rasp.baud(9600);,默认波特率可能不匹配导致通信失败。 - 增加调试输出,确认GPS数据是否被触发:
static void dataAvailable() { waitData |= gps.getAvailableDataType(); printf("GPS data received, type: %d\n", waitData); // 调试用,看回调是否触发 } - 过滤无效GPS数据:GPS未定位时会输出0,这时候没必要发去树莓派,加个判断:
if ((waitData & MTK3339::NmeaGga) != 0) { waitData &= ~(MTK3339::NmeaGga); latitude = gps.getLatitudeAsDegrees(); longitude = gps.getLongitudeAsDegrees(); // 只发送有效定位数据 if (latitude != 0.0f && longitude != 0.0f) { rasp.printf("Lat: %f, Lon: %f\n", latitude, longitude); } else { rasp.printf("Waiting for GPS fix...\n"); } } - 去掉代码里的
waitData &= (MTK3339::NmeaGga|MTK3339::NmeaVtg);,这行逻辑有问题,会保留未处理的Vtg标志,导致循环一直触发却没有对应处理逻辑,反而干扰程序运行。
修改后的完整代码:
#include "mbed.h" #include "MTK3339.h" static int waitData = 0; static MTK3339 gps(D8, D2, 9600); // 明确指定波特率 static float latitude = 0; static float longitude = 0; Serial rasp(D15, D14); // D15 = RX, D14 = TX static void dataAvailable() { waitData |= gps.getAvailableDataType(); printf("GPS data callback triggered!\n"); // 调试用 } int main(void) { rasp.baud(9600); // 树莓派串口波特率匹配 gps.start(&dataAvailable, MTK3339::NmeaGga); // 只启用GGA,减少数据量 while(1) { while(waitData == 0); // 等待GPS数据 if ((waitData & MTK3339::NmeaGga) != 0) { waitData &= ~(MTK3339::NmeaGga); // 清除GGA标志 latitude = gps.getLatitudeAsDegrees(); longitude = gps.getLongitudeAsDegrees(); // 发送有效数据到树莓派 if (latitude != 0.0f && longitude != 0.0f) { rasp.printf("%f,%f\n", latitude, longitude); printf("Sent to Pi: %f, %f\n", latitude, longitude); // 本地调试 } else { rasp.printf("No GPS fix yet\n"); printf("Waiting for fix...\n"); } } } }
按照这个步骤一步步排查,应该能解决树莓派收不到数据的问题。
内容的提问来源于stack exchange,提问作者Rosbibif
相关产品推荐
相关产品推荐

