串口通信

SerialPort类

SerialPort sp = new SerialPort("COM1"); 或者 SerialPort sp = new SerialPort();sp.PortName = "COM1";

这两种写法是等效的;获得串口“COM1”的操作权,就是创建一个SerialPort对象,然后对象的属性PortName初始化为指定的串口名“COM1”,即可用该对象操作串口“COM1”,如:设置串口的通信参数,打开串口,发送数据,接收数据,关闭串口等;

SerialPort类的重要属性:

(1)PortName   

    赋予哪个串口名字,就是操作哪个串口;

(2)DataBits   

      数据位的位数,有7,8,9三种情况,计算机编程语言认为8bit为一个字节,所以一般我们用8bit做为一帧数据帧的数据部分,这样数据帧到达接收方,接收方解析一个数据帧提取出数据位即是一个字节;

(3)Parity       

     奇偶校验的方式,Parity.Even 奇校验;Parity.Odd 偶校验;Parity.None 不校验;不校验数据帧,能增加传输数据的效率,但是通信的可靠性降低;

(4)StopBits     

    停止位的位数,StopBits.One    StopBits.OnePointFive    Two    指的是停止位持续几个电平;

(5)BaudRate   

    波特率,串口通信的速率,值越大串口传输数据越快;如果是异步串口通信的话,二者的波特率应该尽可能无限接近,允许有细微误差;同步串口通信的话,双方一般使用同一个时钟,保证通信双方的波特率严格一致;

检查机器上有无串口,串口的数量,具体串口名字

string[] GetPortName()
//返回的数组的Length ==0,表示无串口
//Length > 0时候,表示有串口,Length的大小就是串口的数量
//字符串数组的每一个元素就是串口的名字

打开串口和关闭串口

sp.IsOpen
//指示串口是否处于打开状态,true打开,false未打开;打开已经打开过的串口会抛出异常;
sp.Open()
//打开串口
sp.Close()
//关闭串口

 向串口写数据

public void Write(string)   //发送字符串
//假设sp的Encoding属性是ASCII,写入字符串“abc”,那么实际写入发送缓存3个字节;
//如果Encoding属性是Unicode,那么实际写入发送缓存6个字节;

public void Write(byte[],int32,int32) //发送字节数组
//第一个参数是函数外已经创建好的字节数组的引用,第二个参数是从字节数组的第几个字节开始写,一般为0,第三个参数表示本次要写入几个字节;

public void Write(char[],int32,int32)  //发送字符数组
//用法参考上述两个重载;特别说明,Encoding属性同样影响写入发送缓存的字节数量,不同的编码方式,虽然发送的是同一个字符数组,但是实际上写入发送缓存的字节数量不同!

public void WriteLine(string)  //发送一行字符串
//发送完string,紧接着向发送缓存写入一个NewLine字符串;

从串口读数据

public int Read (byte[] buffer, int offset, int count);
//返回读到的字节数量
public int Read (char[] buffer, int offset, int count);
//返回读到的字节数量
public int ReadByte();
//从SerialPort输入缓冲区同步读取一个字节
//如果读到末尾,返回-1
public int ReadChar()
//从SerialPort输入缓冲区同步读取一个字符

 读取数据可比发送数据复杂多了!

接收方接收到的数据都在接收缓存中,ReadBufferSize是设定的缓存的大小,默认是4096;BytesToRead表示缓存中暂存到的已经收到的字节数量;

当串口检查到有字节到达时,会触发DataReceived事件,ReceivedBytesThreshold属性能设置缓存中接收到多少字节后才触发该事件,默认是1。

值得注意的是,该事件在辅助线程中触发,所以并不能保证每个字节到达都能触发一次该事件。所以假设:

我收到10个字节,却只触发了2次;如果这两次读不干净缓存中的所有数据,那么剩下的数据在你下一次read()之前就一直留在缓存中而无法利用。

解决方案:

1,开辟一个线程,该线程实时检查BytesToRead,不为0就读取;

2,制定通信协议,在触发事件中,一直检查到结束字节,再停止

    private static void DataReceivedHandler(
                        object sender,
                        SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        Console.WriteLine("Data Received:");
        Console.Write(indata);
    }
原文地址:https://www.cnblogs.com/maoshuyi/p/9938349.html