跳轉至內容

Hempl/UART

來自 Wikibooks,開放世界中的開放書籍

通用非同步收發傳輸器電路或簡稱 UART(發音為“you art”)是用於序列通訊的更常見介面之一。一些計算機,例如 IBM PC,使用稱為 UART 的積體電路將字元轉換為非同步序列形式,並從中轉換。透過“序列”,我們的意思是資料一次傳輸一位。

該電路是推薦標準 232(簡稱 RS-232)的基礎,該標準還定義了 IBM PC 中的物理外部 COM 埠。RS-232 的最新修訂版是 1997 年完成的 EIA RS-232。

近年來,PC 已經失去了 RS-232 埠(可能只是外部),取而代之的是 USB,但 RS-232 仍在廣泛使用,包括許多變體,從工業中使用的 RS-485 到太空站中使用的 SpaceWire。在其更簡單的形式中,它目前在嵌入式行業中被廣泛採用。

為了更多地瞭解 UART 電路和 RS-232,讓我們回顧一下過去。序列傳輸歷史悠久,誕生於第一臺電傳打字機 (TTY)。電傳打字機從 1914 年一直使用到最近,最後一家生產 TTY 的公司於 1990 年關閉,而據報道它們在最近幾年用於航空公司公告,並且使用的許多術語都來自 TTY 世界。例如,Mark 和 Space 是描述電傳打字機電路中邏輯電平的術語。波特率或符號率是序列連線的速度,它基於機電電傳打字機的速率的倍數。

如今,儘管它在個人電腦中變得越來越不常見,但它仍然是微控制器 (MCU) 上最常見的外設之一,用於與外部裝置和系統通訊,與板載序列裝置通訊或在板之間、盒之間或嵌入式板與具有 RS-232 埠的 PC 之間建立連線。

RS-232 全域性指定

  • 佈線
  • 訊號電壓
  • 訊號功能
  • 訊號時序
  • 資訊交換協議
  • UART 配置

我們將從微控制器的角度出發,檢查以上所有要點。

UART 是一個全雙工通訊通道,在非同步模式下,每條線路在其主要功能方面都獨立於其他線路。RX 引腳可以接收資料,而與 TX 引腳的活動無關,反之亦然。

通常,來自微控制器的 UART 線路在 3 線配置(未實現流控制)中標記為 TX、RX、GND(分別表示傳送、接收和接地),以及 5 線 TX、RX、GND、RTS、CTS,帶有硬體流控制,其中 RTS 代表請求傳送,CTS 代表清除傳送。

訊號被描述為正電壓來通訊邏輯值 0,稱為“Mark”,以及負電壓來通訊邏輯值 1,稱為“Space”。

這些訊號的電流和電壓通常太弱,無法從微控制器輸出,並且標準規定應使用 ±5V 至 ±15V 的電壓,導線長度為 10 米,那麼如何與輸出 ±3V 且電流非常低的 UART 線路介面呢?

Mizar32 的序列埠 UART 擴充套件板上的 MAX232 晶片是一個 TTL 到 RS-232 電平轉換器,它將電壓從 ±3V 提升到 ±15V。

訊號時序以波特率衡量,其中二進位制通訊中一個波特率對應於每秒一位,因此在 9600 波特率下,我們每秒有 9600 位,每個位元的時間範圍為 104 μs 1/9600。通常,時鐘將以波特率的 16 倍執行,以允許接收器進行中心取樣。

資料交換協議非常簡單。

資料包以起始位開頭,該起始位是邏輯 0,首先發送/接收。在軟體方面,此位很重要,因為我們可以輪詢 RX 引腳以獲取此位,以表明資料包即將到來。資料位或有效負載可能包含或不包含奇偶校驗位,然後資料包以邏輯 1、一個或兩個停止位結束。

0 開始)
XXXXXXX (7 或 8 位資料)
X 1 個可選的奇偶校驗位
1 一個或兩個停止位

請注意,位元組的最低有效位首先發送,而我們通常將數字的 LSB 寫在右側,因此我們應該從右到左讀取它。

關於配置引數,常見配置(通常儲存在暫存器中)是 9600/8n1,這意味著對於序列埠:9600 波特率、8 位資料、無奇偶校驗位、1 個停止位。顯然,兩個 UART 都應該以相同的方式配置才能進行通訊。

硬體檢視

[編輯 | 編輯原始碼]

Mizar32 在匯流排聯結器上提供了兩個序列埠,UART0 在右側總線上,UART1 在左側總線上。UART0 只有資料 (TXD、RXD) 和硬體流控制 (CTS、RTS) 訊號,而 UART1 還具有調變解調器控制訊號 (DSR、DTR、DCD、RI)。

在 Atmel 文件中,這些被稱為“USART”,因為它們也可以被程式設計為同步模式以用作額外的 SPI 埠。

匯流排引腳
訊號 GPIO 匯流排引腳 PicoLisp
UART0_RX PA0 BUS4 引腳 3 'PA_0
UART0_TX PA1 BUS4 引腳 4 'PA_1
UART0_RTS PA3 BUS4 引腳 5 'PA_3
UART0_CTS PA4 BUS4 引腳 6 'PA_4
UART1_RX PA5 BUS3 引腳 3 'PA_5
UART1_TX PA6 BUS3 引腳 4 'PA_6
UART1_DCD PB23 BUS3 引腳 5 'PB_23
UART1_DSR PB24 BUS3 引腳 6 'PB_24
UART1_DTR PB25 BUS3 引腳 7 'PB_25
UART1_RI PB26 BUS3 引腳 8 'PB_26
UART1_CTS PA9 BUS3 引腳 9 'PA_9
UART1_RTS PA8 BUS3 引腳 10 'PA_8

RS232/RS485 序列埠擴充套件板

[編輯 | 編輯原始碼]

擴充套件序列埠板有兩個撥碼開關組,DIP1 和 DIP2,用於在 RS232 和 RS485 模式之間切換。

RS232 模式

[編輯 | 編輯原始碼]

如果 DIP1 的所有開關都向上,DIP2 的所有開關都向下,它會將匯流排訊號轉換為其 DB9 母頭聯結器 J7 上的 RS232 電平。此聯結器配置為 DCE 裝置,這與 PC 序列埠相反,因此與 PC 通訊的電纜應在每端連線相同的引腳;不需要空閒調變解調器電纜。將其他 DCE 裝置(如調變解調器或 GPS 接收器)連線到它需要互換 TX 和 RX,例如使用空閒調變解調器電纜。

請注意,在序列埠的 1.1.1 版本中,CTS 和 RTS 引腳錯誤地互換了,因此要獲得正確的連線,您需要修改電路板或電纜。但是,eLua 中的硬體流控制尚未工作,因此沒有區別;請參閱 問題 #29

訊號 匯流排引腳 UART 模組
修訂版 1.0
DB-9F 引腳
UART 模組
修訂版 1.1.1
DB-9F 引腳
UART0_RX P5 引腳 3 引腳 3(輸入) 引腳 3(輸入)
UART0_TX P5 引腳 4 引腳 2(輸出) 引腳 2(輸出)
UART0_RTS P5 引腳 5 引腳 8(輸出) 引腳 7(輸出)
UART0_CTS P5 引腳 6 引腳 7(輸入) 引腳 8(輸入)
GND 各種 引腳 5 引腳 5

RS485 模式

[編輯 | 編輯原始碼]

如果 DIP1 的所有開關都向下,DIP2 的所有開關都向上,則電路板的 DB9 聯結器將被停用,並且 RS485 訊號將出現在四個螺釘端子上。

此介面允許最多 32 個 RS485 裝置連線到同一根電線上,電纜長度最長可達 1200 米,速度為 100 kbit/秒。

目前,Hempl 中不支援 RS485 模式;請參閱 問題 #77

軟體檢視

[編輯 | 編輯原始碼]

簡單 I/O

[編輯 | 編輯原始碼]

根據您使用的韌體,UART0 可能用於 PicoLisp 控制檯(配置為 115200 波特率,8 個數據位,1 個停止位,無奇偶校驗),並且 PicoLisp 的預設輸入和輸出檔案是控制檯,因此像“prinl”和“print”這樣的函式可用於在序列埠上輸出字元(分別帶和不帶尾隨 CR-LF 換行符)。

在 PicoLisp 中

# Greet the user
(prinl "What's your name? ")
(prinl "Hello, " (setq name (read)) "!")

低階 I/O

[編輯 | 編輯原始碼]

UART0 也可以使用更低階的 uart Hempl 模組訪問(並且必須訪問 UART1),這可以更精細地控制 UART 的行為。

以下示例在 UART0 上設定不同的波特率,並在收到回覆字元之前每秒輸出兩次提示字元。為此,它使用了 setup 函式和 getchar 函式的可選超時引數。

在 PicoLisp 中

# Prompt a 9600 baud serial device until we receive
# a character in reply

(setq
   uartid 0       # Which UART should we be talking on?
   timeout 500000 # Prompt once every half second
   timerid 0      # Use timer 0 to measure the timeout
   prompt "U" )   # The prompt character (0x55 : binary 01010101)

(de get-char-uart ()
   (uart-getchar uartid timeout timerid) )

# Get a character from UART
(setq reply (get-char-uart))

(until (= "" reply)
  (uart-write uartid prompt)
  (setq reply (get-char-uart)) )

請注意:您還可以從我們在 github 上的示例儲存庫下載上述程式碼 uart-io.l

硬體流控制

[編輯 | 編輯原始碼]

請注意,使用以下方法啟用硬體流控制:

(uart-set-flow-control uartid (+ *uart-flow-rts* *uart-flow-cts*) )

尚無法使用。請參閱 問題 #29

輸入緩衝區

[編輯 | 編輯原始碼]

當 UART 接收字元時,它會記住它,直到您使用 getchar 請求其值。但是,如果在您讀取第一個字元之前到達第二個字元,則第一個字元將被遺忘。

您可以透過啟用 UART 緩衝區來解決此問題,例如

(uart-setup 1 115200 8 0 1)
(uart-set-buffer 1 1024)

以上配置 UART 1 併為其提供輸入緩衝區。這將允許 UART 接收多達 1024 個字元並記住所有這些字元,即使您尚未讀取第一個字元(第 1025 個字元將引發錯誤訊息並被遺忘)。

UART 緩衝區大小必須是 2 的冪,即 1、2、4、8、16 等,最大可達 32768 個字元。

某些韌體使用 UART0 作為 Alcor6L 控制檯。在這種情況下,此 UART 上始終啟用緩衝區。

USB CDC 序列埠

[編輯 | 編輯原始碼]

Hempl 韌體包括模擬 USB 介面上另一個序列埠的軟體。您將 Mizar32 的 USB 線纜連線到您的 PC,PC 上會出現一個新的序列埠。在 Linux 下,它稱為 /dev/ttyACM0,在 Windows 下,它顯示為一個新的“USB 序列埠”。

通常,此虛擬序列埠用作 Hempl 控制檯,傳送 Hempl 輸出和錯誤訊息,並接收使用者的鍵盤輸入。

它與物理序列埠略有不同,因為

  • 它比最快的 RS232 序列埠快十倍以上;
  • 它始終實現流控制,確保您不會因超速而丟失任何輸出或輸入,但如果您的程式產生輸出並且沒有 PC 連線到 USB 埠,則您的程式將在輸出 1 或 2 KB 後凍結;
  • 某些設定(如波特率和停止位)沒有區別,因為訊號不會透過 RS232 線路傳輸;
  • 我不知道 Lua 中斷是否在 USB 序列埠上工作。

請注意:PicoLisp 目前不支援中斷處理。請參閱 問題 #2

波特率精度

[編輯 | 編輯原始碼]

下表顯示了 Hempl(或 eLua)為最常用的波特率設定的實際波特率

期望 獲得 誤差
300 300 0%
600 600 0%
1200 1200 0%
2400 2400 0%
4800 4799 -0.02%
9600 9604 +0.04%
19200 19186 -0.07%
31250 31250 0%
38400 38372 -0.07%
57600 57692 +0.07%
115200 114583 -0.5%

劫持串行板的 TX LED

[編輯 | 編輯原始碼]

如果未使用 UART0,則可以透過使用 pio.PA_1 作為通用 Mizar32/PIO 輸出切換串行板上的 LED:低輸出值關閉此 LED,高輸出值開啟此 LED。

在 PicoLisp 中

# Turn the serial board's TX LED on (a low output lights the LED)
(setq txled 'PA_1)
(pio-pin-setlow txled)              # Prepare "off" as the output value
(pio-pin-setdir *pio-output* txled) # Make the pin a GPIO output, disabling serial port 0

進一步閱讀

[編輯 | 編輯原始碼]
華夏公益教科書