问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

STM32读取GPS数据并在LCD上显示经纬度

创作时间:
2025-01-22 04:28:35
作者:
@小白创作中心

STM32读取GPS数据并在LCD上显示经纬度

GPS(全球定位系统)用于检测地球上任何位置的纬度和经度,具有精确的UTC时间(协调世界时)。该设备每秒从卫星接收坐标,包括时间和日期。GPS提供了很高的准确性,并且还提供了位置坐标以外的其他数据。

在本教程中,我们将GPS模块与STM32F103C8微控制器连接,以查找位置坐标并将其显示在16x2 LCD显示器上。

所需组件

  • STM32F103C8 微控制器
  • GPS模块
  • 16x2 液晶显示屏
  • 面包板
  • 连接线

GPS模块

这是一个 GY-NEO6MV2 XM37-1612 GPS模块。这个GPS模块有四个引脚+5V,GND,TXD和RXD。它使用串行引脚进行通信,可以轻松连接到STM32F103C8的串行端口。

GPS模块以NMEA格式发送数据(见下图)。NMEA格式由几个句子组成,其中我们只需要一个句子。这句话从**$GPGGA开始,包含了坐标、时间等有用的信息。这个GPGGA被称为全球定位系统固定数据**。

下面是一个示例 $GPGGA 字符串及其描述:

**$GPGGA,104534.000,7791.0381,N,06727.4434,E,1,08,0.9,510.4,M,43.9,M,,47*

$GPGGA,HHMMSS.SSS,latitude,N,longitude,E,FQ,NOS,HDP,altitude,M,height,M,,checksum data

但在本教程中,我们使用的是TinyGPSPlusGPS库,它从NMEA语句中提取所有必需的信息,我们只需要编写一行简单的代码来获取纬度和经度,我们将在本教程后面看到。

STM32F103C8的引脚

STM32F103C8 (BLUE PILL) USART串行通信端口如下图所示。这些是蓝色的,具有(PA9-TX1、PA10-RX1、PA2-TX2、PA3-RX2、PB10-TX3、PB11-RX3)。它有三个这样的沟通渠道。

电路图和连接

GPS模块与STM32F103C8电路连接

GPS模块
STM32F103C8
接收端
PA9 (TX1)
发送端
PA10 (RX1)
+5V
+5V
地线
地线

16x2 LCD 和 STM32F103C8 之间的连接

LCD 引脚号
LCD 引脚名称
STM32 引脚名称
1
接地 (Gnd)
地面 (G)
2
虚拟控制中心
5V
3
VEE
电位器中心的引脚
4
寄存器选择 (RS)
PB11
5
读/写 (RW)
地面 (G)
6
启用(EN)
PB10
7
数据位 0 (DB0)
无连接 (NC)
8
数据位 1 (DB1)
无连接 (NC)
9
数据位 2 (DB2)
无连接 (NC)
10
数据位 3 (DB3)
无连接 (NC)
11
数据位 4 (DB4)
PB0
12
数据位 5 (DB5)
PB1
13
数据位 6 (DB6)
PC13
14
数据位 7 (DB7)
PC14
15
LED正极
5V
16
LED负极
地面 (G)

整个设置如下所示:

为 GPS模块接口编程STM32F103C8

本项目末尾给出了使用STM32使用GPS模块查找位置的完整程序。STM32F103C8可以使用Arduino IDE进行编程,只需通过USB端口将其连接到PC。确保在上传代码时移除引脚TX和RX,并在上传后连接。

要将GPS与STM32连接,首先我们必须从GitHub链接TinyGPSPlus下载一个库。下载库后,可以通过Sketch -> Include Library -> Add .zip Library将其包含在Arduino IDE中。相同的库可用于将GPS与Arduino连接。

所以首先包括必要的库文件并为16x2 LCD定义引脚:

#include <LiquidCrystal.h>
#include <TinyGPS++.h>
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

然后创建一个名为gps的对象,属于TinyGPSPlus类。

TinyGPSPlus gps;

接下来在无效设置中,使用Serial1.begin(9600)开始与GPS模块的串行通信。Serial1用作STM32F103C8的Serial 1端口(引脚-PA9、PA10)。

Serial1.begin(9600);

然后显示欢迎消息一段时间。

lcd.begin(16,2);
lcd.print("Circuit Digest");
lcd.setCursor(0,1);
lcd.print("STM32 with GPS");
delay(4000);
lcd.clear();

接下来在void loop()中,我们从GPS接收纬度和经度,并检查接收到的数据是否有效,并在串口监视器和LCD中显示信息。

检查可用的位置数据是否有效

loc_valid = gps.location.isValid();

接收纬度数据

lat_val = gps.location.lat();

接收经度数据

lng_val= gps.location.lng();

如果接收到无效数据,它会在串口监视器中显示“*”,并在LCD中显示“waiting”。

if (!loc_valid)
{
  lcd.print("Waiting");
  Serial.print("Latitude : ");
  Serial.println("*****");
  Serial.print("Longitude : ");
  Serial.println("*****");
  delay(4000);
  lcd.clear();
}

如果收到有效数据,纬度和经度将显示在串口监视器和LCD显示屏上。

lcd.clear();
Serial.println("GPS READING: ");
Serial.print("Latitude : ");
Serial.println(lat_val, 6);
lcd.setCursor(0,0);
lcd.print("LAT:");
lcd.print(lat_val,6);
Serial.print("Longitude : ");
Serial.println(lng_val, 6);
lcd.setCursor(0,1);
lcd.print("LONG:");
lcd.print(lng_val,6);
delay(4000);

以下函数提供读取数据的延迟。它一直在串口上寻找数据。

static void GPSDelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    while (Serial1.available())
    gps.encode(Serial1.read());
  } while (millis() - start < ms);
}

使用 GPS 和 STM32 查找经纬度

建立设置并上传代码后,确保将GPS模块放置在空旷区域以快速接收信号。有时需要几分钟才能收到信号,因此请稍等片刻。当GPS模块开始接收信号时,LED将开始闪烁,并且位置坐标将显示在LCD显示屏上。

您可以使用谷歌地图验证位置的纬度和经度。只需在打开GPS的情况下转到Google地图,然后单击蓝点。它将显示带有纬度和经度的地址,如下图所示

下面给出了完整的代码:

#include <LiquidCrystal.h>     //Library for using LCD display functions                      
#include <TinyGPS++.h>         //Library for using GPS functions
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14;  //LCD pins connected with STM32
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
TinyGPSPlus gps;               //Object gps for class TinyGPSPlus
void setup()
{
  Serial1.begin(9600);         //Begins Serial comunication at Serial Port 1 at 9600 baudrate
  lcd.begin(16,2);             //Sets display in 16x2 Mode
  lcd.print("Circuit Digest");
  lcd.setCursor(0,1);
  lcd.print("STM32 with GPS");
  delay(4000);
  lcd.clear();      
}
void loop()
{
  GPSDelay(1000);
  unsigned long start;
  double lat_val, lng_val;
  bool loc_valid;
  lat_val = gps.location.lat();        //Gets the latitude
  loc_valid = gps.location.isValid(); 
  lng_val = gps.location.lng();        //Gets the longitude
 
  if (!loc_valid)                     //Excecutes when invalid data is received from GPS
  {
    lcd.print("Waiting");
    Serial.print("Latitude : ");
    Serial.println("*****");
    Serial.print("Longitude : ");
    Serial.println("*****");
    delay(4000);
    lcd.clear();
  }
  else                              //Excutes when valid data is received from GPS
  {
    lcd.clear();
    
    Serial.println("GPS READING: ");
   
    Serial.print("Latitude : ");
    Serial.println(lat_val, 6);   //Prints latitude at Serial Monitor
   
    lcd.setCursor(0,0);
    lcd.print("LAT:");
    lcd.print(lat_val,6);         //Prints latitude at LCD display
    Serial.print("Longitude : ");
    Serial.println(lng_val, 6);   //Prints longitude at Serial monitor
    lcd.setCursor(0,1);
    lcd.print("LONG:");
    lcd.print(lng_val,6);          //Prints longitude at LCD display
    delay(4000);
  }
}
static void GPSDelay(unsigned long ms)          //Delay for receiving data from GPS
{
  unsigned long start = millis();
  do
  {
    while (Serial1.available()) 
    gps.encode(Serial1.read());
  } while (millis() - start < ms);
}  
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号