【單晶片入門】(三)應用層軟體開發的單晶片學習之路-UART串列通訊和C#互動

【單晶片入門】(三)應用層軟體開發的單晶片學習之路-UART串列通訊和C#互動

UART串列通訊和C#串列進行通訊的一個案例,以及什麼是中斷,中斷的作用與實踐

最後更新 2022/10/25 下午9:58
陈显达
預計閱讀 9 分鐘
分類
分享
標籤
.NET C# 硬體相關

本文由網友投稿。

作者:陳顯達

原文標題:【微控制器入門】(三)應用層軟體開發的微控制器學習之路-----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。

繼續探索

延伸閱讀

更多文章
同分類 / 同標籤 2025/8/13

推薦一款高效能狀態機管理解決方案

在實際軟體開發中,尤其是工業軟體,每一款設備都有複雜的狀態以及狀態之間的切換的功能需求,在這種情況下,如何管理狀態以及狀態之間切換,和對應狀態下的功能控制,成為非常重要的一個問題。

繼續閱讀
同分類 / 同標籤 2025/3/18

(7)從護士到C#開發者--物件導向程式設計基礎

作為一名從護理行業轉行的程式設計師,我將分享如何透過醫護工作經驗來理解物件導向程式設計的概念。本文將介紹類別、物件、屬性、方法等物件導向的核心概念,並結合醫療保健領域的實例來加深理解。

繼續閱讀