[Arduino] 使用示波器來看Arduino的UART, Inverted Software serial及RS-232訊號並對其進行解碼



主題: 使用示波器來看Arduino的UART訊號及Inverted Software Serial的波形,及這些訊號轉換成RS-232訊號後的波形,並對其進行ASCII code解碼。



本次測試使用器材為
  1. Arduino MEGA 2560 Rev3 (可參考Po文: [Arduino] 欣賞官方版Arduino MEGA 2560 Rev3 )
  2. TTL to RS-232模組。(這個市面上有N種,本次使用MAX3232 ESE+DN20晶片。)
  3. Keysight 2002A示波器 (關於如何學習該款示波器,可參考Po文: [儀器學習] Keysight DSOX2002A Oscilloscope 示波器 )

PS1: 其他Arduino開發版也可適用此案例,例如: Arduino UNO Rev3Arduino UNO SMD



UART and RS-232基本認知

兩者的邏輯訊號的電壓不同,請見下表。
其中UART採用正邏輯,而RS-232採用負邏輯,因此兩者的波形相反(當然電壓也不同)。

LogicUARTRS-232
1Vcc (3.3 or 5 V)傳送端 -5 V ~ -15 V / 接收端 -3 V ~ -15 V
00 V傳送端 +5 V ~ +15 V / 接收端 +3 V ~ +15 V


序列通訊(Serial Communication)傳輸速度與傳輸封包結構

不管是UART或是RS-232的序列通訊,在此測試中都使用相同的傳輸速度與傳輸封包結構。

關於傳輸速度與傳輸封包結構,由於已行之有年,業界通常都講得非常簡略,也成為了一種默契。

業界行話: 
  1. Baud rate 2400 bps。
  2. 8N1 (詳細請見參考資料)。

這個行話,簡單來說: 
  1. 每秒會傳送2400個Bit。表示資料傳輸速度。
  2. 會看到訊號長成10個格子的樣子,如下圖所示。
其中Start (第1個Bit)會用Logic 0表示,Stop (第10個Bit)會用Logic 1表示,這兩個都是固定不變。
D0~D7這8個Bit就是存放資料的地方(灰色區域),Logic可以是0或1,看你放什麼資料。

當封包結構解開後(10碼結構),解碼主要就是解這塊(8碼灰色區域)。

Bit12345678910
MeaningStartD0D1D2D3D4D5D6D7Stop
Logic01


Arduino UART

獻慶寫了一個Arduino的code,請Arduino每秒從第16 pin輸出訊號 (Tx2,第3組Serial channel)。

示波器的探棒兩端則對Arduino的第16 pin及GND偵測。

調整示波器至可看到訊號波形( [儀器學習] Keysight DSOX2002A Oscilloscope 示波器 ),會看到一堆凹凸的方塊波,長度不一。
第一次看到,會慌,不用擔心,我們一步一步做下去。

UART訊號波型。

先檢查訊號電壓。低電壓為10 mV,表示邏輯0,高電壓為4.91 V,表示邏輯1。電壓差為4.9 V。
這點與Arduino規格上的Vcc=5V有接近,差值可能來自於線損。

檢查訊號電壓。

請看出訊號中"最窄的凹凸","最窄的凹凸"的寬度表示1個Bit的傳輸時間。這裡寬度量得為416.60 μs (μs通常顯示為us,因為μ這個希臘字不容易顯示),倒數後換算成傳輸速度(Bit Rate)則是2400.4 bps (圖中顯示2.4004 kbps)。此數值與訊號傳輸的Baud rate設定值幾乎吻合,表示找對的訊號來計算。

PS1:
傳輸速度(Bit Rate)計算方式,就是用"頻率(f)=1/週期(period)"這個耳熟能詳的式子來計算,傳輸速度就是頻率值。
其中,週期period量得為416.60 μs = 416.60 × 10−6 s
傳輸速度 = 1/週期period = 1 / (416.60 × 10−6 s) = 0.0024004 × 106 = 2400.4 (bps)

PS2: 若找錯訊號計算,則計算值可能會低於設定值幾倍。而如果在這個錯誤下硬去解碼,則是會產生很多解碼問題。例如: 訊號實際波形與傳輸封包結構不匹配。

PS3: 老手可跳過這步。反正只要猜到哪個是1個Bit的寬度(最窄的凹凸),就可以開始解碼了。另外,新式的示波器,也可把自動量測Bit Rate的選項打開,直接看到數值。

計算Bit rate。

根據serial communication的封包結構,可先用10 bit的寬度將原始訊號切開。

訊號切開的起始點,其實很好判斷。沒訊號時,會看到訊號基本上維持同一個電壓,一旦電壓開始改變,就是訊號進來了。另外一種說法,長時間都是Logic 1的訊號,一旦開始變成Logic 0,表示訊號進來了。

原始訊號切開後,可切得4個區塊。
每個區塊中,由左側數過來,第1個Bit為Logic 0,表示Start,第10個Bit為Logic 1,表示Stop,這兩個都是固定不變。
D0~D7這8個Bit就是存放資料的地方(灰色區域),Logic可以是0或1,看你放什麼資料。

先將Logic根據實際訊號狀況分析出來,也就是把圖中的黃字填上。記得在UART Serial communication中,低電壓表示Logic 0,高電壓表示Logic 1。

UART分析訊號並解碼。

封包結構分析完畢後,接著就是要解碼了。
解碼其實是要有密碼對照表或演算法。但這裡獻慶很單純的就是用ASCII code來解碼。下表列出本次用到的code。

DecHexBinaryCharDescription
130D00001101CR ( or \r )Carriage Return
654101000001A
825201010010R
865601010110V

使用該對照表可解碼,其中原始訊號中的第1個區塊解碼為R,第2個區塊解碼為V,第3個區塊解碼為V,第4個區塊解碼為\r。

得到訊號為 RVA\r
本文中的測試訊號就是預設為這個,從頭到尾不變,方便各位進行波形比對。

PS: 這裡Binary code的順序為D7~D0,得左右顛倒唸,才比較方便比對。例如: 表上的"00001101",左右顛倒後為"10110000",可對到原始訊號中的區塊4的信號。

完整對照表請參考資料: ASCII Table


Arduino UART to RS-232

先請Arduino每秒從第16 pin輸出序列訊號 (Tx2,第3組serial channel),透過"TTL to RS-232模組",將UART的訊號轉成RS-232的訊號。

示波器則對轉換後的Tx訊號進行偵測。

調整示波器至可看到訊號波形,會看到一堆凹凸的方塊波,長度不一。
我們一步一步做下去。

RS-232訊號波型。

先檢查訊號電壓。低電壓為-8.8 V,表示邏輯1,高電壓為8.9 V,表示邏輯0。電壓差為17.7 V。

PS: 從這個檢查中,得知電壓差為17.7 V,若此訊號直接接到Arduino上,可能會造成Arduino燒毀,因此為了避免燒毀,需要電壓轉換模組,也就是本次使用的"TTL to RS-232模組。

檢查訊號電壓。

請看出訊號中"最窄的凹凸","最窄的凹凸"的寬度表示1個Bit的傳輸時間。這裡寬度量得為416.96 μs (μs通常顯示為us,因為μ這個希臘字不容易顯示),倒數後換算成傳輸速度(Bit Rate)則是2398.3 bps (圖中顯示2.3983 kbps)。此數值與訊號傳輸的Baud rate設定值幾乎吻合,表示找對訊號來計算。

計算Bit rate。

根據serial communication的封包結構,可先用10 bit的寬度將原始訊號切開。

訊號切開的起始點,其實很好判斷。沒訊號時,會看到訊號基本上維持同一個電壓,一旦電壓開始改變,就是訊號進來了。另外一種說法,長時間都是Logic 1的訊號,一旦開始變成Logic 0,表示訊號進來了。

原始訊號切開後,可切得4個區塊。
每個區塊中,由左側數過來,第1個Bit為Logic 0,表示Start,第10個Bit為Logic 1,表示Stop,這兩個都是固定不變。
D0~D7這8個Bit就是存放資料的地方(灰色區域),Logic可以是0或1,看你放什麼資料。

先將Logic根據實際訊號狀況分析出來,也就是把圖中的黃字填上。記得在RS-232 Serial communication中,高電壓表示Logic 0,低電壓表示Logic 1 (請注意,RS-232跟UART的電壓邏輯顛倒)。

RS-232分析訊號並解碼。

封包結構分析完畢後,接著就是要解碼了。
解碼其實是要有密碼對照表或演算法。但這裡獻慶很單純的就是用ASCII code來解碼。下表列出本次用到的code。

DecHexBinaryCharDescription
130D00001101CR ( or \r )Carriage Return
654101000001A
825201010010R
865601010110V

使用該對照表可解碼,其中原始訊號中的第1個區塊解碼為R,第2個區塊解碼為V,第3個區塊解碼為V,第4個區塊解碼為\r。

得到訊號為 RVA\r

PS: 這裡Binary code的順序為D7~D0,得左右顛倒唸,才比較方便比對。例如: 表上的"00001101",左右顛倒後為"10110000",可對到原始訊號中的區塊4的信號。

完整對照表請參考資料: ASCII Table



獻慶這裡將UART與RS-232輸出的訊號放在一起,方便各位比較。

(由於手上只有一根探棒,無法同時取得並顯兩組訊號,此圖是分別取得訊號後,在後製拼圖)

Arduino的UART與RS-232輸出的訊號比較與分析。


Arduino Inverted Software Serial 

以下會帶一下何謂Software serial,何謂Inverted software serial,還有案例的示波器訊號。

關於Software Serial

Arduino除了部分pin提供硬體序列功能外,也在其他特定pin提供軟體序列功能(Software serial)。這樣可以提供更多的序列通訊通道,補強Arduino序列通道不足的問題。

Software serial有提升A序列通訊數量的優點,但也有些缺點,例如: (1) 每提供1個通道的軟體序列通訊,則會少掉2個pin供其他輸出入應用。(2) 軟體序列通訊的最高傳輸速率遠低於硬體序列通訊的最高傳輸速率。如果有高速通訊的需求,就得考慮這點。


詳細內容,請見參考資料: 


關於Inverted Software serial

既然都已經使用Software serial,怎麼前面還要加一個"Inverted"?

Inverted 表示反向

在Arduino的SoftwareSerial語法中,可透過inverse_logic來更改邏輯方向。

SoftwareSerial(rxPin, txPin, inverse_logic)

inverse_logic: 預設是0,或者就不要寫這個選項。設為1時,就會反向,也就是可以處理邏輯反向的訊號。

只是邏輯電壓顛倒,這個看似多餘的功能,卻意外地在實際應用時幫得上忙。


PS:
但為何一開始有學software serial的人,卻不知道有開啟反向邏輯設定?

因為很多Arduino的software serial程式範例是長這樣
SoftwareSerial(rxPin, txPin)
所以很多人不知道後面還有開啟反向邏輯設定

要另外去完整的語法介紹頁面,才會看到
SoftwareSerial(rxPin, txPin, inverse_logic)


參考資料:

示波器Data

以下是從示波器量測Inverted software serial獲得的訊號,各位可以使用"Arduino UART"這節提供的方法來進行分析。

要注意,電壓有上下顛倒。

Inverted software serial, 原始波型。

Inverted software serial, 檢查高低電壓用。

Inverted software serial, 計算傳輸速率。


Arduino Inverted Software Serial to RS-232

以下是從示波器量測Inverted software serial轉成RS-232後獲得的訊號,各位可以使用"Arduino UART to RS-232"這節提供的方法來進行分析。

要注意,電壓有上下顛倒。

Inverted software serial to RS-232, 原始波型。

Inverted software serial to RS-232, 檢查高低電壓用。

Inverted software serial to RS-232, 計算傳輸速率。


Hardware vs Software Serial

既然有示波器,那我們可以來看看硬體跟軟體序列通訊的差異性。


在通訊速度Bit rate 2400 bps的狀態下,兩者基本上看不太出差異。

不管是大致上的波形(下圖(a)及(b)),由低電壓至高電壓的波形放大圖(下圖(c)及(d)),由高電壓至低電壓的波形放大圖(下圖(e)及(f)),都大致相同。

Hardware vs software serial. (a) Hardware, total signal, (b) Software, total signal, (c) Hardware, low-to-high signal, (d) Software, low-to-high signal, (e) Hardware, high-to-low signal, and (f) Software, high-to-low signal.

眼尖的朋友會注意到,訊號變換時,電壓的變化並不是穩定的,而是看起來有衝過頭的狀況。此現象在電路學中有個名詞,叫overshooting。發生的時間很短,解析度高的示波器比較可捕捉到。在本案例中,每次電壓轉都會出現overshooting的現象,但在上圖(a)及(b)中,卻只看到其僅出現在某些轉換。這台示波器提供了"Peak Detect"的功能,能保留一定時間內波型的最大最小值,使我們在示波器訊號解析度不足的狀況下,也能看到每個電壓轉換時出現的overshooting現象,如下圖所示。

示波器的"Peak Detect"功能,使得每個電壓轉換時出現的overshooting現象,得以顯現。訊號源: Inverted software serial。


在Arduino官方對Software serial的介紹中 (Arduino - SoftwareSerial Library),有提到
It is possible to have multiple software serial ports with speeds up to 115200 bps.


那我們就來看看實際波形到底會如何。

在經過許多不同傳輸速度的測試後,獻慶發現,訊號不穩定的狀況,主要來自延遲輸出,造成訊號錯誤。儘管不是每個訊號都延遲輸出,但出現的頻率越高,表示訊號越不穩定,也越容易造成讀寫錯誤的狀況發生。

為了捕捉這個延遲輸出,開啟示波器的波形保留功能,來捕捉這個狀況。比較亮的波形就是實際訊號波型,而有點暗的波形(或稱殘影)就是有延遲輸出的波形(波形保留的測試時間大概2分鐘左右)。如下圖所示。

開啟示波器的波形保留功能,來捕捉輸出延遲的狀況。

在Inverted software serial的訊號中,隨著設定傳輸速度越來越大,殘影的狀況越來越嚴重,在19200 bps時就有明顯的感覺。而9600 bps則是看起來不明顯,難怪業界都喜歡選這個數值。

另外,隨著設定傳輸速度越來越大,實際輸出的傳輸速度與設定值的落差會增大。例如: 設定傳輸速度為1500000 bps時,實際傳輸速度只有842100 bps (如圖(w)所示,842.1 kbps)。

不管是訊號延遲或是速度落差都會造成通訊失效。

Inverted software serial訊號在各個設定傳輸速度下的實際波形。



接下來看看硬體輸出的UART訊號,9600 bps當然沒問題,然後就一路沒問題,到512000 bps也都沒問題,只是傳輸速度有些許落差。與軟體序列傳輸比起來,這個狀況好太多了,難怪大家說"有硬體的一定要用硬體的"。

設定傳輸速度1024000 bps時,開始出現殘影(傳輸延遲)。設定傳輸速度越高,殘影狀況越嚴重。

有趣的是,設定傳輸速度1500000 bps及3000000 bps時,實際傳輸速度都是2000000 bps (2.000 Mbps)。

UART訊號在各個設定傳輸速度下的實際波形。


TTL to RS-232模組的轉換效果

由下圖可看出,原本的UART訊號(圖(a))轉換為RS-232訊號後,overshooting的現象消失了(圖(b))。看起來是個優點。

但轉換時間變長了,從6 ns (圖(c)及(e))到350 ns (圖(d)及(f))。看起來是個問題。這樣會造成轉換後的RS-232訊號,沒辦法支援很高的傳輸速度。

"Original UART" vs "TTL to RS-232". (a) Original UART, total signal, (b) TTL to RS-232, total signal, (c) Original UART, low-to-high signal, (d) TTL to RS-232, low-to-high signal, (e) Original UART, high-to-low signal, and (f) TTL to RS-232, high-to-low signal.

如下圖所示,
設定傳輸速度為9600 bps時(圖(a)~(d))。每個bit的凹凸形狀都非常銳利,呈現90度變化,實際傳輸速度與設定速度也幾乎吻合(圖(b)及(c))。沒有看到殘影發生(圖(d))。

設定傳輸速度為115200 bps時(圖(e)~(h))。每個bit的凹凸形狀就沒那麼銳利,有些歪斜,實際傳輸速度與設定速度仍吻合(圖(f)及(g))。沒有看到殘影發生(圖(h))。

設定傳輸速度為256000 bps時(圖(i)~(l))。每個bit的凹凸形狀就更不銳利,歪斜加重,實際傳輸速度與設定速度已不吻合(圖(j)及(k))。沒有看到殘影發生(圖(l))。

設定傳輸速度為512000 bps時(圖(m)~(p))。每個bit的凹凸形狀就更不銳利,歪斜再度加重,實際傳輸速度與設定速度已不吻合(圖(n)及(o))。沒有看到殘影發生(圖(p))。

設定傳輸速度為1024000 bps時(圖(q)~(t))。每個bit的凹凸形狀就更不銳利,歪斜非常加重,實際傳輸速度與設定速度已極度不吻合(圖(r)及(s))。有看到殘影發生(圖(t))。表示繼承了UART原始波型的殘影。至於實際波形就更慘了,很多方塊波看起來都快變成三角波了。

經過測試,轉換後的RS-232訊號,沒辦法支援很高的傳輸速度,大約穩定的速度為115200 bps。而造成此結果的主因,確實來自於訊號轉換時間變長。

UART訊號轉成RS-232訊號後,在各個設定傳輸速度下的實際波形。


感想

1.
記得高中老師說過: 
示波器的最高境界是量序列埠的訊號,也就是可以監聽序列埠訊號,分析包率、邏輯0,1、破解資料。現在跟你們講這些還太早... 我們還是先用示波器來看sine波好了...

現在可以認真回應老師: 有看到序列埠了歐! 讚! ^_^

2.
駭客入侵手段

記得之前在看駭客的攻擊手段時,除了大家印象中那種寫程式的駭客外,還有一種駭客手段就是所謂的"實體侵入"。

以這個案例來看,利用示波器配合其他分析器,就可以在序列埠的實體線路上達成監聽訊號的目的。訊號解析完畢後,還可以偽裝官方發送指令碼。看來可以做的事也不少了...

3.
在之前的Po文中( [Arduino] 解決RS-232轉TTL的邏輯反向問題 (亂碼問題) ),獻慶猜到了反向邏輯的某些解決方式。不過當時沒有辦法去看到實際訊號,來進行驗證。

這次的測試給足了驗證機會。

4.
很多時候,儀器設備是不會完美的。這次量測時,由於探棒只有一根,沒辦法同時顯示UART跟經過轉換後的RS-232兩組訊號。

沒有兩根探棒 那就分開量測,還是可以有一定的效果。

當然,有兩根會更棒,也許可以看到兩組訊號間的延遲狀況。

5.
由沒有license,無法開啟示波器的序列訊號分析功能,所以應用更多示波器的基本功,也學到更多。

這台示波器有分析UART跟RS-232的功能,只是需要license。原廠的說明如下:
To complete this lab, your scope must be licensed with the RS232/UART trigger and decode option (Option COMP).
但在沒用這些延伸功能的狀況下,仍然應用基本功量得訊號,也成功進行分析。

這樣反而對示波器的基本操作更扎實,而且對於訊號結構及解碼有更深入的理解。賺到! ^_^

原廠示範UART跟RS-232的訊號分析功能。


感謝

感謝好友阿峪提供示波器,讓獻慶有機會來自己做測試,看到UART跟RS-2322的實際波型,並解決開發上的困擾。

感謝超倍能科技林榮豐董事長鼎力相挺,提供獻慶許多資源與時間去學習示波器,練習解碼,達成開發案的完成。

感謝楊孝文老師,提供許多開發上的硬體,還有點子。

感謝羅彥凱,討論研發過程。



相關Po文

RS-232反向問題


示波器學習


Arduino










相關連結




留言

張貼留言

這個網誌中的熱門文章

什麼是電池的CCA(Cold Cranking Amperes)? 如何量測CCA?

感恩接力棒 活動

[數據處理] Excel 日期時間 換算成 秒