C#串口通訊概念以及簡單實現

来源:https://www.cnblogs.com/ZaraNet/archive/2019/03/12/10510014.html
-Advertisement-
Play Games

最近在研究串口通訊,其中有幾個比較重要的概念,RS-232這種適配於上位機和PC端進行連接,RS-232只限於PC串口和設備間點對點的通信。它很簡單的就可以進行連接,由於串口通訊是非同步的,也就是說你可以同時向兩端或者更多進行數據發送,它們之間的傳輸數據類型是byte,串口通信最重要的參數是波特率、數 ...


  最近在研究串口通訊,其中有幾個比較重要的概念,RS-232這種適配於上位機和PC端進行連接,RS-232只限於PC串口和設備間點對點的通信。它很簡單的就可以進行連接,由於串口通訊是非同步的,也就是說你可以同時向兩端或者更多進行數據發送,它們之間的傳輸數據類型是byte,串口通信最重要的參數是波特率、數據位、停止位和奇偶校驗。對於兩個進行通信的埠,這些參數必須匹配。

  聽大佬說的幾個關於串口通訊的術語,啥?啥,這是啥?

  就讓我這個“小白”給你說說:第一個波特率,這個東西在不同領域都有涉及,在串口通訊中兩個串口之間通訊之間的信號單元叫做碼元,每分鐘傳遞的信號(碼元)也就是波特率;

  第二個數據位、停止位:這個聽名字就知道是啥意思了,在傳遞數據過程之前,機器會識別你的數據是個啥,然後根據這個類型,去調整不同的起始位、停止位。

  第三個奇偶校驗:就是想知道你這個數據有多大,多長,因為傳輸都是1 和 0 ,具體校驗方法如下:

奇校驗:就是讓原有數據序列中(包括你要加上的一位)1的個數為奇數     ----     1000110(0)你必須添0這樣原來有3個1已經是奇數了所以你添上0之後1的個數還是奇數個。

偶校驗:就是讓原有數據序列中(包括你要加上的一位)1的個數為偶數     ----      1000110(1)你就必須加1了這樣原來有3個1要想1的個數為偶數就只能添1了。

  如果想要在C#中玩轉串口通訊或者模擬串口,你必須先搞個硬體,當然我們是在模擬,那你就弄個模擬的工具唄,這個我給大家準備好了,自己去下載吧

鏈接:https://pan.baidu.com/s/1TcdgIWMY0i9BiKVGDxnAzQ 提取碼:9uap 

  安裝好了之後,桌面會有圖標,然後打開,添加一個串口,具體請看下圖

  下麵我們就開始代碼的實現了,創建一個.NET Fwk的 Winform 項目,然後開始我們的代碼!

SerialPort sp1 = new SerialPort();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string[] strCom = SerialPort.GetPortNames();
            if (strCom == null)
            {
                MessageBox.Show("本機沒有串口!", "Error");
                return;
            }
            foreach (string com in System.IO.Ports.SerialPort.GetPortNames())
            {
                cbCom.Items.Add(com);
            }
            cbCom.SelectedIndex = 0;
            sp1.BaudRate = 9600;
            Control.CheckForIllegalCrossThreadCalls = false;
            sp1.DataReceived += Sp1_DataReceived;

            sp1.DtrEnable = true;
            sp1.RtsEnable = true;
            sp1.ReadTimeout = 1000;
            sp1.Close();
        }

  在窗體載入中,我們嘗試獲取了本機的所有串口,通過 SerialPort.GetPortNames() 方法,會返回一個字元串數組,如果沒有就返回null,在其中,我們還設置了波特率,通過SerialPort類下的 DataReceived 方法,來監聽我們的數據回傳,還啟用了DTR\DTS請求方式,通過 ReadTimeOut 對數據讀取超時進行了控制。 

   既然我們監聽了數據回傳,那麼在這個方法中,通過 ReadTimeOut.Read 進行了讀取,直接從0到最後,截取完畢。

private void Sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (sp1.IsOpen)     //判斷是否打開串口
            {
                //輸出當前時間
                DateTime dt = DateTime.Now;
                txtReceived.Text += dt.GetDateTimeFormats('f')[0].ToString() + "\r\n";
                Byte[] receivedData = new Byte[sp1.BytesToRead];        //創建接收位元組數組
                sp1.Read(receivedData, 0, receivedData.Length);         //讀取數據
                AddContent(new UTF8Encoding().GetString(receivedData));
            }
            else
            {
                MessageBox.Show("請打開某個串口", "錯誤提示");
            }
        }

        private void AddContent(string v)
        {
            this.BeginInvoke(new MethodInvoker(delegate
            {
                txtReceived.AppendText(v);
                txtReceived.AppendText("\r\n");
            }));
        }

當然以上的操作都必須在打開串口之後才能進行,打開串口這個還是比較費勁的,因為要設置各種參數,也就是我剛纔說的那幾個概念,如果不對,你讓其他的埠來訪問就找不到了。

        private void button2_Click(object sender, EventArgs e)
        {
            if (!sp1.IsOpen)
            {
                try
                { 
                    string serialName = cbCom.SelectedItem.ToString();
                    sp1.PortName = serialName;
                    string strBaudRate = cbBaudRate.Text;
                    string strDateBits = cbDataBits.Text;
                    string strStopBits = cbStop.Text;
                    Int32 iBaudRate = Convert.ToInt32(strBaudRate);
                    Int32 iDateBits = Convert.ToInt32(strDateBits);
                    sp1.BaudRate = iBaudRate;       //波特率
                    sp1.DataBits = iDateBits;       //數據位
                    switch (cbStop.Text)            //停止位
                    {
                        case "1":
                            sp1.StopBits = StopBits.One;
                            break;
                        case "1.5":
                            sp1.StopBits = StopBits.OnePointFive;
                            break;
                        case "2":
                            sp1.StopBits = StopBits.Two;
                            break;
                        default:
                            MessageBox.Show("Error:參數不正確!", "Error");
                            break;
                    }
                    switch (cbCheck.Text)             //校驗位
                    {
                        case "":
                            sp1.Parity = Parity.None;
                            break;
                        case "奇校驗":
                            sp1.Parity = Parity.Odd;
                            break;
                        case "偶校驗":
                            sp1.Parity = Parity.Even;
                            break;
                        default:
                            MessageBox.Show("Error:參數不正確!", "Error");
                            break;
                    }

                    if (sp1.IsOpen == true)
                    {
                        sp1.Close();
                    }

                    //設置必要控制項不可用
                    cbCom.Enabled = false;
                    cbBaudRate.Enabled = false;
                    cbDataBits.Enabled = false;
                    cbStop.Enabled = false;
                    cbCheck.Enabled = false;
                    sp1.Open();     //打開串口
                    button2.Text = "關閉串口";
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show("Error:" + ex.Message, "Error");
                    return;
                }
            }
            else
            {
                cbCom.Enabled = true;
                cbBaudRate.Enabled = true;
                cbDataBits.Enabled = true;
                cbStop.Enabled = true;
                cbCheck.Enabled = true;
                sp1.Close();                    //關閉串口
                button2.Text = "打開串口";
            }
        }

最後也就是發送了,剛纔我們接收使用Read,發送也當然很簡單,是Write...

private void button1_Click(object sender, EventArgs e)
        {
            byte[] sendData = null;
            if (!sp1.IsOpen) //如果沒打開
            {
                MessageBox.Show("請先打開串口!", "Error");
                return;
            }
            String strSend = txtSendStr.Text;
            try
            {
                sendData = Encoding.UTF8.GetBytes(txtSendStr.Text.Trim());
                sp1.Write(sendData, 0, sendData.Length);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error:" + ex.Message, "Error");
            }

        }

還是非常簡單的。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • @[toc] 前言 有三個重要的類Claim, ClaimsIdentity, ClaimsPrincipal,我們以一個持有合法證件的學生Bob做比方,ClaimsPrincipal就是持有證件的學生Bob,ClaimsIdentity就是學生Bob的證件駕照,Claim就是Bob駕照中的各種信息 ...
  • 在虛擬機中安裝CentOS7碰到的問題以及解決方法 1.安裝之後想通過CRT遠程連接獲,輸入ifconfig查看系統ip報錯誤:ifconfig command not found,報此錯誤是由於初次安裝的CentOS是未啟用網路的,所以我們需要啟用網路 2.所以需要打開network,需執行如下命 ...
  • net core 和普通net 發佈沒有什麼不同,只需要在個別地方註意下: 1. 在visual Studio 2017 發佈 2. 把發佈好的文件copy到伺服器上,並新建一個網站,同時要註意選擇無托管代碼 3.此時訪問介面,會報錯,是因為沒有安裝 window server Hosting,它的 ...
  • 今天工作中遇到了一個情景: 前端向後臺發送一個請求,希望後臺返回一組數據,由於後臺返回的數據量很大,希望儘可能壓縮響應的大小 我的想法:後臺將數據(Short的數組)直接轉換成Byte[] 然後將byte[]發送至前端。 傳統的Json是將數據序列化成Json文件在發送到前端,這樣做的好處是處理簡單 ...
  • 系統:WIndows 10 工具:Visual Studio 2017 在寫代碼的過程中,我遇到了這樣的一個問題。如圖 vs錯誤提示是在SqlHelper中有錯,可是怎麼改都不能解決問題。 最後發現是前端往後端傳數據的時候,多寫了一個Id,如圖 在下麵編號中我已經回傳了一個Id的值,就不再需要一個h ...
  • ASP.NET Core 身份驗證及鑒權 目錄 + 項目準備 + 身份驗證 定義基本類型和介面 編寫驗證處理器 實現用戶身份驗證 + 許可權鑒定 思路 編寫過濾器類及相關介面 實現屬性註入 實現用戶許可權鑒定 + 測試 環境 + VS 2017 + ASP.NET Core 2.2 目標 以相對簡單優雅 ...
  • 昨天看碼雲上有兩個項目感覺很好, 可惜竟然不會Git 找了很久看了好多文檔看他寫的都好複雜啊! 在這我給寫出來一點點 1.下載Git https://git-scm.com/download/win 安裝 64-bit Git for Windows Setup. 這個版本。 2.在所需要下載的文件 ...
  • Electron.Net(結合Asp.Net Core)初次使用 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...