C#串口数据处理--环形缓冲区-FIFO

 一、FIFO环形缓冲区初始化

        static int MAX_BUFFER_LEN = 1024;//定义缓冲区大小
        FIFO receiveBufferManager = new FIFO(MAX_BUFFER_LEN);

 二、串口接收事件中添加写入环形缓冲

 int num = serialPort1.BytesToRead;      //获取接收缓冲区中的字节数
                byte[] received_buf = new byte[num];    //声明一个大小为num的字节数据用于存放读出的byte型数据
                serialPort1.Read(received_buf, 0, num);   //读取接收缓冲区中num个字节到byte数组中
                if (num > 0)
                {
                     receiveBufferManager.WriteBuffer(received_buf, 0,num);
                }

三、开一个线程解析数据,测试中串口以10ms的周期发送大量数据,然后在线程中以1s的速度去解析数据,数据依然不会丢失。

private void serialPort1_DataReceived1(object o)
        {
            try
            {
                byte[] freame_byte = new byte[1024];
                byte[] freame_byte1 = new byte[1024];
                while (true)
                {
                    if (receiveBufferManager.GetDataCount() > 0)
                    {
                        receiveBufferManager.ReadBuffer(freame_byte, 0, 5);
                        receiveBufferManager.ReadBuffer(freame_byte1, 0,freame_byte[2]);
                        Console.Write("数据=");
                        for (int i = 0; i < freame_byte[2]; i++)
                        {
                            Console.Write("{0:X000} ", freame_byte1[i]);
                        }
                        Console.WriteLine("");
                         receiveBufferManager.Clear(freame_byte[2]);
                    }
                    else { Console.WriteLine("缓冲区没有数据"); }
                    Thread.Sleep(1000);
               }
            }
            catch
            {

            }
        }

四、环形缓冲区实现类

public class RingBufferManager
{
    public byte[] Buffer { get; set; } // 存放内存的数组
    public int DataCount { get; set; } // 写入数据大小
    public int DataStart { get; set; } // 数据起始索引
    public int DataEnd { get; set; }   // 数据结束索引
    public RingBufferManager(int bufferSize)
    {
        DataCount = 0; DataStart = 0; DataEnd = 0;
        Buffer = new byte[bufferSize];
    }

    public byte this[int index]
    {
        get
        {
            if (index >= DataCount) throw new Exception("环形缓冲区异常,索引溢出");
            if (DataStart + index < Buffer.Length)
            {
                return Buffer[DataStart + index];
            }
            else 
            {
                return Buffer[(DataStart + index) - Buffer.Length];
            }
        }
    }

    public int GetDataCount() // 得到当前写入的字节数
    {
        return DataCount;
    }

    public int GetReserveCount() // 得到剩余的字节数
    {
        return Buffer.Length - DataCount;
    }

    public void Clear()
    {
        DataCount = 0;
    }

    public void Clear(int count) // 清空指定大小的数据
    {
        if (count >= DataCount) // 若是须要清理的数据大于现有数据大小,则所有清理
        {
            DataCount = 0;
            DataStart = 0;
            DataEnd = 0;
        }
        else
        {
            if (DataStart + count >= Buffer.Length)
            {
                DataStart = (DataStart + count) - Buffer.Length;
            }
            else 
            {
                DataStart += count;
            }
            DataCount -= count;
        }
    }

    public void WriteBuffer(byte[] buffer, int offset, int count)
    {
        Int32 reserveCount = Buffer.Length - DataCount;
        if (reserveCount >= count)                          // 可用空间够使用
        {
            if (DataEnd + count < Buffer.Length)            // 数据没到结尾
            {
                Array.Copy(buffer, offset, Buffer, DataEnd, count);
                DataEnd += count;
                DataCount += count;
            }
            else           //  数据结束索引超出结尾 循环到开始
            {
                System.Diagnostics.Debug.WriteLine("缓存从新开始....");
                Int32 overflowIndexLength = (DataEnd + count) - Buffer.Length;      // 超出索引长度
                Int32 endPushIndexLength = count - overflowIndexLength;             // 填充在末尾的数据长度
                Array.Copy(buffer, offset, Buffer, DataEnd, endPushIndexLength);
                DataEnd = 0;
                offset += endPushIndexLength;
                DataCount += endPushIndexLength;
                if (overflowIndexLength != 0)
                {
                    Array.Copy(buffer, offset, Buffer, DataEnd, overflowIndexLength);
                }
                DataEnd += overflowIndexLength;                                     // 结束索引
                DataCount += overflowIndexLength;                                   // 缓存大小
            }
        }
        else 
        {
            // 缓存溢出,不处理
        }
    }

    public void ReadBuffer(byte[] targetBytes,Int32 offset, Int32 count) 
    {
        if (count > DataCount) throw new Exception("环形缓冲区异常,读取长度大于数据长度");
        Int32 tempDataStart = DataStart;
        if (DataStart + count < Buffer.Length)
        {
            Array.Copy(Buffer, DataStart, targetBytes, offset, count);
        }
        else 
        {
            Int32 overflowIndexLength = (DataStart + count) - Buffer.Length;    // 超出索引长度
            Int32 endPushIndexLength = count - overflowIndexLength;             // 填充在末尾的数据长度
            Array.Copy(Buffer, DataStart, targetBytes, offset, endPushIndexLength);
            
            offset += endPushIndexLength;
            
            if (overflowIndexLength != 0)
            {
                Array.Copy(Buffer, 0, targetBytes, offset, overflowIndexLength);
            }
        }
    }


    public void WriteBuffer(byte[] buffer)
    {
        WriteBuffer(buffer, 0, buffer.Length);
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值