欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用c#進(jìn)行串口通信的實(shí)現(xiàn)示例

 更新時(shí)間:2025年08月13日 11:18:13   作者:互聯(lián)網(wǎng)打工人no1  
本文主要介紹了使用c#進(jìn)行串口通信的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、串口通信協(xié)議

1.串口通信協(xié)議簡介

串口通信(serial communication)是一種設(shè)備間非常常用的串行通信方式,大部分電子設(shè)備都支持,電子工程師再調(diào)試設(shè)備時(shí)也經(jīng)常使用該通信方式輸出調(diào)試信息。講到某一種通信協(xié)議,離不開的就是物理層,物理層主要表現(xiàn)形式是電平信號(hào)的高低幅值,分別代表的狀態(tài)。 串口的物理層有很多標(biāo)準(zhǔn),主要包含RS232標(biāo)準(zhǔn),該標(biāo)準(zhǔn)規(guī)定了信號(hào)的用途、通信接口以及信號(hào)的電平標(biāo)準(zhǔn);

在上面的通訊方式中,兩個(gè)通訊設(shè)備的“DB9接口”之間通過串口信號(hào)線建立起連接,串口信號(hào)線中使用“RS-232標(biāo)準(zhǔn)”傳輸數(shù)據(jù)信號(hào)。
由于RS-232電平標(biāo)準(zhǔn)的信號(hào)不能直接被控制器直接識(shí)別,所以這些信號(hào)會(huì)經(jīng)過一個(gè)“電平轉(zhuǎn)換芯片”轉(zhuǎn)換成控制器能識(shí)別的“TTL校準(zhǔn)”的電平信號(hào),才能實(shí)現(xiàn)通訊。

電平標(biāo)準(zhǔn) 根據(jù)通信使用的電平標(biāo)準(zhǔn)不同,串口通信可以分為TTL標(biāo)準(zhǔn)和RS232標(biāo)準(zhǔn)

我們常見的電子電路中使用的TTL電平標(biāo)準(zhǔn),理想狀態(tài)下,使用5V表示二級(jí)制邏輯1,使用0V表示邏輯0,而為了增加串口通信的遠(yuǎn)距離傳輸以及抗干擾能力,它使用-15V表示邏輯1,+15V表示邏輯0,使用RS232與TTL電平標(biāo)準(zhǔn)表示同一個(gè)信號(hào)時(shí)的對比見圖

因?yàn)榭刂破饕话闶褂肨TL電平標(biāo)準(zhǔn),所以常常會(huì)使用MA3232芯片對TTL以及RS232電平信號(hào)進(jìn)行互相轉(zhuǎn)換。

RS-232信號(hào)線 在最初的應(yīng)用中,RS-232串口標(biāo)準(zhǔn)常用于計(jì)算機(jī)、路由與調(diào)制調(diào)解器(MODEN,俗稱“貓”)之間的通訊 ,在這種通訊系統(tǒng)中,設(shè)備被分為數(shù)據(jù)終端設(shè)備DTE(計(jì)算機(jī)、路由)和數(shù)據(jù)通訊設(shè)備DCE(調(diào)制調(diào)解器)。我們以這種通訊模型講解它們的信號(hào)線連接方式及各個(gè)信號(hào)線的作用。

在舊式的臺(tái)式計(jì)算機(jī)中一般會(huì)有RS-232標(biāo)準(zhǔn)的COM口(也稱DB9接口)

其中接線口以針式引出信號(hào)線的稱為公頭,以孔式引出信號(hào)線的稱為母頭。在計(jì)算機(jī)中一般引出公頭接口,而在調(diào)制調(diào)解器設(shè)備中引出的一般為母頭,使用上圖中的串口線即可把它與計(jì)算機(jī)連接起來。通訊時(shí),串口線中傳輸?shù)男盘?hào)就是使用前面講解的RS-232標(biāo)準(zhǔn)調(diào)制的。

在這種應(yīng)用場合下,DB9接口中的公頭及母頭的各個(gè)引腳的標(biāo)準(zhǔn)信號(hào)線接法見圖

上表中的是計(jì)算機(jī)端的DB9公頭標(biāo)準(zhǔn)接法,由于兩個(gè)通訊設(shè)備之間的收發(fā)信號(hào)(RXD與TXD)應(yīng)交叉相連,所以調(diào)制調(diào)解器端的DB9母頭的收發(fā)信號(hào)接法一般與公頭的相反,兩個(gè)設(shè)備之間連接時(shí),只要使用“直通型”的串口線連接起來即可

串口線中的RTS、CTS、DSR、DTR及DCD信號(hào),使用邏輯 1表示信號(hào)有效,邏輯0表示信號(hào)無效。例如,當(dāng)計(jì)算機(jī)端控制DTR信號(hào)線表示為邏輯1時(shí),它是為了告知遠(yuǎn)端的調(diào)制調(diào)解器,本機(jī)已準(zhǔn)備好接收數(shù)據(jù),0則表示還沒準(zhǔn)備就緒。

在目前的其它工業(yè)控制使用的串口通訊中,一般只使用RXD、TXD以及GND三條信號(hào)線,直接傳輸數(shù)據(jù)信號(hào)。而RTS、CTS、DSR、DTR及DCD信號(hào)都被裁剪掉了,如果您在前面被這些信號(hào)弄得暈頭轉(zhuǎn)向,那就直接忽略它們吧。

協(xié)議層 

串口通訊的數(shù)據(jù)包由發(fā)送設(shè)備通過自身的TXD接口傳輸?shù)浇邮赵O(shè)備的RXD接口。在串口通訊的協(xié)議層中,規(guī)定了數(shù)據(jù)包的內(nèi)容,它由啟始位、主體數(shù)據(jù)、校驗(yàn)位以及停止位組成,通訊雙方的數(shù)據(jù)包格式要約定一致才能正常收發(fā)數(shù)據(jù),其組成見下圖。

波特率

在串口異步通訊中由于沒有時(shí)鐘信號(hào)(如前面講解的DB9接口中是沒有時(shí)鐘信號(hào)的),所以兩個(gè)通訊設(shè)備之間需要約定好波特率,即每個(gè)碼元的長度,以便對信號(hào)進(jìn)行解碼常見的波特率為4800、9600、115200等。

  1. 通訊的起始和停止信號(hào) 串口通訊的一個(gè)數(shù)據(jù)包從起始信號(hào)開始,直到停止信號(hào)結(jié)束。數(shù)據(jù)包的起始信號(hào)由一個(gè)邏輯0的數(shù)據(jù)位表示,而數(shù)據(jù)包的停止信號(hào)可由0.5、1、1.5或2個(gè)邏輯1的數(shù)據(jù)位表示,只要雙方約定一致即可。
  2. 有效數(shù)據(jù) 在數(shù)據(jù)包的起始位之后緊接著的就是要傳輸?shù)闹黧w數(shù)據(jù)內(nèi)容,也稱為有效數(shù)據(jù),有效數(shù)據(jù)的長度常被約定為5、6、7或8位長。
  3. 數(shù)據(jù)校驗(yàn) 在有效數(shù)據(jù)之后,有一個(gè)可選的數(shù)據(jù)校驗(yàn)位。由于數(shù)據(jù)通信相對更容易受到外部干擾導(dǎo)致傳輸數(shù)據(jù)出現(xiàn)偏差,可以在傳輸過程加上校驗(yàn)位來解決這個(gè)問題。校驗(yàn)方法有奇校驗(yàn)(odd)、偶校驗(yàn)(even)、0校驗(yàn)(space)、1校驗(yàn)(mark)以及無校驗(yàn)(noparity),它們介紹如下:
    1. 奇校驗(yàn)要求有效數(shù)據(jù)和校驗(yàn)位中“1”的個(gè)數(shù)為奇數(shù),比如一個(gè)8位長的有效數(shù)據(jù)為:01101001,此時(shí)總共有4個(gè)“1”,為達(dá)到奇校驗(yàn)效果,校驗(yàn)位為“1”,最后傳輸?shù)臄?shù)據(jù)將是8位的有效數(shù)據(jù)加上1位的校驗(yàn)位總共9位。
    2. 偶校驗(yàn)與奇校驗(yàn)要求剛好相反,要求幀數(shù)據(jù)和校驗(yàn)位中“1”的個(gè)數(shù)為偶數(shù),比如數(shù)據(jù)幀:11001010,此時(shí)數(shù)據(jù)幀“1”的個(gè)數(shù)為4個(gè),所以偶校驗(yàn)位為“0”。
    3. 0校驗(yàn)是不管有效數(shù)據(jù)中的內(nèi)容是什么,校驗(yàn)位總為“0”,1校驗(yàn)是校驗(yàn)位總為“1”。

在無校驗(yàn)的情況下,數(shù)據(jù)包中不包含校驗(yàn)位。

二、程序連接串口操作

SerialPort類的常用API:
屬性:

常用方法

常用事件

代碼示例:

using System.IO.Ports;
using System.Text;

namespace SerialPortCommunication
{
    class Program
    {
        private static SerialPort serialPort;

        public static void Main()
        {
            #region 串口通信
            ConnectSerialPort("COM2");
            ClosePort();
            ReciveData();
            SendData();

            Console.ReadKey();
            #endregion
        }

        /// <summary>
        /// 接收串口數(shù)據(jù)
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private static void ReciveData()
        {
            // 連接串口
            var result = ConnectSerialPort("COM2");
            while(true)
            {
                if (result)
                {
                    // BytesToRead 代表串口中的字節(jié)大小
                    // 串口中的數(shù)據(jù)接收后,數(shù)據(jù)就被移除了。
                    var buffer = new byte[serialPort.BytesToRead];
                    // 接收發(fā)送的數(shù)據(jù)
                    #region 主動(dòng)接收
                    serialPort.Read(buffer, 0, buffer.Length);
                    var resultString = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
                    Console.WriteLine($"接收到結(jié)果: {resultString}");
                }
            }
            
            serialPort.Close();
            
            #endregion
        }

        /// <summary>
        /// 發(fā)送數(shù)據(jù)的方法
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private static void SendData()
        {
            // 連接串口
            var result = ConnectSerialPort("COM1");
            if (result)
            {
                // 發(fā)送數(shù)據(jù)
                //serialPort.Write("Hello SerialPort");
                //var buffer = new byte[] { 0x01, 0x02,0x03 };
                // 發(fā)送數(shù)據(jù)
                var buffer = Encoding.UTF8.GetBytes("中文");
                serialPort.Write(buffer, 0, buffer.Length);
                //serialPort.WriteBufferSize = 65535; // modbus 250
                //serialPort.WriteLine("Don't type chinese");
            }
            serialPort.Close();
        }

        /// <summary>
        /// 關(guān)閉串口的方法
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private static void ClosePort()
        {
            if (serialPort == null)
            {
                return;                                
            }
            serialPort.Close();
        }

        /// <summary>
        /// 連接串口的方法
        /// </summary>
        /// <returns></returns>
        private static bool ConnectSerialPort(string portName)
        {
            // 創(chuàng)建串口對象
            serialPort = new SerialPort();
            // 設(shè)置連接串口名稱
            serialPort.PortName = portName;
            // 設(shè)置波特率
            serialPort.BaudRate = 9600;
            // 設(shè)置數(shù)據(jù)位
            serialPort.DataBits = 8;
            // 設(shè)置停止位
            serialPort.StopBits = StopBits.One;
            // 設(shè)置校驗(yàn)位
            serialPort.Parity = Parity.None;
            serialPort.DataReceived += SerialPort_DataReceived;
            // 打開串口
            serialPort.Open();
            // 判斷串口是否成功打開
            if (serialPort.IsOpen)
            {
                Console.WriteLine("串口連接成功");
                return true;
            }
            else
            {
                Console.WriteLine("串口連接失敗");
            }

            return false;
        }

        /// <summary>
        /// 接收事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private static void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            var serialPort1 = sender as SerialPort;
            var buffer = new byte[serialPort1!.BytesToRead];
            serialPort1.Read(buffer, 0, buffer.Length);
            var resultString = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
            Console.WriteLine($"接收到結(jié)果: {resultString}");

        }
    }
}

到此這篇關(guān)于使用c#進(jìn)行串口通信的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)c# 串口通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#控件編程之顯示信息控件詳解(Label、LinkLabel)

    C#控件編程之顯示信息控件詳解(Label、LinkLabel)

    這篇文章主要介紹了C#控件編程之顯示信息控件詳解(Label、LinkLabel),具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • C# Request.Form用法案例詳解

    C# Request.Form用法案例詳解

    這篇文章主要介紹了C# Request.Form用法案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • c#并行編程示例分享

    c#并行編程示例分享

    這篇文章主要介紹了c#并行編程示例,大家直接看下面的代碼吧
    2014-01-01
  • C#實(shí)現(xiàn)文件與字符串互轉(zhuǎn)的方法詳解

    C#實(shí)現(xiàn)文件與字符串互轉(zhuǎn)的方法詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)文件與字符串互轉(zhuǎn)效果,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定幫助,需要的可以參考一下
    2022-08-08
  • C#中的for和foreach的性能對比

    C#中的for和foreach的性能對比

    這篇文章主要介紹了C#中的for和foreach的性能對比,在C#中,for和foreach是兩種常用的循環(huán)結(jié)構(gòu),用于迭代集合中的元素,盡管它們在功能上相似,但它們在性能、空間效率和垃圾回收(GC)方面有一些區(qū)別,需要的朋友可以參考下
    2023-10-10
  • C#解決訪問API顯示基礎(chǔ)連接已經(jīng)關(guān)閉的問題

    C#解決訪問API顯示基礎(chǔ)連接已經(jīng)關(guān)閉的問題

    最近在 Web 部署百度 AI 圖像識(shí)別 AipSdk.dll 封裝庫的時(shí)候,在調(diào)用OCR圖像識(shí)別 API 的時(shí)候,顯示為 “ 基礎(chǔ)連接已經(jīng)關(guān)閉: 接收時(shí)發(fā)生錯(cuò)誤,” ,并且運(yùn)行后直接崩潰,所以本文給大家介紹了C#解決訪問API顯示基礎(chǔ)連接已經(jīng)關(guān)閉的問題,需要的朋友可以參考下
    2024-12-12
  • c# 識(shí)別圖片格式的方法

    c# 識(shí)別圖片格式的方法

    這篇文章主要介紹了c# 識(shí)別圖片格式的方法,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-02-02
  • Unity3D 單例模式和靜態(tài)類的使用詳解

    Unity3D 單例模式和靜態(tài)類的使用詳解

    這篇文章主要介紹了Unity3D 單例模式和靜態(tài)類的使用詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • c# delegate和event的使用說明

    c# delegate和event的使用說明

    這篇文章主要介紹了c# delegate和event的使用說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • C#代碼實(shí)現(xiàn)PDF文檔操作類

    C#代碼實(shí)現(xiàn)PDF文檔操作類

    本篇文章給大家介紹使用pdf文檔操作C#代碼,本文代碼非常簡單,代碼附有注釋,需要注意的是:需要添加itextsharp.dll引用才可以正常通過編譯,感興趣的朋友可以參考下
    2015-10-10

最新評論