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

C#實(shí)現(xiàn)簡單串口通信

 更新時(shí)間:2022年02月21日 16:22:09   作者:RunnerDNA  
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)簡單串口通信,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

串口通信(Serial Communications)是指外設(shè)和計(jì)算機(jī)間通過數(shù)據(jù)信號(hào)線、地線等按位(bit)進(jìn)行傳輸數(shù)據(jù)的一種通信方式,屬于串行通信方式,能夠?qū)崿F(xiàn)遠(yuǎn)距離通信,長度可達(dá)1200米。盡管比按字節(jié)(byte)的并行通信慢,但是串口可以在使用一根線發(fā)送數(shù)據(jù)的同時(shí)用另一根線接收數(shù)據(jù)。串口通信最重要的參數(shù)是波特率、數(shù)據(jù)位、停止位和奇偶校驗(yàn)。對(duì)于兩個(gè)進(jìn)行通信的端口,這些參數(shù)必須匹配。

串口通信的接口標(biāo)準(zhǔn)有很多,有 RS-232C、RS-232、RS-422A、RS-485 等。常用的就是 RS-232 和 RS-485。串口通信使用的大多都是 DB9 接口,如下圖。

1 載波檢測(DCD) 2 接受數(shù)據(jù)(RXD) 3 發(fā)出數(shù)據(jù)(TXD) 4 數(shù)據(jù)終端準(zhǔn)備好(DTR) 5 信號(hào)地線(SG) 6 數(shù)據(jù)準(zhǔn)備好(DSR) 7 請(qǐng)求發(fā)送(RTS) 8 清除發(fā)送(CTS) 9 振鈴指示(RI)

這里我們以 RS-232 接口進(jìn)行演示。

1、數(shù)據(jù)包格式定為(10bytes):

幀頭(0xAA,0x55),命令字(1byte),地址位(2bytes),數(shù)據(jù)位(2bytes),校驗(yàn)位(1byte,和校驗(yàn)),幀尾(0xFE,0xFE)

地址位和數(shù)據(jù)位都是高位在前。

數(shù)據(jù)封裝方法:

//數(shù)據(jù)打包
private byte[] DataPackage(byte cmd, int addr, int data)
? ? ? ? {
? ? ? ? ? ? byte[] package = new byte[10];
? ? ? ? ? ? package[0] = 0xAA;//幀頭
? ? ? ? ? ? package[1] = 0x55;
? ? ? ? ? ? package[2] = cmd;//命令字 ? ?
? ? ? ? ? ? byte[] dataaddr = IntToByteArray(addr);
? ? ? ? ? ? package[3] = dataaddr[0];//地址高字節(jié)
? ? ? ? ? ? package[4] = dataaddr[1];//地址低字節(jié)
? ? ? ? ? ? byte[] value = IntToByteArray(data);
? ? ? ? ? ? package[5] = value[0];//數(shù)據(jù)高字節(jié)
? ? ? ? ? ? package[6] = value[1];//數(shù)據(jù)低字節(jié)
? ? ? ? ? ? package[7] = CheckSum(package);//校驗(yàn)位
? ? ? ? ? ? package[8] = 0xFE;//幀尾
? ? ? ? ? ? package[9] = 0xFE;
? ? ? ? ? ? return package;
? ? ? ? }
?
? ? ? ? //將int轉(zhuǎn)換成2位數(shù)組
? ? ? ? private static byte[] IntToByteArray(int value)
? ? ? ? {
? ? ? ? ? ? int hvalue = (value >> 8) & 0xFF;
? ? ? ? ? ? int lValue = value & 0xFF;
? ? ? ? ? ? byte[] arr = new byte[] { (byte)hvalue, (byte)lValue };
? ? ? ? ? ? return arr;
? ? ? ? }
?
? ? ? ? //得到和校驗(yàn)碼
? ? ? ? private byte CheckSum(byte[] package)
? ? ? ? {
? ? ? ? ? ? byte checksum = 0;
? ? ? ? ? ? for (int i = 0; i < package.Length; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? checksum += package[i];
? ? ? ? ? ? }
? ? ? ? ? ? return checksum;
? ? ? ? }

2、串口調(diào)用封裝類CommHelper.cs

internal class CommHelper
? ? {
? ? ? ? //委托
? ? ? ? public delegate void EventHandle(byte[] readBuffer);
? ? ? ? public event EventHandle DataReceived;
?
? ? ? ? public SerialPort serialPort;
? ? ? ? private Thread thread;
? ? ? ? volatile bool _keepReading;
?
? ? ? ? public CommHelper()
? ? ? ? {
? ? ? ? ? ? serialPort = new SerialPort();
? ? ? ? ? ??
? ? ? ? ? ? thread = null;
? ? ? ? ? ? _keepReading = false;
?
? ? ? ? ? ? serialPort.ReadTimeout = -1;
? ? ? ? ? ? serialPort.WriteTimeout = 1000;
? ? ? ? }
?
? ? ? ? //獲取串口打開狀態(tài)
? ? ? ? public bool IsOpen
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return serialPort.IsOpen;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //開始讀取
? ? ? ? private void StartReading()
? ? ? ? {
? ? ? ? ? ? if (!_keepReading)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? _keepReading = true;
? ? ? ? ? ? ? ? thread = new Thread(new ThreadStart(ReadPort));
? ? ? ? ? ? ? ? thread.Start();
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //停止讀取
? ? ? ? private void StopReading()
? ? ? ? {
? ? ? ? ? ? if (_keepReading)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? _keepReading = false;
? ? ? ? ? ? ? ? thread.Join();
? ? ? ? ? ? ? ? thread = null;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //讀數(shù)據(jù)
? ? ? ? private void ReadPort()
? ? ? ? {
? ? ? ? ? ? while (_keepReading)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (serialPort.IsOpen)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? int count = serialPort.BytesToRead;
? ? ? ? ? ? ? ? ? ? if (count > 0)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? byte[] readBuffer = new byte[count];
? ? ? ? ? ? ? ? ? ? ? ? try
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? Application.DoEvents();
? ? ? ? ? ? ? ? ? ? ? ? ? ? serialPort.Read(readBuffer, 0, count);
? ? ? ? ? ? ? ? ? ? ? ? ? ? DataReceived?.Invoke(readBuffer);
? ? ? ? ? ? ? ? ? ? ? ? ? ? Thread.Sleep(100);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? catch (TimeoutException)
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //寫數(shù)據(jù)
? ? ? ? public void WritePort(byte[] send, int offSet, int count)
? ? ? ? {
? ? ? ? ? ? if (IsOpen)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? serialPort.Write(send, offSet, count);
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //打開
? ? ? ? public void Open()
? ? ? ? {
? ? ? ? ? ? Close();
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? serialPort.Open();
? ? ? ? ? ? ? ? serialPort.RtsEnable = true;
? ? ? ? ? ? ? ? if (serialPort.IsOpen)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? StartReading();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? MessageBox.Show("串口打開失??!");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? catch
? ? ? ? ? ? {
?
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //關(guān)閉
? ? ? ? public void Close()
? ? ? ? {
? ? ? ? ? ? StopReading();
? ? ? ? ? ? serialPort.Close(); ? ? ? ? ? ?
? ? ? ? }
? ? }

3、調(diào)用(模擬測試讀寫硬件版本號(hào))

//地址存儲(chǔ)信息定義
private static int HARD_VERSION = 0;?? ??? ? ? ?//硬件版本號(hào)
? ? ? ?
//命令定義
private static byte RD_HV = 0;?? ??? ??? ? ? ?//讀硬件版本
private static byte WR_HV = 1;?? ??? ??? ? ? ?//寫硬件版本
?
private CommHelper comm = new CommHelper();
private bool GetCorrect = false; //用來標(biāo)識(shí)是否已經(jīng)接收到返回值
?
private List<byte> buffer = new List<byte>(1024);//默認(rèn)分配1M內(nèi)存,限制不能超過
private byte[] binary_data = new byte[10];//指定格式的某個(gè)完整數(shù)據(jù)
?
//串口初始化
private void InitComm()
? ? ? ? {
? ? ? ? ? ? comm.serialPort.PortName = "COM1";
? ? ? ? ? ? comm.serialPort.BaudRate = 19200;
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? comm.Open();
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception ex)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? MessageBox.Show(ex.Message);
? ? ? ? ? ? }
? ? ? ? ? ? if (comm.IsOpen)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? comm.DataReceived += new CommHelper.EventHandle(comm_DataReceived);
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //數(shù)據(jù)接收后處理
? ? ? ? private void comm_DataReceived(byte[] readBuffer)
? ? ? ? {
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? buffer.AddRange(readBuffer);//將數(shù)據(jù)放到緩存中
? ? ? ? ? ? ? ? //完整性判斷
? ? ? ? ? ? ? ? while (buffer.Count >= 10)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? //查找數(shù)據(jù)頭
? ? ? ? ? ? ? ? ? ? if (buffer[0] == 0xAA && buffer[1] == 0x55)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? //和校驗(yàn)
? ? ? ? ? ? ? ? ? ? ? ? byte checksum = 0;
? ? ? ? ? ? ? ? ? ? ? ? for (int i = 0; i < 7; i++)
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? checksum += buffer[i];
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? if (checksum != buffer[7])
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? buffer.RemoveRange(0, 10);//如果校驗(yàn)失敗,從緩存中刪除這一包數(shù)據(jù)
? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? buffer.CopyTo(0, binary_data, 0, 10);//復(fù)制一條完整的數(shù)據(jù)到具體的數(shù)據(jù)緩存
?
? ? ? ? ? ? ? ? ? ? ? ? //讀取硬件版本號(hào)
? ? ? ? ? ? ? ? ? ? ? ? if (binary_data[2] == RD_HV && ByteArrayToInt(binary_data[3], binary_data[4]) == HARD_VERSION)//命令字為讀RD_HV,地址HARD_VERSION
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? GetCorrect = true;
? ? ? ? ? ? ? ? ? ? ? ? ? ? string data = ByteArrayToString(binary_data[5], binary_data[6]);
? ? ? ? ? ? ? ? ? ? ? ? ? ? //這里可以處理數(shù)據(jù)更新界面展示
? ? ? ? ? ? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? ? ? ? ? ? buffer.RemoveRange(0, 10);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? GetCorrect = false;
? ? ? ? ? ? ? ? ? ? ? ? buffer.RemoveAt(0);//如果數(shù)據(jù)開始不是頭,則刪除數(shù)據(jù)
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? catch
? ? ? ? ? ? {
?
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //將2位數(shù)組轉(zhuǎn)換成字符串
? ? ? ? private static string ByteArrayToString(byte arr1, byte arr2)
? ? ? ? {
? ? ? ? ? ? int value = ByteArrayToInt(arr1, arr2);
? ? ? ? ? ? string str = Convert.ToString(value, 10);
? ? ? ? ? ? return str;
? ? ? ? }
?
? ? ? ? //將2位數(shù)組轉(zhuǎn)換成10進(jìn)制數(shù)
? ? ? ? private static int ByteArrayToInt(byte arr1, byte arr2)
? ? ? ? {
? ? ? ? ? ? byte[] arr = new byte[] { arr1, arr2 };
? ? ? ? ? ? int value = (int)((arr[0] & 0xFF) << 8)
? ? ? ? ? ? ? ? ? ? ? | (arr[1] & 0xFF);
? ? ? ? ? ? return value;
? ? ? ? }
?
? ? ? ? //讀取硬件版本號(hào)
? ? ? ? private void ReadHV()
? ? ? ? {
? ? ? ? ? ? GetCorrect = false;
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? comm.WritePort(DataPackage(RD_HV, HARD_VERSION, 0), 0, 10);//發(fā)送RD_E2P命令,地址HARD_VERSION
? ? ? ? ? ? ? ? Delay(100);
? ? ? ? ? ? ? ? if (GetCorrect == true)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? MessageBox.Show("硬件版本號(hào)讀取成功!");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? MessageBox.Show("硬件版本號(hào)讀取失?。?);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception ex)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? MessageBox.Show(ex.Message);
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //寫入硬件版本號(hào)
? ? ? ? private void WriteHV()
? ? ? ? {
? ? ? ? ? ? if (tbVersion.Text.Length == 4 && isLegal(tbVersion.Text))//限定只能寫入4個(gè)字符且輸入合法
? ? ? ? ? ? {
? ? ? ? ? ? ? ? try
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? int buf = Convert.ToInt32(tbVersion.Text);
? ? ? ? ? ? ? ? ? ? GetCorrect = false;
? ? ? ? ? ? ? ? ? ? comm.WritePort(DataPackage(WR_HV, HARD_VERSION, buf), 0, 10);//發(fā)送WR_HV命令,地址HARD_VERSION
? ? ? ? ? ? ? ? ? ? Delay(100);
? ? ? ? ? ? ? ? ? ? if (GetCorrect == true)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? MessageBox.Show("硬件版本號(hào)寫入成功!");
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? MessageBox.Show("硬件版本號(hào)寫入失敗!");
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? catch (Exception ex)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? MessageBox.Show(ex.Message);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? MessageBox.Show("硬件版本號(hào)數(shù)據(jù)格式錯(cuò)誤!請(qǐng)重新寫入!");
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? //判斷輸入是否合法,必須是數(shù)字
? ? ? ? private const string PATTERN = @"^[0-9]*$";
? ? ? ? private bool isLegal(string hex)
? ? ? ? {
? ? ? ? ? ? return System.Text.RegularExpressions.Regex.IsMatch(hex, PATTERN);
? ? ? ? }
?
? ? ? ? //延時(shí)函數(shù)
? ? ? ? [DllImport("kernel32.dll")]
? ? ? ? static extern uint GetTickCount();
? ? ? ? static void Delay(uint ms)
? ? ? ? {
? ? ? ? ? ? uint start = GetTickCount();
? ? ? ? ? ? while (GetTickCount() - start < ms)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Application.DoEvents();
? ? ? ? ? ? }
? ? ? ? }

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#實(shí)現(xiàn)選擇排序

    C#實(shí)現(xiàn)選擇排序

    這篇文章介紹了C#實(shí)現(xiàn)選擇排序的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • WPF實(shí)現(xiàn)自繪儀表盤Gauge

    WPF實(shí)現(xiàn)自繪儀表盤Gauge

    這篇文章主要為大家詳細(xì)介紹了如何使用WPF實(shí)現(xiàn)自繪儀表盤Gauge效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • UGUI繪制動(dòng)態(tài)曲線

    UGUI繪制動(dòng)態(tài)曲線

    這篇文章主要為大家詳細(xì)介紹了UGUI繪制動(dòng)態(tài)曲線的具體方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • C#中Json反序列化的實(shí)現(xiàn)方法

    C#中Json反序列化的實(shí)現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于C#中Json反序列化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-06-06
  • C#中的靜態(tài)成員、靜態(tài)方法、靜態(tài)類介紹

    C#中的靜態(tài)成員、靜態(tài)方法、靜態(tài)類介紹

    本文主要介紹了C#中的靜態(tài)成員、靜態(tài)方法、靜態(tài)類的基礎(chǔ)的使用,并做了相關(guān)的代碼演示,供初學(xué)者參考。
    2016-03-03
  • C#中值類型和引用類型解析

    C#中值類型和引用類型解析

    這篇文章主要為大家詳細(xì)介紹了C#中值類型和引用類型的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • C#文件分割的方法

    C#文件分割的方法

    這篇文章主要介紹了C#文件分割的方法,針對(duì)小于等于64M文件和大于64M文件兩種情況分析了C#文件分割的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-07-07
  • C#使用FileStream復(fù)制一個(gè)任意文件

    C#使用FileStream復(fù)制一個(gè)任意文件

    這篇文章主要為大家詳細(xì)介紹了C#使用FileStream復(fù)制一個(gè)任意文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • C#通過流寫入數(shù)據(jù)到文件的方法

    C#通過流寫入數(shù)據(jù)到文件的方法

    這篇文章主要介紹了C#通過流寫入數(shù)據(jù)到文件的方法,涉及C#通過字節(jié)流讀寫文件的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • WPF MVVM示例講解

    WPF MVVM示例講解

    WPF技術(shù)的主要特點(diǎn)是數(shù)據(jù)驅(qū)動(dòng)UI,所以在使用WPF技術(shù)開發(fā)的過程中是以數(shù)據(jù)為核心的,WPF提供了數(shù)據(jù)綁定機(jī)制,當(dāng)數(shù)據(jù)發(fā)生變化時(shí),WPF會(huì)自動(dòng)發(fā)出通知去更新UI,這篇文章通過示例讓大家體驗(yàn)下WPF MVM,有需要的朋友可以參考下
    2015-08-08

最新評(píng)論