跨越网络工作室

跨越网络工作室专注于网站建设、游戏软件和行业软件开发,目标就是为客户提供最好的服务.qq:1578065783
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

开发经验分享-串口程序开发

Posted on 2011-05-07 20:41  跨越网络工作室  阅读(451)  评论(0)    收藏  举报

本工作室开发的项目不少,积累的开发经验不少。现在和各位分享。今天分享的是串口处理数据程序,它的作用是是将从从USB或者硬件串口获取到的数据进行读取并将数据存储到相应的位置。每接受一个字节,触发一次DataReceived事件,读取串口所有数据;使用一个优先级低于读取串口数据的线程,该线程首先解析获得一个完整的帧。

以下是主要的代码:

    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {//串口数据来到
            try
            {
                //this.InsertError("接收到串口数据" + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
                string str = this.serialPort1.ReadExisting();
               

                if (this.oThread == null || this.oThread.ThreadState == System.Threading.ThreadState.Stopped)
                {
                    this.oThread = new Thread(new ThreadStart(this.DealSerialData));
                    //this.InsertError("重新new接受处理线程:" + DateTime.Now.ToShortDateString());

                    //this.textBox1.Text = this.textBox1.Text + System.Environment.NewLine + "重新new线程";
                }
                if (this.oThread.ThreadState == System.Threading.ThreadState.Unstarted)
                {
                    this.oThread.Start();
                    //this.InsertError("串口接受数据处理线程重新开始");
                }
                this.TotalReadNum += str.Length;
                Byte[] byteArray = new Byte[str.Length];
                for (int i = 0; i < str.Length; i++)
                    byteArray[i] = Convert.ToByte(str[i]);
                lock (this.ByteArray)
                {
                   
                    this.ByteArray.InsertRange(this.ByteArray.Count, byteArray);//将从串口读取的数据放到未处理字节数组byteArray中
                    //this.InsertError("将串口数据复制到缓存中" + MyCommandByteArrayToStr(byteArray)+"复制后缓存长度:"+ByteArray.Count);
                }
            }
            catch (Exception ex)
            {
                this.InsertError("函数serialPort1_DataReceived出错" + ex.ToString());
            }

        }       

  private void DealSerialData()
        {
   //处理串口数据
            try
            {
                Thread.Sleep(10);
                //this.InsertError("进入串口接收数据处理线程");
                int ByteArrayLength = 0;
                lock (this.ByteArray)
                {
                    ByteArrayLength = this.ByteArray.Count;
                    //this.InsertError("串口数据长度:" + ByteArrayLength);
                }

                while (ByteArrayLength >= 4)
                {
                    //this.InsertError(ByteArrayLength);
                    string FrameControlByte = "0";//帧控制字
                    int FrameLength = -1;//帧总长度
                    ArrayList FrameByteArray = new ArrayList();//一个帧的字节数组
                    //this.InsertError("正在处理数据线程中");
                    bool HaveDeleteFrameHead = false;//是否已经删除帧头
                    while (ByteArrayLength >= 4)//至少要有4个字节才能开始解析
                    {
                        int deleteByteNum;//需要删除的字节数目
                        if (HaveDeleteFrameHead == false)
                        {//尚未删除帧头
                            lock (ByteArray)
                            {
                                if (Convert.ToByte(ByteArray[0]) == 0xaa && Convert.ToByte(ByteArray[1]) == 0x55)
                                {
                                    deleteByteNum = 2;
                                    this.ByteArray.RemoveRange(0, deleteByteNum);//删除帧头
                                    ByteArrayLength = ByteArrayLength - 2;
                                    HaveDeleteFrameHead = true;//读取本帧命令前,已经不需要再删除帧头,读取完一帧命令后,再将HaveDeleteFrameHead 设置为false

                                }
                                else
                                {
                                    deleteByteNum = 1;
                                    ByteArrayLength = ByteArrayLength - 1;
                                    this.ByteArray.RemoveRange(0, deleteByteNum);//删除一个错误字节
                                    this.InsertError("删除错误字节");
                                }

                            }
                        }


                        //帧头并不参与校验
                        lock (ByteArray)
                        {
                            FrameControlByte = this.MyByteToFixedLengthString(Convert.ToByte(this.ByteArray[0]));//第一个字节为帧控制字
                            FrameLength = 7 + Convert.ToInt32(this.ByteArray[1]);//ByteArray[1]为帧有效数据长度,加上控制、校验等7个字节
                            //this.InsertError("待处理的字节数" + this.ByteArray.Count.ToString() + " 帧长度" + FrameLength.ToString());
                        }
                        if (ByteArrayLength >= FrameLength)
                        {//如果当前帧已经完全读入,则复制当前帧的字节到CommByteArray中

                            // this.InsertError("待处理字节数大于帧长度,开始解析数据帧");
                            HaveDeleteFrameHead = false;
                            FrameByteArray.Clear();
                            for (int i = 0; i < FrameLength; i++)
                                FrameByteArray.Add(ByteArray[i]);
                            string strByteArray = "";
                            lock (this.ByteArray)
                            {
                                this.ByteArray.RemoveRange(0, FrameLength);
                                ByteArrayLength = ByteArray.Count;
                            }

                            this.WaitSerialTimeNum = 0;
                            this.DealReceiveCommandByteArray(FrameByteArray);//处理得到的字节帧
                        }
                        else
                        {
                            lock (this.ByteArray)
                            {
                                ByteArrayLength = ByteArray.Count;
                            }

                        }


                    }
                }
               
            }
            catch (Exception ex)
            {
                this.InsertError("函数DealSerialData出错" + ex.ToString());
            }
           
           
        }