---
title: GPS 接收器的原理與應用—PART7
description: "**作者：Bird** 在上一篇文章[【Maker 電子學】GPS 接收器的原理…"
url: "https://makerpro.cc/docs/gps-receiver-principles-and-application-part7/"
updated: "2025-05-05"
category: GPS接收器
---

# GPS 接收器的原理與應用—PART7

**作者：Bird**

在上一篇文章[【Maker 電子學】GPS 接收器的原理與應用—PART6](https://makerpro.cc/2022/05/gps-receiver-principles-and-application-part6/) 中，我們將 u-blox NEO-7M GPS 接收器模組透過 USB 接到 PC 上，用 terminal 程式直接觀察在真實環境中收到的訊號、解出來的資料，我們也說明了 $GPGSA、$GPGGA、$GPGLL、$GPRMC 等幾個最重要的定位訊息。

這一回我們要試著將 GPS 接收器透過 UART 連接到像 Arduino 這樣的小系統上，來使用 GPS 的訊號。

### **連接 ESP8266**

我們選用 ESP8266 來當作這次實驗的主控晶片。除了 Arduino 原生的 ATmega328p 之外，ESP8266 可能是 Arduino 平台上數一數二流行的晶片，它有 Wi-Fi 的功能，又有足夠大的 flash 和 RAM，處理器的速度也夠快，可以做很多 ATmega328p 做不到或做起來很吃力的事。

不過 ESP8266 最大的缺點就是 I/O 接腳太少，雖然晶片本身提供了 17 支的 GPIO，但 GPIO 0、GPIO 2、GPIO 15 用來控制啟動狀態，使用上有一些限制，而 GPIO 6-11 則用來連接存放程式碼的 SPI flash memory，其中 GPIO 7-10 是 data bits；如果你讓 SPI flash 跑在 4-bit 模式下，這四支腳都要用到；如果你把 SPI flash 設成 1-bit 模式，就可以空出 GPIO 8-10 三支腳出來當 GPIO 使用。

ESP8266 晶片本人有兩組硬體的 UART，但嚴格來說只有一組半。UART 0 有完整的 RxD/TxD 接腳，甚至還有硬體 flow control 用的 RTS/CTS 接腳，但 UART 1 只有一支 TxD 接腳，也就是說 UART 1 只能發不能收。

UART0 的 RxD/TxD 分別在 GPIO 3 和 GPIO 1 上，而 UART 1 的 TxD 則是 GPIO 2。在很多 ESP8266 的開發板上，會把 GPIO13 和 GPIO15 標示成 UART2，這裡其實有點小小的誤會。GPIO13 和 GPIO15 其實是 UART0 的另一組可以設定的接腳，也就是說當你用了 GPIO13/15，GPIO1/GPIO3 就不能當 UART 用了。

 ![](http://makerpro.cc/wp-content/uploads/2022/05/1.1-2.png)

（圖片來源：Bird 提供）

當我們在 Arduino 裡面使用 Serial.begin() 來起始 serial 物件時，使用的就是預設在 GPIO1/3 上面的 serial port。如果要用第二組接腳 GPIO13/15，只要呼叫 Serial.swap()，就可以把 UART0 的接腳換到 GPIO13/15 上，但這時 GPIO1/3 上就沒有 UART 訊號了，而一般的 ESP8266 開發板像 NodeMCU 或是 WeMos D1，都是將 UART-USB 橋接晶片接在 GPIO1/3 上，以便透過 USB 可以燒錄 firmware，因此如果將 UART0 的接腳移走，我們雖然可以在別的接腳上使用 UART，但就失去了透過 USB 來觀察 UART0 輸出的方便。

我們想要將 GPS 模組的輸出連接到 ESP8266 上，又希望可以繼續用 Serial.print() 等方便的工具來觀察 ESP8266 的工作狀態，但 UART1 又只有 TxD，無法接收 GPS 的資料。

該怎麼辦呢？

### **軟體 Serial 界面**

Arduino 裡有一個叫做 SoftwareSerial 的函式庫，可以在任意的 GPIO 接腳上用軟體方式模擬 serial 界面。原來的這個函式庫只能給 AVR 架構的 Arduino 硬體使用，在 ESP8266 上直接使用 SoftwareSerial 會遭遇一些奇奇怪怪的問題。幸好後來有一個叫做 EspSoftwareSerial 的函式庫，是專門移植給 ESP8266/ESP32 使用的 SoftwareSerial。

我們可以將 SoftwareSerial 出來的 UART 界面拿來連接 GPS 接收器，而將原來的硬體 UART 保留給 debug 界面。

SoftwareSerial 用起來很簡單：

 #include &lt;SoftwareSerial.h&gt; // 帶入 library 的 header file
 SoftwareSerial SWSerial (rxPin, txPin); // 初始化 SoftwareSerial 物件

SoftwareSerial 物件繼承了 Serial 物件大部分的 property 跟 method，因此用起來的方法就跟 SErial 物件一樣。

我們先來寫個小程式：

  #include int serialChar; SoftwareSerial SWSerial(13,15); // RxD - 13, TxD - 15 for GPS receiver void setup() { SWSerial.begin(9600); // Neo-7m module defualt UART baudrate Serial.begin(115200); // original defualt UART } void loop() { if(SWSerial.available()&gt;0) // check if there is data to be read { serialChar = SWSerial.read(); // read 1 character from SWSerial Serial.print((char)serialChar); // put it to Serial } }

這個程式很簡單，它不斷地從 SoftwareSerial 模擬的 UART 界面上將資料讀進來，然後送到硬體的 UART 0 上。我們在程式中宣告的軟體 UART 接腳是 RxD 用 GPIO 13，TxD 用 GPIO 15。

我們以 ESP8266 的開發板 NodeMCU 爲例，用四根線將 NodeMCU 跟 Neo-7m GPS 接收器模組連接起來：

 ![](http://makerpro.cc/wp-content/uploads/2022/05/2.1-2.png)

（圖片來源：Bird 提供）

 ![](http://makerpro.cc/wp-content/uploads/2022/05/3.1-2.png)

（圖片來源：Bird 提供）

如果連接正確，當我們把 NodeMCU 的 USB 插上電腦，NodeMCU 就會對 Neo-7m 模組供電，我們就會看到 Neo-7m 板子上的紅色 LED 亮起來。

接下來，在 Arduino 環境中將上面那組程式碼燒到 ESP8266 裡面之後，再用 Arduino 內建的 Serial Monitor 觀察 ESP8266 所連接的 serial port，應該就會看到來自 Neo-7m 模組的訊息，像這樣：

 ![](http://makerpro.cc/wp-content/uploads/2022/05/4-4.png)

（圖片來源：Bird 提供）

嗯我們又看到了 99.99 的 DOP 了，因爲我做這個實驗的時候是在室內，GPS 接收器收不到任何訊號，所以就如我們上一回所聊的，$GPGSA 後面有一大排逗點，一顆有效的衛星編號都沒有。

從 UART 拿到 GPS 接收器送來的 NMEA 資料後，接下來就可以去 parse 它，拿出我們需要用的數據來使用了。就如我們上次聊過的，如果你只需要經緯度跟時間，就可以抓 $GPGLL；如果需要經緯度跟速度，就要抓 $GPRMC；如果想要知道現在使用的衛星編號、定位精度，就要抓 $GPGSA…。

NMEA-0183 的格式要用 Arduino 的字串處理功能來 parse 並不難，因爲它的格式很單純：又特定字串開頭標示不同的資訊，而每一行內的資訊都以逗點分隔各欄位，所以如果你不需要計算 checksum，其實可以很容易用 strtok() 之類的函數將字串拆解後就拿到所需的資訊。

當然，寫程式如果能站在巨人的肩膀上，開發的速度往往會更快。Arduino 上已經有很多前人寫好的 GPS NMEA parser 函式庫可以使用，常用的像是 MicroNMEA、TinyGPS 等，只要宣告好物件、將有 NMEA 資料流的 UART 餵給 parser，就可以輕鬆拿出所需的特定欄位。這個部分就留給讀者當作進一步研究的題目了。

### **最準的時鐘**

在結束這個系列之前，我想再提一件事。除了定位之外，GPS 還有一個異常強大的功能：時鐘。

GPS 接收器上的時鐘在捕獲 GPS 衛星訊號之後，會與 GPS 衛星上的原子鐘同步，因此在持續有 GPS 訊號存在的狀況下，它所輸出的時間精度就跟衛星上的原子鐘一樣。GPS 上的原子鐘有極高的精確度，誤差大概在數千億甚至上兆分之一的等級，也就是三千多年才會有一秒的誤差。

你只要透過 GPS 接收器捕獲 GPS 衛星，你就有一個跟 GPS 衛星上的原子鐘一樣精確的時鐘。更棒的是，不管你在地球的哪個角落，只要收得到 GPS 衛星訊號，這個時鐘就是同步的。在手機通訊的技術進入 3G 時代之後，由於 CDMA 調變技術需要在不同的基地台之間有精確的時間同步，基地台之間需要一個一致的、同步的時脈訊號，因此在 3G 時代乃至於後來的 4G、5G 系統，基地台都使用 GPS 訊號來同步。

在 Neo-7m GPS 接收器模組的排針上有一個訊號叫做 PPS，它的意思是「pulse per second」，也就是一秒一次的方波。接收器捕獲 GPS 訊號後，PPS 上就會開始輸出這個一秒一次的方波，不過這個 PPS 訊號的精度跟定位精度一樣，都會受到電磁波傳遞延遲、訊號衰減等不確定因素的影響，它的精確度大概在十幾 ns 甚至數百 ns 左右，但它的不準確是以「jitter」的形式存在，長期來看它的準確度仍然會接近原子鐘本身的精確度。

### **小結**

我們花了七次的篇幅，從 GPS 的技術、原理開始講起，順便聊了一些展頻通訊的技術，以及 GPS 的編碼、導航電文的格式等，一直到示範如何使用實際的 GPS 接收器。希望這一次關於 GPS 的系列文章對於讀者們往後使用 GPS 時，能有一些幫助。

（責任編輯：賴佩萱）
