C# serial port communication search frame header algorithm, if version

Serial port communication usually needs to judge the frame header.


byte[] headbyte = new byte[]{
    
    0x5F,0x5F,0xF5,0xF5};
/// <summary>
/// 查找帧头, if版
/// </summary>
/// <param name="serialPort"></param>
/// <returns></returns>
public void ReadToPackHead(SerialPort serialPort)
{
    
    
    while (true)
    {
    
    
        if (serialPort.ReadByte() == headbyte[0])
        {
    
    
            if (serialPort.ReadByte() == headbyte[1])
            {
    
    
                if (serialPort.ReadByte() == headbyte[2])
                {
    
    
                    if (serialPort.ReadByte() == headbyte[3])
                    {
    
    
                        break;
                    }
                }
            }
        }
    }
}

I have to say that this version looks a bit silly, but from the perspective of easy understanding, it is much better than the while loop. Generally, when we design the frame header, it is generally not too long.

If you prefer the loop version, the code is as follows.

 // 查找帧头 , 循环版, 这个看起来就不是那么容易理解了
 public int ReadToPackHead(SerialPort serialPort)
 {
    
    
     int h = 1;
     while (h < serialPort.BytesToRead)
     {
    
    
         if (serialPort.ReadByte() == headbyte[0])
         {
    
    
             bool ishead = true;

             while (h < headbyte.Length)
             {
    
    
                 if (serialPort.ReadByte() == headbyte[h])
                 {
    
    
                     h++;
                 }
                 else
                 {
    
    
                     ishead = false;
                     break;
                 }
             }
             if (ishead)
             {
    
    
                 break;
             }
         }
     }
     return h;
 }

The main code for reading data from the serial port

if(serialPort.IsOpen ==false)
{
    
    
     serialPort.Open(); 
     Thread.Sleep(200);
 }

// 现在发送的命令返回的数据, 下次才能读取到.
 serialPort.Write(cmdGetData, 0, cmdGetData.Length);
 Thread.Sleep(500);
 

//找到起始帧
ReadToPackHead(serialPort);
//然后开始读取数据长度帧
byte[] lenbytes = new byte[2];
serialPort.Read(lenbytes, 0, 2);
int onePackLength = BitConverter.ToUInt16(lenbytes, 0);// 16位的数据, 按照8位发的所以需要*2
//pindex = pindex + 2;

Console.WriteLine("本包数据长度" + onePackLength);
//然后循环读取数据, 直到全部读取完整. 如果是小包的数据, 例如20个以下的, 会比较简单.
//但是如果数据量比较大, 则一次无法完全读取完毕所以应该要写入到buffer中然后进行合并.
byte[] onePackBuffer = new byte[onePackLength];
int newDataIndex = 0;

//这里使用循环的原因是, 串口的速度比较慢, 需要等串口把指定长度的数据都传过来之后再进行后续的处理.
while (newDataIndex < onePackLength)
{
    
    
    if (serialPort.BytesToRead == 0)
    {
    
    
        continue;
    }
    serialPort.Read(onePackBuffer, newDataIndex, onePackLength);
    newDataIndex = newDataIndex + serialPort.BytesToRead;
    Thread.Sleep(1);
}
              

Guess you like

Origin blog.csdn.net/phker/article/details/127088612