Hempl/UART
通用非同步收發傳輸器電路或簡稱 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
|
擴充套件序列埠板有兩個撥碼開關組,DIP1 和 DIP2,用於在 RS232 和 RS485 模式之間切換。
如果 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 |
如果 DIP1 的所有開關都向下,DIP2 的所有開關都向上,則電路板的 DB9 聯結器將被停用,並且 RS485 訊號將出現在四個螺釘端子上。
此介面允許最多 32 個 RS485 裝置連線到同一根電線上,電纜長度最長可達 1200 米,速度為 100 kbit/秒。
目前,Hempl 中不支援 RS485 模式;請參閱 問題 #77。
根據您使用的韌體,UART0 可能用於 PicoLisp 控制檯(配置為 115200 波特率,8 個數據位,1 個停止位,無奇偶校驗),並且 PicoLisp 的預設輸入和輸出檔案是控制檯,因此像“prinl”和“print”這樣的函式可用於在序列埠上輸出字元(分別帶和不帶尾隨 CR-LF 換行符)。
在 PicoLisp 中
# Greet the user (prinl "What's your name? ") (prinl "Hello, " (setq name (read)) "!")
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 上始終啟用緩衝區。
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% |
如果未使用 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
- Atmel AT32UC3A 資料手冊 第 26 章:通用同步/非同步收發器 (USART)
- eLua 手冊的 UART 部分,瞭解所有
uart.*()函式的詳細資訊 - 序列程式設計