C#實(shí)現(xiàn)串口通信詳解
前言
我們知道對(duì)于 標(biāo)準(zhǔn)DLL,可以采用DllImport進(jìn)行調(diào)用。
例如:
[DllImport("KMY350X.dll")]
private static extern int OpenPort(int PortNum, int BaudRate);
如果一些廠家比較懶的話,沒有提供相應(yīng)的dll,我們只能對(duì)它進(jìn)行串口通信編程了。
以前從沒接觸過串口編程,最近在一個(gè)項(xiàng)目中有幾個(gè)地方都需要采用串口通信,跟公司一個(gè)老手請(qǐng)教后,感覺學(xué)到了很多東西,特在此做個(gè)總結(jié)。
正文
一、首先我們來認(rèn)識(shí)下什么是串口
右鍵 我的電腦-管理-設(shè)備管理器-端口,選擇一個(gè)端口,點(diǎn)擊屬性。

我們可以看到該串口的屬性,在C#中我們使用SerialPort類來表示串口
ConfigClass config = new ConfigClass(); comm.serialPort.PortName = config.ReadConfig("SendHealCard");
//波特率
comm.serialPort.BaudRate = 9600;
//數(shù)據(jù)位
comm.serialPort.DataBits = 8;
//兩個(gè)停止位
comm.serialPort.StopBits = System.IO.Ports.StopBits.One;
//無奇偶校驗(yàn)位
comm.serialPort.Parity = System.IO.Ports.Parity.None;
comm.serialPort.ReadTimeout = 100;
comm.serialPort.WriteTimeout = -1;
二、串口調(diào)試工具
在對(duì)串口進(jìn)行編程時(shí)候,我們要向串口發(fā)送指令,然后我們解析串口返回的指令。
在這里向大家推薦一款工具。

將要發(fā)送的指令用空格隔開,選擇HEX顯示為放回的字符串。
三、正式編程
編寫Comm類
public class Comm
{
public delegate void EventHandle(byte[] readBuffer);
public event EventHandle DataReceived;
public SerialPort serialPort;
Thread thread;
volatile bool _keepReading;
public Comm()
{
serialPort = new SerialPort();
thread = null;
_keepReading = false;
}
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;
}
}
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);
if(DataReceived != null)
DataReceived(readBuffer);
Thread.Sleep(100);
}
catch (TimeoutException)
{
}
}
}
}
}
public void Open()
{
Close();
serialPort.Open();
if (serialPort.IsOpen)
{
StartReading();
}
else
{
MessageBox.Show("串口打開失敗!");
}
}
public void Close()
{
StopReading();
serialPort.Close();
}
public void WritePort(byte[] send, int offSet, int count)
{
if (IsOpen)
{
serialPort.Write(send, offSet, count);
}
}
}
注冊(cè)串口
Comm comm = new Comm();
ConfigClass config = new ConfigClass();
comm.serialPort.PortName = config.ReadConfig("SendHealCard");
//波特率
comm.serialPort.BaudRate = 9600;
//數(shù)據(jù)位
comm.serialPort.DataBits = 8;
//兩個(gè)停止位
comm.serialPort.StopBits = System.IO.Ports.StopBits.One;
//無奇偶校驗(yàn)位
comm.serialPort.Parity = System.IO.Ports.Parity.None;
comm.serialPort.ReadTimeout = 100;
ialPort.WriteTimeout = -1;
pen();
if (comm.IsOpen)
{
comm.DataReceived += new Comm.EventHandle(comm_DataReceived);
}
發(fā)送指令
/// <summary>
/// 發(fā)卡到機(jī)口
/// </summary>
private void SendCardToOut()
{
is_read_card = false;
sendCardToOut = true;
byte[] send = { 0x02, 0x46, 0x43, 0x34, 0x03, 0x30 };
if (comm.IsOpen)
{
comm.WritePort(send, 0, send.Length);
}
}
收到指令,并解析
void comm_DataReceived(byte[] readBuffer1)
{
//log.Info(HexCon.ByteToString(readBuffer));
if (readBuffer1.Length == 1)
{
receive = HealCardClass.ByteToString(readBuffer1);
string str = "06";
if (string.Equals(receive.Trim(), str, StringComparison.CurrentCultureIgnoreCase))
{
try
{
if (is_read_card)
{
byte[] send = new byte[1];
send[0] = 0x05;
comm.WritePort(send, 0, send.Length);
Thread.Sleep(500);
comm.DataReceived -= new Comm.EventHandle(comm_DataReceived);
InitReadComm();
}
if (sendCardToOut)
{
byte[] send = new byte[1];
send[0] = 0x05;
comm.WritePort(send, 0, send.Length);
readComm.DataReceived -= new Comm.EventHandle(readComm_DataReceived);
readComm.Close();
log.Info("發(fā)卡完成!");
lblMsg.Text = "發(fā)卡成功!";
lblSendCardMsg.Text = "發(fā)卡完成,請(qǐng)收好卡!";
timer1.Tick -= new EventHandler(timer1_Tick);
PlaySound();
this.btnOK.Enabled = true;
}
}
catch (Exception ex)
{
log.Info(ex.ToString());
}
}
}
}
至此,串口通信編程告一段落
最后
到此這篇關(guān)于C#實(shí)現(xiàn)串口通信詳解的文章就介紹到這了,更多相關(guān)C#串口通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# Char結(jié)構(gòu)中IsLetterOrDigit(Char)的方法詳解
這篇文章給大家介紹了C#的Char 結(jié)構(gòu)的IsLetterOrDigit(Char)的方法,并通過代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-02-02
C#實(shí)現(xiàn)餐飲管理系統(tǒng)完整版
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)餐飲管理系統(tǒng)的完整版,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
C#中sqlDataRead 的三種方式遍歷讀取各個(gè)字段數(shù)值的方法
這篇文章主要介紹了C#中 sqlDataRead 的三種方式遍歷讀取各個(gè)字段數(shù)值的方法,每種方法給大家介紹的都非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09
SQLite之C#版 System.Data.SQLite使用方法
這篇文章主要介紹了SQLite之C#版 System.Data.SQLite使用方法,需要的朋友可以參考下2020-10-10
c# 實(shí)現(xiàn)MD5,SHA1,SHA256,SHA512等常用加密算法源代碼
c# 如何實(shí)現(xiàn)MD5,SHA1,SHA256,SHA512等常用加密算法,需要的朋友可以參考下2012-12-12

