串口通信的同步与异步的理解与实现

一、 串口通信的基本原理

    串口通信:按位(bit)发送和接收字节的一种通信方式,其最重要的参数是波特率、数据位、停止位和奇偶校验位。

    1. 波特率:衡量符号传输速率的参数。波特率和距离成反比。

    2. 数据位:衡量通信中实际数据位的参数。实际数据位取决于通信协议。

    3. 停止位:用于表示单个包的最后一位。由于数据是在传输线上定时的,并且每一台设备都有自己的时钟,很可能在通信的两台设备间出现了一些不同步的情况。它不仅仅是表示传输的结束,也是计算机校正时钟同步的机会。

    4. 奇偶校验位:在串口通信中是一种检错方式。奇、偶、高、低、无。使得接收设备能够知道一个位的状态,有机会判断传输与接收数据是否不同步。

二、异步通信和同步通信

1 异步通信

1.1 异步通信的理解

    异步通信采用固定的通信格式,数据以相同的帧格式传送。每一帧由起始位、数据位、奇偶校验位和停止位组成。如下图,每一帧都是由起始位、数据位、奇偶校验位和停止位组成。

    
    在通信线上没有数据传送时处于逻辑“1”状态。当发送设备发送一个字符数据时,首先发出一个逻辑“0”信号,这个逻辑低电平就是起始位。起始位通过通信线传向接收设备,当接收设备检测到这个逻辑低电平后,就开始准备接收数据信号。因此,起始位所起的作用就是表示字符传送开始。

    起始位后面紧接着的是数据位,它可以是5位、6位、7位、或8位。数据传送时,低位在前。

    奇偶校验位用于数据传送过程中的数据检错,数据通信时通信双方必须约定一致的奇偶校验方式。就数据传送而言,奇偶校验位是冗余位,但它表示数据的一种性质。也有的不要校验位。

    在奇偶校验位或数据位后紧接的是停止位,停止位可以是一位、也可以是1.5位或2位。接收端收到停止位后,知道上一字符已传送完毕,同时,也为接收下一字符作好准备。若停止位后不是紧接着传送下一个字符,则让线路保持为“1”。“1”表示空闲位,线路处于等待状态。存在空闲位是异步通信的特性之一。

1.2 实现异步通信

private static SerialPort sp = null;

private void openCom()
{
    if (sp == null)
    {
        //string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits
        //串口名称,波特率,校验位,数据位,停止位
        sp = new SerialPort("COM1", 57600, Parity.Even, 8, StopBits.One);
        sp.ReceivedBytesThreshold = 5; //设置 System.IO.Ports.SerialPort.DataReceived 事件发生前内部输入缓冲区中的字节数,默认为1。小于或等于零时发生异常
        sp.DataReceived += new SerialDataReceivedEventHandler(readCom);//订阅委托
    }
    else
    {
        if (sp.IsOpen)
        {
            sp.Close();
            Thread.Sleep(200);
        }
    }
    sp.Open();
}

private void closeCom()
{
    if (sp == null) return;
    if (sp.IsOpen) { sp.Close(); }
}

private void readCom(object sender, SerialDataReceivedEventArgs e)
{
    var reVal = sp.ReadExisting();
    Console.WriteLine(reVal);//接收数据
}

private void writeCom(string comd)
{
    if (sp == null) return;
    if (!sp.IsOpen) { sp.Open(); }
    //Method one for hex
    byte[] hexComd = new ASCIIEncoding().GetBytes(comd);
    sp.Write(hexComd, 0, hexComd.Length);

    //Method two for ascii
    //sp.Write(comd);
}

2 同步通信

2.1 同步通信的理解

    同步通信时,通信双方共用一个时钟,这是同步通信区分于异步通信的最显著的特点。在异步通信中,每个字符要用起始位和停止位作为字符开始和结束的标志,以致占用了时间。所以在数据块传送时,为提高通信速度,常去掉这些标志,而采用同步通信。同步通信中,数据开始传送前用同步字符来指示(常约定1~2个),并由时钟来实现发送端和接收端的同步,即检测到规定的同步字符后,下面就连续按顺序传送数据,直到一块数据传送完毕。同步传送时,字符之间没有间隙,也不要起始位和停止位,仅在数据开始时用同步字符SYNC来指示,如下图。
    

2.2 实现同步通信

private static SerialPort sp = null;

private void openCom()
{
    if (sp == null)
    {
        //string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits
        //串口名称,波特率,校验位,数据位,停止位
        sp = new SerialPort("COM1", 57600, Parity.Even, 8, StopBits.One);
        // 获取或设置 System.IO.Ports.SerialPort 输入缓冲区的大小。默认值为 4096。
        sp.ReadBufferSize = 1024;
        //  获取或设置串行端口输出缓冲区的大小。默认值为 2048。
        sp.WriteBufferSize = 1024;
    }
    else
    {
        if (sp.IsOpen)
        {
            sp.Close();
            Thread.Sleep(200);
        }
    }
    sp.Open();
}

private void closeCom()
{
    if (sp == null) return;
    if (sp.IsOpen) { sp.Close(); }
}

private string writeCom(string comd)
{
    if (sp == null) return "";
    if (!sp.IsOpen) { sp.Open(); }
    //Method one for hex
    byte[] hexComd = new ASCIIEncoding().GetBytes(comd);
    sp.Write(hexComd, 0, hexComd.Length);

    //Method two for ascii
    //sp.Write(comd);

    //读取返回数据
    while (sp.BytesToRead == 0)
    {
        Thread.Sleep(1);
    }
    Thread.Sleep(100); //100毫秒内数据接收完毕,可根据实际情况调整
    byte[] recData = new byte[sp.BytesToRead];
    sp.Read(recData, 0, recData.Length);
    var recDataStr = Encoding.ASCII.GetString(recData);
    return recDataStr;
}

三、异步通信与同步通信的特点

1 同步通信

    进行数据传输时,发送和接收双方要保持完全的同步。因此,要求接收和发送设备必须使用同一时钟。优点是可以实现高速度、大容量的数据传送;缺点是要求发生时钟和接收时钟保持严格同步。
2 异步通信

    异步通信是按字符传输的。每传输一个字符就用起始位来进来收、发双方的同步。不会因收发双方的时钟频率的小的偏差导致错误。
    这种传输方式利用每一帧的起、止信号来建立发送与接收之间的同步。特点是:每帧内部各位均采用固定的时间间隔,而帧与帧之间的间隔时随机的。接收机完全靠每一帧的起始位和停止位来识别字符时正在进行传输还是传输结束。

    总结:不论是异步通信还是同步通信都需要进行同步,只是异步通信通过传送字符内的起始位来进行同步,而同步通信采用共用外部时钟来进行同步。所以,可以说前者是自同步,后者是外同步。

参考文献

[1] 串口通信异步通信与同步通信的区别
[2] 串口同步和异步理解

原文地址:https://www.cnblogs.com/wufanJY/p/13785424.html