張高興的 .NET Core IoT 入門指南:(五)串列埠通訊入門
在開始之前,首先要說明的是串列埠通訊所用到的 SerialPort
類並不包含在 System.Device.Gpio
NuGet 包中,而是在 System.IO.Ports
NuGet 包中。之所以在這裡介紹串列埠通訊,是因為在嵌入式中串列埠通訊是與其他裝置進行互動的一種重要方式,而且在某些沒有螢幕的裝置中充當著程式除錯的工具。
什麼是串列埠
串列埠是序列介面的簡稱,這是一個非常大的概念,在嵌入式中串列埠通常指 UART (Universal Asynchronous Receiver/Transmitter,通用非同步收發器)。使用串列埠進行的通訊叫做序列通訊,與之相對的一個概念是並行通訊。序列通訊是指資料一位一位的按順序傳輸,而並行通訊則是多位資料同時傳輸。如圖1所示,DATA BUS
UART 1
之間是並行通訊,UART 1
到 UART 2
之間是序列通訊。
圖1:序列通訊與並行通訊
串列埠通訊的資料幀格式如圖2所示,通常一幀共包括 10 位:1 個起始位,8 個數據位和 1 個停止位。有一些特殊的資料幀在停止位前面包含 1 位的奇偶校驗位,還有的停止位有 2 個位元。其中起始位為低電平(0),標誌著資料傳輸的開始;停止位為高電平(1),表示資料幀傳輸結束;資料位則為實際傳送的資料,使用高低電平來表示位元資訊,如果傳送的內容是文字,那麼這段資料為字元的二進位制編碼(ASCII,UTF-8……)。資料傳輸的速率我們使用波特率(Baud Rate)來表示,即每秒鐘傳送的碼元符號的個數[1]
圖2:串列埠通訊的資料幀
裝置進行串列埠通訊時,裝置的連線如圖3所示,兩個裝置的訊號線,即傳送端(TXD)與接收端(RXD)交叉相連,並且需要共地。在 Raspberry Pi 的引腳上共引出了 1 組串列埠,即 UART 0
,對應 8 和 10 號引腳。
圖3:串列埠裝置的連線
相關類
串列埠操作的相關類位於 System.IO.Ports
名稱空間下。
SerialPort
public class SerialPort : Component { // portName 為串列埠的名稱,可以使用靜態方法 GetPortNames() 獲取 public SerialPort(string portName); // 傳輸的波特率 public int BaudRate { get; set; } // 指定傳輸內容的編碼 public Encoding Encoding { get; set; } // 新行格式,即設定換行的字元 public string NewLine { get; set; } // 設定停止位的格式 public StopBits StopBits { get; set; } // 設定校驗位的格式 public Parity Parity { get; set; } // 開啟串列埠通訊流 public void Open(); // 關閉串列埠通訊流 public void Close(); // 向串列埠通訊流中寫一行字元 public void WriteLine(string text); // 從串列埠通訊流中讀一行字元 public string ReadLine(); // 讀取緩衝區中的所有可用內容,一般用於清空緩衝區,防止讀取舊的內容 public string ReadExisting(); // 獲取可用的串列埠名稱 public static string[] GetPortNames(); }
串列埠通訊的步驟
- 配置串列埠通訊引數,如波特率,內容編碼,新行格式,超時時間等。
SerialPort sp = new SerialPort(portName: "/dev/ttyUSB0")
{
BaudRate = 115200,
Encoding = Encoding.UTF8,
ReadTimeout = 500,
WriteTimeout = 500,
}
- 開啟串列埠
sp.Open();
- 讀取和寫入文字
sp.WriteLine($"Text content.");
string content = sp.ReadLine();
- 關閉串列埠
sp.Close();
USB 串列埠通訊實驗
硬體需求
名稱 | 數量 |
---|---|
USB 串列埠 | x1 |
杜邦線 | 若干 |
USB 串列埠裝置只要 Raspberry Pi 支援即可,這裡使用的是 FT232RL
。
電路
- GND - GND
- RX - TX (Pin 8)
- TX - RX (Pin 10)
- USB - USB
使用 Docker 執行示例
示例地址:https://github.com/ZhangGaoxing/dotnet-core-iot-demo/tree/master/src/SerialCommunication
docker build -t serial-sample -f Dockerfile .
docker run --rm -it --device /dev/ttyUSB0 --device /dev/ttyS0 serial-sample
程式碼
- 開啟 Visual Studio ,新建一個 .NET Core 控制檯應用程式,專案名稱為“SerialCommunication”。
- 引入 System.IO.Ports NuGet 包。
- 在 Program.cs 中,將主函式程式碼替換如下:
static void Main(string[] args)
{
using (SerialPort usb = new SerialPort(portName: "/dev/ttyUSB0"))
{
usb.BaudRate = 115200;
usb.Encoding = Encoding.UTF8;
usb.ReadTimeout = 500;
usb.WriteTimeout = 500;
usb.Open();
using (SerialPort rpi = new SerialPort(portName: "/dev/ttyS0"))
{
rpi.BaudRate = 115200;
rpi.Encoding = Encoding.UTF8;
rpi.ReadTimeout = 500;
rpi.WriteTimeout = 500;
rpi.Open();
for (int i = 0; i < 10; i++)
{
rpi.WriteLine($"Hello {i}!");
Console.WriteLine($"USB receive: {usb.ReadLine()}");
}
rpi.Close();
}
usb.Close();
}
}
- 釋出、拷貝、更改許可權、執行
效果圖
備註
下一篇文章將談談 Iot.Device.Bindings NuGet 包的使用。