National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 04

序列通訊與 pyserial

鮑率、資料格式、終止字元、逾時與第一次和儀器對話
Interaction 25 minute(s)

Learning Objectives

  • 說出鮑率、資料位元、同位元、停止位元的意思,算出 8N1 每秒能傳幾個位元組
  • 用 pyserial 開啟序列埠、送出指令、讀回一行回應
  • 分辨位元組(bytes)與字串(str),會用 encode() 與 decode() 轉換
  • 知道終止字元與逾時的作用,能判斷「讀到空的 b''」的可能原因

最簡單的一條線

序列通訊(serial communication)把資料一個位元接一個位元送出去。電腦的 COM 埠(RS-232)、微控制器的 UART、 很多儀器背後的 DB9 接頭都是這一類。它的線很少、規則簡單,所以到現在還很常見:老儀器、溫度控制器、條碼掃描器、 開發板的除錯輸出都在用。

序列通訊沒有共同的時脈線,雙方要事先約好速度與格式,才能正確地切出每一個位元:

參數 意思 常見值
鮑率(baud rate) 每秒傳幾個位元(符號) 9600、19200、115200
資料位元 每個字元幾個位元 8
同位元(parity) 簡單的錯誤檢查:無(N)、偶(E)、奇(O) N
停止位元 每個字元結尾的「休息」位元 1

「9600 8N1」就是鮑率 9600、8 個資料位元、無同位元、1 個停止位元,也是儀器最常見的預設值。 每個字元前面還有 1 個起始位元,所以 8N1 傳一個位元組要 1+8+1=10 個位元,9600 鮑率每秒約可傳 960 個位元組。

RS-232 用正負電壓表示 0 與 1(常見範圍是 ±3~±15 V),和微控制器 3.3 V 的 UART 腳位不同,不能直接相接,中間要有轉換晶片或 USB 轉序列轉接線。

看一個字元在線上長什麼樣子

送出 *IDN? 的第一個字元是 *(ASCII 碼 0x2A)。用邏輯分析儀一格一格看:閒置是高電位,起始位元拉低, 接著 8 個資料位元從最低位元(D0)先送,最後是停止位元。

pyserial:用 Python 開序列埠

Python 用 pyserial 套件(pip install pyserial,匯入名稱是 serial)控制序列埠:

import serial
ser = serial.Serial("COM3", 9600, timeout=1)   # Windows 是 COM3,Linux 常見 /dev/ttyUSB0
ser.write(b"*IDN?\n")                          # 送出:一定要是位元組(bytes)
reply = ser.readline()                          # 讀到換行為止,回傳位元組
ser.close()

三個重點:

  1. 送出與收到的都是位元組(b"..."),不是字串。字串要用 .encode() 轉成位元組,收到的位元組用 .decode() 轉回字串。
  2. 終止字元:儀器靠一個特殊字元(常見是換行 \n,有些是 \r\n 或 \r)知道「一個指令結束了」,回應也用它結尾。 本課的電錶收 \n、回 \r\n。
  3. 逾時(timeout):readline() 最多等幾秒。時間到還沒收到換行,就回傳目前收到的內容,什麼都沒收到時是空的 b''。 不設 timeout 的話,對方不回應時程式會一直卡住。

逐步看:第一次和電錶對話

看下方通訊紀錄:先「開啟序列埠 COM3 9600」,然後 → 送出 *IDN?\n、← 收到電錶的回答。注意第 10 行印出的是位元組(前面有 b、結尾有 \r\n)。

讀到 b'' 的時候

序列通訊最常見的問題是 readline() 回傳空的 b'':程式等到逾時,什麼都沒收到。常見原因:

原因 發生什麼事 怎麼辦
鮑率不一致 對方切錯位元,收到的是亂碼,不會回應 查儀器的設定選單或手冊,兩邊設成一樣
少了終止字元 對方還在等指令結束 指令結尾加上 \n(或手冊規定的字元)
送的不是查詢 設定類指令(例如 CONF:VOLT)本來就不會回應 只有查詢(結尾有 ?)才讀回應
接錯埠、線沒接、TX/RX 接反 對方根本沒收到 用 comports() 確認埠名,檢查接線

開啟不存在的埠(例如 COM9)則會直接丟出 serial.SerialException。下一個範例示範前兩種問題。

逐步看:鮑率錯了、終止字元忘了

同樣送 *IDN?,先用錯誤的鮑率,再忘記換行。注意虛擬時間:每次 readline() 等不到回應,就要等滿逾時 0.5 秒。

逐步看:字串與位元組、把讀值轉成數字

先故意把字串直接傳給 write(),看 pyserial 怎麼拒絕;再用 encode() 送出量電阻的指令,把收到的位元組轉成數字。

互動練習:修好序列埠程式

電錶接在 COM3,設定是 9600 8N1,終止字元是換行。起始程式有兩個問題,所以只讀到 b''。依序完成任務:

  1. 直接執行起始程式,看通訊紀錄:送出去了,但沒有收到回應。
  2. 修正鮑率與終止字元,收到電錶的 *IDN? 回答。
  3. 送出 MEAS:RES?,把回應轉成數字,用 round(…, 1) 印出電阻值(約 1000 Ω)。
  4. 回答一個問題。

小測驗:序列通訊的參數

1.

「19200 8N1」中的 N 是什麼意思?

2.

鮑率 115200、8N1,每秒最多大約可以傳多少個位元組?

3.

電腦送出 *IDN?\n,但鮑率設成 115200,電錶是 9600。readline()(timeout=1)會怎樣?

第 1 次作答

小測驗:位元組與字串

1.

下面的程式會印出什麼?

raw = b"+2.50000E+00\r\n"
text = raw.decode().strip()
print(len(raw), len(text), float(text) * 2)
2.

下面哪一行能正確送出指令 MEAS:VOLT:DC??(ser 已經開啟)

第 1 次作答

重點整理

  • 序列通訊雙方要事先約好鮑率與資料格式(常見 9600 8N1);8N1 每個位元組 10 個位元。
  • RS-232 用正負電壓,不能直接接微控制器的 3.3 V UART。
  • pyserial:serial.Serial(埠, 鮑率, timeout=秒)、write(位元組)、readline()、close();list_ports.comports() 列出埠。
  • 送出與收到的都是位元組:"文字".encode() → 位元組,b"...".decode() → 字串。
  • 指令結尾要有終止字元(常見 \n);設 timeout 避免卡住。讀到 b'':檢查鮑率、終止字元、是不是查詢、接線。

序列埠要自己處理位元組、終止字元與逾時;下一課先學儀器聽得懂的指令語言 SCPI,第 06 課再用 PyVISA 把這些細節交給 VISA 處理。

這一課完成了!
Next lesson:SCPI 指令語法
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。