串口通信总结

一:串口通信总结

搬运自博客园:http://www.cnblogs.com/binfire/archive/2011/10/08/2201973.html

 

我们知道对于 标准DLL,可以采用DllImport进行调用。例如:

[DllImport("KMY350X.dll")]
private static extern int OpenPort(int PortNum, int BaudRate);

如果一些厂家比较懒的话,没有提供相应的dll,我们只能对它进行串口通信编程了。以前从没接触过串口编程,最近在一个项目中有几个地方都需要采用串口通信,跟公司一个老手请教后,感觉学到了很多东西,特在此做个总结:

 

一:首先我们来认识下什么是串口:

 

右键 我的电脑-管理-设备管理器-端口,选择一个端口,点击属性。

 

 

我们可以看到该串口的属性,在C#中我们使用SerialPort类来表示串口

 

复制代码
ConfigClass config = new ConfigClass();
comm.serialPort.PortName = config.ReadConfig("SendHealCard");
//波特率
comm.serialPort.BaudRate = 9600;
//数据位
comm.serialPort.DataBits = 8;
//两个停止位
comm.serialPort.StopBits = System.IO.Ports.StopBits.One;
//无奇偶校验位
comm.serialPort.Parity = System.IO.Ports.Parity.None;
comm.serialPort.ReadTimeout = 100;
comm.serialPort.WriteTimeout = -1;
复制代码

二:串口调试工具:

在对串口进行编程时候,我们要向串口发送指令,然后我们解析串口返回的指令。在这里向大家推荐一款工具。

串口调试助手.exe

 

 

 

将要发送的指令用空格隔开,选择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);
}
}
}
复制代码

注册串口:

 

复制代码
Comm comm = new Comm();
ConfigClass config = new ConfigClass();
comm.serialPort.PortName = config.ReadConfig("SendHealCard");
//波特率
comm.serialPort.BaudRate = 9600;
//数据位
comm.serialPort.DataBits = 8;
//两个停止位
comm.serialPort.StopBits = System.IO.Ports.StopBits.One;
//无奇偶校验位
comm.serialPort.Parity = System.IO.Ports.Parity.None;
comm.serialPort.ReadTimeout = 100;
comm.serialPort.WriteTimeout = -1;

comm.Open();
if (comm.IsOpen)
{
comm.DataReceived += new Comm.EventHandle(comm_DataReceived);
}
复制代码

发送指令:

 

复制代码
///


/// 发卡到机口
///

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("发卡完成!");
lblMsg.Text = "发卡成功!";
lblSendCardMsg.Text = "发卡完成,请收好卡!";
timer1.Tick -= new EventHandler(timer1_Tick);
PlaySound();
this.btnOK.Enabled = true;


}
}
catch (Exception ex)
{
log.Info(ex.ToString());
}
}
}
}
复制代码

 

 

搬运自博客园:http://www.cnblogs.com/doucontorl/archive/2010/08/06/serialport.html

C# 串口 通信

串口的基本概念

目前较为常用的串口有9针串口(DB9)和25针串口(DB25),通信距离较近时(<12m),可以用电缆线直接连接标准RS232端口(RS422,RS485较远),若距离较远,需附加调制解调器(MODEM)。最为简单且常用的是三线制接法,即地、接收数据和发送数据三脚相连。

 

1.DB9和DB25的常用信号脚说明

 

 9针串口(DB9)

25针串口(DB25)

针号

功能说明

缩写

针号

功能说明

缩写

1

数据载波检测

DCD

8

数据载波检测

DCD

2

接收数据

RXD

3

接收数据

RXD

3

发送数据

TXD

2

发送数据

TXD

4

数据终端准备

DTR

20

数据终端准备

DTR

5

信号地

GND

7

信号地

GND

6

数据设备准备好

DSR

6

数据准备好

DSR

7

请求发送

RTS

4

请求发送

RTS

8

清除发送

CTS

5

清除发送

CTS

9

振铃指示

DELL

22

振铃指示

DELL

 

 

2.RS232C串口通信接线方法(三线制)

首先,串口传输数据只要有接收数据针脚和发送针脚就能实现:同一个串口接收脚和发送脚直接用线相连,两个串口相连或一个串口和多个串口相连

· 同一个串口接收脚和发送脚直接用线相连 对9针串口和25针串口,均是2与3直接相连;

两个不同串口(不论是同一台计算机的两个串口或分别是不同计算机的串口

9针-9针
25针-25针
9针-25针
2
3
3
2
2
2
3
2
2
3
3
3
5
5
7
7
5
7

上面表格是对微机标准串行口而言的,还有许多非标准设备,如接收GPS数据或电子罗盘数据,只要记住一个原则:接收数据针脚(或线)与发送数据针脚(或线)相连,彼此交叉,信号地对应相接,就能百战百胜。

3.串口调试中要注意的几点:

串口调试时,准备一个好用的调试工具,如串口调试助手、串口精灵等,有事半功倍之效果; 
强烈建议不要带电插拨串口,插拨时至少有一端是断电的,否则串口易损坏。

4.奇偶校验

串行数据在传输过程中,由于干扰可能引起信息的出错,例如,传输字符‘E’,其各位为:

0100,0101=45H

由于干扰,0可能使位变为1,这种情况,我们称为出现了“误码”。我们把如何发现传输中的错误,叫“检错”。发现错误后,如何消除错误,叫“纠错”。

最简单的检错方法是“奇偶校验”,即在传送字符的各位之外,再传送1位奇/偶校验位。可采用奇校验或偶校验.

奇校验:所有传送的数位(含字符的各数位和校验位)中,“1”的个数为奇数,如:

1 0110,0101

0 0110,0001

偶校验:所有传送的数位(含字符的各数位和校验位)中,“1”的个数为偶数,如:

1 0100,0101

奇偶校验能够检测出信息传输过程中的部分误码(1位误码能检出,2位及2位以上误码不能检出),同时,它不能纠错。在发现错误后,只能要求重发。但由于其实现简单,仍得到了广泛使用。

5.串口通讯流控制

这里讲到的“流”,当然指的是数据流。数据在两个串口之间传输时,常常会出现丢失数据的现象,或者两台计算机的处理速度不同,如台式机与单片机之间的通讯,接收数据缓冲区已满,则此时继续发送来的数据就会丢失。现在我们在网络上通过MODEM进行数据传输,这个问题就尤为突出。流控制能解决这个问题,当接收数据处理不过来时,就发出“不再接收”的信号,发送端就停止发送,直到收到“可以继续发送”的信号再发送数据。因此流控制可以控制数据传输的进程,防止数据的丢失。 PC机中常用的两种流控制是硬件流控制(包括RTS/CTS、DTR/CTS等)和软件流控制XON/XOFF(继续/停止),下面分别说明。

<1>.硬件流控制
硬件流控制常用的有RTS/CTS流控制和DTR/DSR(数据终端就绪/数据设置就绪)流控制。
硬件流控制必须将相应的电缆线连上,用RTS/CTS(请求发送/清除发送)流控制时,应将通讯两端的RTS、CTS线对应相连,数据终端设备(如计算机)使用RTS来起始调制解调器或其它数据通讯设备的数据流,而数据通讯设备(如调制解调器)则用CTS来起动和暂停来自计算机的数据流。这种硬件握手方式的过程为:我们在编程时根据接收端缓冲区大小设置一个高位标志(可为缓冲区大小的75%)和一个低位标志(可为缓冲区大小的25%),当缓冲区内数据量达到高位时,我们在接收端将CTS线置低电平(送逻辑0),当发送端的程序检测到CTS为低后,就停止发送数据,直到接收端缓冲区的数据量低于低位而将CTS置高电平。RTS则用来标明接收设备有没有准备好接收数据
常用的流控制还有还有DTR/DSR(数据终端就绪/数据设置就绪)。

<2>软件流控制
由于电缆线的限制,我们在普通的控制通讯中一般不用硬件流控制,而用软件流控制。一般通过XON/XOFF来实现软件流控制。常用方法是:当接收端的输入缓冲区内数据量超过设定的高位时,就向数据发送端发出XOFF字符(十进制的19或Control-S,设备编程说明书应该有详细阐述),发送端收到XOFF字符后就立即停止发送数据;当接收端的输入缓冲区内数据量低于设定的低位时,就向数据发送端发出XON字符(十进制的17或Control-Q),发送端收到XON字符后就立即开始发送数据。一般可以从设备配套源程序中找到发送的是什么字符。
应该注意,若传输的是二进制数据,标志字符也有可能在数据流中出现而引起误操作,这是软件流控制的缺陷,而硬件流控制不会有这个问题。

SerialPort类的属性和方法

名  称

说  明

BaseStream

获取 SerialPort 对象的基础 Stream 对象

BaudRate

获取或设置串行波特率

BreakState

获取或设置中断信号状态

BytesToRead

获取接收缓冲区中数据的字节数

BytesToWrite

获取发送缓冲区中数据的字节数

CDHolding

获取端口的载波检测行的状态

CtsHolding

获取“可以发送”行的状态

DataBits

获取或设置每个字节的标准数据位长度

DiscardNull

获取或设置一个值,该值指示 Null 字节在端口和接收缓冲区之间传输时是否被忽略

DsrHolding

获取数据设置就绪 (DSR) 信号的状态

DtrEnable

获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号

Encoding

获取或设置传输前后文本转换的字节编码

Handshake

获取或设置串行端口数据传输的握手协议

IsOpen

获取一个值,该值指示 SerialPort 对象的打开或关闭状态

NewLine

获取或设置用于解释 ReadLine( )和WriteLine( )方法调用结束的值

Parity

获取或设置奇偶校验检查协议

名  称

说  明

ParityReplace

获取或设置一个字节,该字节在发生奇偶校验错误时替换数据流中的无效字节

PortName

获取或设置通信端口,包括但不限于所有可用的 COM 端口

ReadBufferSize

获取或设置 SerialPort 输入缓冲区的大小

ReadTimeout

获取或设置读取操作未完成时发生超时之前的毫秒数

ReceivedBytesThreshold

获取或设置 DataReceived 事件发生前内部输入缓冲区中的字节数

RtsEnable

获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号

StopBits

获取或设置每个字节的标准停止位数

WriteBufferSize

获取或设置串行端口输出缓冲区的大小

WriteTimeout

获取或设置写入操作未完成时发生超时之前的毫秒数

方法

方 法 名 称

说  明

Close

关闭端口连接,将 IsOpen 属性设置为False,并释放内部 Stream 对象

Open

打开一个新的串行端口连接

Read

从 SerialPort 输入缓冲区中读取

ReadByte

从 SerialPort 输入缓冲区中同步读取一个字节

ReadChar

从 SerialPort 输入缓冲区中同步读取一个字符

ReadLine

一直读取到输入缓冲区中的 NewLine 值

ReadTo

一直读取到输入缓冲区中指定 value 的字符串

Write

已重载。将数据写入串行端口输出缓冲区

WriteLine

将指定的字符串和 NewLine 值写入输出缓冲区

发送接收实例

 

SerialPort serialPort1;
private void button1_Click(object sender, EventArgs e)
         {
             serialPort1.PortName = "COM1";
             serialPort1.BaudRate = 9600;
             serialPort1.Open();
             byte[] data = Encoding.Unicode.GetBytes(textBox1.Text);
             string str = Convert.ToBase64String(data);
             serialPort1.WriteLine(str);
             MessageBox.Show("数据发送成功!","系统提示");
         }
         private void button2_Click(object sender, EventArgs e)
         {
             byte[] data = Convert.FromBase64String(serialPort1.ReadLine());
             textBox2.Text = Encoding.Unicode.GetString(data);
             serialPort1.Close();
             MessageBox.Show("数据接收成功!","系统提示");
         }

 

 

 
 

转载于:https://www.cnblogs.com/plexus/p/7056155.html

你可能感兴趣的:(串口通信总结)