本文由網友投稿。
作者:陳顯達
原文標題:【微控制器入門】(三)應用層軟體開發的微控制器學習之路-----UART 序列埠通訊和C#互動
原文連結:https://www.cnblogs.com/1996-Chinese-Chen/p/16826558.html
引言
在第一章部落格中,我們講了 Arduino 對 ESP32 的一個環境配置,以及了解到了常用的一個匯流排通訊協定,其中有 SPI、IIC、UART 等,今天我為大家帶來 UART 序列埠通訊和 C# 序列埠進行通訊的一個案例,以及什麼是中斷,中斷的作用和實作,話不多說,讓我們正式開始。
UART
在第一篇部落格中,我們講了 UART 是需要一個接收一個發送的腳位,總共兩個,分別是 TXD(發送腳位)、RXD(接收腳位),不管是什麼類型的微控制器序列埠腳位都是這兩個,可能有的是少了最後面的那個 D,但是都是一樣的東西。在 ESP32 的開發板上,是有三對 UART 的腳位的,也就是說板子上有三個序列埠可以供我們使用,如下圖,Serial0 對應的腳位為 1 和 3,Serial1 對應的腳位為 9 和 10,Serial2 對應的腳位為 16 和 17。但是在我們燒錄的時候,1 和 3 是不能使用的,因為我們透過 USB 將微控制器連接到電腦上,使用的序列埠腳位就是 1 和 3,所以我們可使用的序列埠只有兩個。而 Arduino IDE 上面,對應的 Serial 也有四個靜態類別,分別是 Serial、Serial1 和 Serial2 以及 Serial3。雖然它的數量和我們 ESP32 的序列埠數量是一樣,但是只有第一個可以使用,後面兩個我們是無法使用的,因為後面兩個對應的腳位和我們 ESP32 的腳位是不相同的,我們可以從下面第二個圖看到,Serial1、Serial2 的 PINS 是和我們 ESP32 的腳位是對不上的,所以我們在序列埠開發的時候是不使用這兩個,對於第一個 Serial 我們是可以使用的。


我們如果需要使用 ESP32 的序列埠開發,在 ESP 的開發套件裡,官方給我們提供了一個 HardwareSerial 的一個序列埠函式庫,裡面我們可以使用開發板上面的序列埠,同時將腳位指定為我們腳位圖上面的腳位。這個函式庫的位置為我們 Arduino IDE 目錄下的 hardware/espressif/esp32/cores/esp32 可以找到這個函式庫,這個資料夾下包含了一些 ESP32 的官方函式庫;使用這個 HardwareSerial.h 檔案我們可以實現使用 ESP32 開發板上面的序列埠進行開發,接下來我們在程式碼中去了解他如何使用。

編碼
在下面的程式碼中,我們開始了一個簡單的一個序列埠通訊,在程式碼第一行,是和 C 語言一樣引入我們需要的函式庫檔案,然後在第二行,定義了 HardwareSerial 這個類別的一個 MySerial1 物件,裡面的建構子的值是 1 代表著,我們將使用第一個序列埠。在下面的 setup 裡面,我們開始啟動了 MySerial1 這個序列埠物件,啟動的鮑率是 9600,資料長度是 8,校驗位是 NONE,停止位是 1,以及序列埠的 RX 的腳位是 16,TX 的腳位為 17。在下一行程式碼,我們傳入了一個我們下方定義的 receiveEvent 的一個方法,這個方法用來接收序列埠接收資料的一個回呼,將我們這個方法指標傳入進去,在序列埠接收到資料之後,會進入到我們這個方法中。
最後一行程式碼,我們是啟用了第 0 個序列埠,鮑率是 9600。
可能上面的程式碼有朋友就有疑惑了,明明 16 和 17 在腳位圖中定義的序列埠是 2,為什麼這裡定義的是 1 呢?實際上這個我們可以自己修改這個序列埠的定義和腳位,這個建構子傳入的參數取值範圍為 0、1、2,對應的是我們開發板上的三個 UART 序列埠,在 begin 哪裡傳入的腳位和這個 0、1、2 是沒有關係的,但是這個傳入的腳位必須是開發板上三個 UART 序列埠之一,所以我們也可以定義為 MySerial2.begin(9600,SERIAL_8N1,10,9);這裡的 0、1、2 僅對應有三對序列埠,不指定對應的腳位,在 begin 方法我們指定對應的序列埠的腳位。
在下面的接收到序列埠訊息的回呼中,我們第一行程式碼呼叫了 available 這個方法,這個方法返回的是一個 int 參數,當然了我們這塊也可以寫 available()>0,也是可以的,這個方法是從序列埠快取中讀取我們接收到的資料長度,這個條件成立,說明我們是有接收到資料,然後在裡面我們開始去讀取資料。
在所有的 Serial 都是繼承程式 Arduino 的一個 Stream 的一個基礎類別,這個類別提供了一些我們對資料處理的一個方法,所以在下面的程式碼中,我們將讀取的資料轉為字串,然後將程式碼延遲暫停了一秒,隨後,我們使用我們的序列埠物件,將接收到的資料寫入緩衝區,緩衝區會把我們寫入的資料,在發送出去,即將 println 裡面傳入的參數發送到我們的序列埠發送方,誰發的資料,誰就會收到「i am receive!!」+str。
#include <HardwareSerial.h>
HardwareSerial MySerial1(1);
void setup() {
// put your setup code here, to run once:
MySerial1.begin(9600,SERIAL_8N1,16,17);
MySerial1.onReceive(receiveEvent);
Serial.begin(9600);
}
void loop() {
}
void receiveEvent()
{
if(MySerial1.available())
{
String str= MySerial1.readString();
delay(1000);
MySerial1.println("i am receive!!"+str);
}
delay(1000);
}
Stream 包括了以下方法,其中繼承 Stream 的分別為序列埠、IIC 通訊的 Wire、SD 卡的一個類別,以及用於網路連線的 Ethernet 類別,都可以使用這些方法用來對資料進行操作。

C# 編碼
C# 方面的程式碼則簡單很多,介面一個開啟序列埠的按鈕,一個發送資料的按鈕和文字框,以及用來接收資料顯示的文字框。
在程式碼中我們開啟了序列埠,指定了打開的是哪一個序列埠,一些屬性是需要在 ESP32 那邊設定一樣的,在上面我們設定鮑率為 9600,資料為是 8,停止位是 1,校驗位是 NONE,所以在 C# 這邊我們也需要這樣設定,不過校驗位預設是 NONE 的,所以此處我們沒有設定,然後開啟序列埠,註冊了一個接收到資料的一個回呼,然後定義一個 1024 的位元組陣列,從序列埠讀取資料,返回讀取的資料長度,然後在對剛才定義的 1024 位元組陣列進行截取,然後透過 UTF-8 的格式轉為字串,然後顯示到介面上的富文本框中。在發送按鈕事件中,我們從輸入框讀取資料轉為位元組陣列,然後將資料寫入到序列埠中去即可。

public partial class Form1 : Form
{
private SerialPort serialPort = new SerialPort("COM6");
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
serialPort.BaudRate = 9600;
serialPort.StopBits = StopBits.One;
serialPort.DataBits = 8;
serialPort.Open();
serialPort.DataReceived += (a, b) => {
var serial = a as SerialPort;
var data = new byte[1024];
var res=serial.Read(data,0, data.Length);
data = data[..res];
string st = Encoding.UTF8
.GetString(data);
BeginInvoke(() => { richTextBox1.Text += st; });
};
}
private void button2_Click(object sender, EventArgs e)
{
var str = Encoding.UTF8.GetBytes(textBox1.Text);
serialPort.Write(str, 0, str.Length);
}
}
接線圖
在此處的實例,我們需要準備一個 USB 轉 TTL 的模組,四根母對母的杜邦線,在程式燒錄之後,我們需要將使用杜邦線讓 USB 轉 TTL 模組和微控制器進行連接,VCC 或者 5V 接微控制器的 5V 腳位,USB 轉 TTL 的 GND 和微控制器的 GND 相接,然後 USB 轉 TTL 的 RXD 腳位和微控制器 17 腳位相接,TXD 腳位和微控制器的 16 腳位相接,如下圖所示接線,5V 不可和 GND 接反,否則可能會燒壞模組,確認接線無誤後,將 USB 轉 TTL 模組插入電腦中,然後程式碼中執行 C# 程式,按鍵開啟序列埠,隨後發送資料,可以接收到微控制器的回饋。




結語
序列埠通訊是物聯網中,必不可少的一種通訊方式,通常情況下都是 RX 接 TX,TX 接 RX,除非是模組廠商的規定,否則都是這樣接線。在後面的課程中,我會依次對 IIC,以及 PWM、還有 SPI,以及中斷單獨做一個講解,歡迎大家關注,學習和探討,我會將我所知道的都會分享,同時,後面也會有 STM32 系列的教學。如果有感興趣的朋友,可以加 QQ 群一起來討論 822084696。
