工作项目总结(六)之串口通信

来源:互联网 发布:linux项目经理招聘 编辑:程序博客网 时间:2024/06/05 14:50

96、串口数据包组装

//串口数据包组装;I、首先创建类:CRecvBuf.cs/*http://wenku.baidu.com/view/cc833787bceb19e8b8f6ba53.html*/using System;using System.Collections.Generic;/// <summary>/// 创建数据接收队列/// CRecvBuf是一个用于缓存接收数据的类,利用List类来实现。/// 在创建该类的实例时,要制定参数maxLength,表示队列的总容量。/// 每当接收到一段数据,就调用Add方法将收到的数据添加到队列中,/// Add方法中判断添加数据后字节数是否超过maxLength,并将超过部分从队首删除。/// </summary>class CRecvBuf{    public List<byte> li;    public int maxLength;    public CRecvBuf(int maxLength)    {        li = new List<byte>();        this.maxLength = maxLength;    }    public void Add(byte[] b)    {        if (b.Length > maxLength)            throw new Exception("接收到得数据量超出缓冲区长度");        li.AddRange(b);        if (li.Count > maxLength)            li.RemoveRange(0, li.Count - maxLength);    }}


97、串口通信Com源码(一部分) 

  public partial class SerialportSampleForm : Form    {        private SerialPort comm = new SerialPort();           private StringBuilder builder = new StringBuilder();       //避免在事件处理方法中反复的创建,定义到外面。           private long received_count = 0;//接收计数           private long send_count = 0;//发送计数           private bool Listening = false;       //是否没有执行完invoke相关操作           private bool ComClosing = false;      //是否正在关闭串口,执行Application.DoEvents, 并阻止再次invoke           private CRecvBuf recvbuf;        WriteLog log = new WriteLog();        //string a="asas";        string dataAsyncstr = null;        string buffer = null;        private bool dataState = false;//数据包校验和判断标识        DTU_PacketBuf packetbuf = new DTU_PacketBuf();        //定义委托,它定义了可以代表的方法的类型        public delegate void GreetingDelegate(string name);               public SerialportSampleForm()        {            InitializeComponent();        }        private void SerialportSampleForm_Load(object sender, EventArgs e)        {            string[] ports = SerialPort.GetPortNames();            Array.Sort(ports);            comboPortName.Items.AddRange(ports);            comboPortName.SelectedIndex =            comboPortName.Items.Count > 0 ? 0 : -1;            comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("9600");            recvbuf = new CRecvBuf(120);//队列长度为数据帧长度的两倍            //comm.            //初始化SerialPort对象            comm.NewLine = "\r\n";            comm.RtsEnable = true;            //根据实际情况吧。            //添加事件注册            comm.DataReceived +=comm_DataReceived;             }        void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)        {            if (ComClosing)            {                return;            }            //如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环              try            {                Listening = true;                //设置标记,说明我已经开始处理数据,   一会儿要使用系统UI的。              /**************以下为按字节读取第一个字节数据再读取剩余字节数据将读取数据添加到队列队尾提取完整的数据帧***********/                byte firstbyte;                byte[] tmp;                comm.ReadTimeout = 5000;//5秒内没收到数据将捕获异常                received_count += comm.BytesToRead;//增加接收计数                   firstbyte = (byte)comm.ReadByte();//读取第一个字节,程序在这里堵塞                tmp = new byte[comm.BytesToRead + 1];                tmp[0] = firstbyte;                comm.Read(tmp, 1, tmp.Length - 1);//读取剩余字节到tmp数组中                this.Invoke((EventHandler)(delegate               {                   txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "tmp------->" + CCheck.BinaryToHexString(tmp));               }));                                   recvbuf.Add(tmp);//添加接收数据到队列                               //显示队列中全部数据                //txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "Recvbuf--->"+CCheck.BinaryToHexString(recvbuf.ge));                //提取一个完整的数据帧                tmp = getBlock(recvbuf.li);                //获取到一个数据包数据时,开始解析                if (tmp.Length >= 59)                {                    this.Invoke((EventHandler)(delegate                    {                        txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "tmpAsync-->" + CCheck.BinaryToHexString(tmp));                    }));                    AsyncPacket(tmp);                                }                this.Invoke((EventHandler)(delegate            {                if (tmp != null)                    txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "tmp!=null->" + CCheck.BinaryToHexString(tmp));                else                    txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "tmp==null->" + " ");            }));                /* *************************************************/                #region                /*******************************************                 int n = 59;                //int n = comm.BytesToRead;                //先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致                               //int n = comm.BytesToRead;                byte[] buf = new byte[n];                //声明一个临时数组存储当前来的串口数据                   //received_count += n;//增加接收计数                   comm.Read(buf, 0, n);//读取缓冲数据                   //comm.ReadByte();                //   builder.Clear();//清除字符串构造器的内容                 builder.Remove(0, builder.Length);                //因为要访问ui资源,所以需要使用invoke方式同步ui。                   this.Invoke((EventHandler)(delegate                {                    //判断是否是显示为16禁止                       if (checkBoxHexView.Checked)                    {                        //依次的拼接出16进制字符串                           foreach (byte b in buf)                        {                            builder.Append(b.ToString("X2") + " ");                        }                    }                    else                    {                        //依次的拼接出16进制字符串                           foreach (byte b in buf)                        {                            builder.Append(b.ToString("X2") + " ");                        }                        ////直接按ASCII规则转换成字符串                           //builder.Append("\r\n"+System.DateTime.Now.ToString()+"--->"+Encoding.ASCII.GetString(buf));                      }                    this.txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "--->" + builder.ToString());                    //修改接收计数                       labelGetCount.Text = "Get:" + received_count.ToString();                }));                  ******************************************/                #endregion            }            catch (Exception ex)            {                this.Invoke((EventHandler)(delegate                {                    txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "---------->" + ex.Message);                }));                log.ConnError("数据接收出错,详细为:"+ex.Message);            }            finally            {                Listening = false;//我用完了,ui可以关闭串口了。               }        }
}

98、

  #region        public static byte[] HexStringToBinary(string hexstring)//十六进制格式转换        {            string[] tmpary = hexstring.Trim().Split(' ');            byte[] buff = new byte[tmpary.Length];            for (int i = 0; i < buff.Length; i++)            {                buff[i] = Convert.ToByte(tmpary[i], 16);//转换            }            return buff;        }        #endregion        #region        /// <summary>        ///         /// </summary>        /// <param name="li"></param>        /// <returns></returns>        private byte[] getBlock(List<byte> li)        {            byte[] b = null;            if (li.Count < 59) return b;//总长度不足59字节            int p = li.Count;            //从右向左查找起始标志F0F1,获取下标            while ((p = li.LastIndexOf(0xF0, p - 1)) != -1)                if (li.Count >= p + 59)                    if (li[p + 1] == 0xF1&&li[p+57]==0xFE&&li[p+58]==0xFF)                        break;//已经找到,接收循环            if (p != -1)//p为数据块的起始位置            {                b = new byte[59];                li.CopyTo(p, b, 0, 59);//拷贝数据块到b数组            }            return b;        }        public class CCheck        {            //字节数组转换为十六进制字符串            public static string BinaryToHexString(byte[] buff)            {                StringBuilder tmp = new StringBuilder();                for(int i=0;i<buff.Length;i++)                    tmp.Append(buff[i].ToString("X2")+" ");                return tmp.ToString().Trim();            }        }        #endregion


99、

 #region        /// <summary>        /// 保存TextBox文本,   
        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void SaveBtn_Click(object sender, EventArgs e)        {//创建文件            FileStream fs;            //string ax = System.DateTime.Today.Date.ToString();            string ax = System.DateTime.Now.ToShortDateString();            //string filename = "E:/" + ax + ".txt";            string filename = System.Environment.CurrentDirectory+"\\data\\" + ax + ".txt";            if (File.Exists(filename))            {                fs = File.Open(filename, FileMode.Append);            }            else            {                fs = File.Create(filename);            }            //fs.Close();            string fswr = "";            try            {                fswr = txGet.Text;                byte[] str = System.Text.Encoding.Default.GetBytes(fswr);                fs.Write(str, 0, str.Length);                fs.Flush();                //UpdateDataViewTbxText("\r\n" + System.DateTime.Now.ToString() + "保存成功!");                this.Invoke((EventHandler)(delegate                {                    txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "---------->" + "保存成功!");                }));            }            catch (IOException ex)            {                log.ConnError("保存文件失败,原因为" + ex.Message);                //UpdateDataViewTbxText("\r\n" + System.DateTime.Now.ToString() + "保存失败:" + ex.Message);                this.Invoke((EventHandler)(delegate                {                    txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "---------->" + "保存失败!");                }));            }            finally            {                fs.Close();            }        }        #endregion

100、

  #region        /// <summary>        /// 进行包头包尾匹配        /// </summary>        /// <param name="data"></param>        /// <param name="dwLen"></param>        /// <returns></returns>        static int[] ExtractPacketLength(byte[] data)//,int[] Index        {            int[] Index = new int[2];            Index[0] = 0; Index[1] = 0;            //int StartIndex = 0, EndIndex = 0;            string datastr = DisplayByte(data);            string pattern = @"^F0F1";            Regex reg1 = new Regex(pattern);            if (reg1.IsMatch(datastr, 0))            {                Index[0] = 2;            }            string pattern2 = @"FEFF{1}quot;;            Regex reg2 = new Regex(pattern2);            if (reg2.IsMatch(datastr, 56))            {                Index[1] = 56;            }            return Index;        }        #endregion

101、

 #region        /// <summary>        /// 校验包头和包尾,校验和,长度        /// </summary>        /// <param name="data"></param>        /// <returns></returns>        private bool ReceivePacket(byte[] data)        {            //数据包正确标识            dataState = false;            //获取数据包位置            int[] index = ExtractPacketLength(data);            //找到数据包位置            if (index[1] > index[0] && index[0] != 0)// && data.Length == 28            {                byte[] Arraybyte = new byte[index[1] - index[0]];                Array.Copy(data, index[0], Arraybyte, 0, index[1] - index[0]);                //计算校验和                byte cs = GetCS(Arraybyte);                //对比数据                if (cs == data[index[1]])                {                    dataState = true;                }            }            return dataState;        }        #endregion


102、

 #region        /// <summary>        /// 解析温度-55~100,2个字节,第一位为符号位:(+/-)xx.x        /// </summary>        /// <param name="data"></param>        /// <returns></returns>        private string GetTemp(byte[] data)        {            decimal Para = 0.1M;            string temp = null;            //符号            string Symbol = null;            byte S = (byte)(data[1] >> 4);            if (S == 0x1)            {                Symbol = "-";            }            string tempStr = Symbol + (((byte)(data[0] << 4)) >> 4).ToString()                + (data[1] >> 4).ToString() + (((byte)(data[1] << 4)) >> 4).ToString();            temp = (Convert.ToInt32(tempStr) * Para).ToString();            return temp;        }        #endregion        #region        /// <summary>        /// 计算电压、电流 3字节(格式000.000)        /// </summary>        /// <param name="data"></param>        /// <returns></returns>        private string GetVacAndIac(byte[] data)        {            decimal multiplier = 0.001M;            //数据            string Effdata = null;            //数据位                       string datastr = (data[0] >> 4).ToString() + (((byte)(data[0] << 4)) >> 4).ToString()            + (data[1] >> 4).ToString() + (((byte)(data[1] << 4)) >> 4).ToString()            + (data[2] >> 4).ToString() + "" + (((byte)(data[2] << 4)) >> 4).ToString();            Effdata = (Convert.ToDecimal(datastr) * multiplier).ToString();            return Effdata;        }        #endregion        #region        /// <summary>        ///  3字节 有功、无功功率(格式+/-00000)        /// </summary>        /// <param name="data"></param>        /// <returns></returns>        private string GetPacData(byte[] data)        {            //数据            string Effdata = null;            //符号            string Symbol = null;            //符号位            byte S = (byte)(data[0] >> 4);            if (S == 0x1)            {                Symbol = "-";            }            //数据位(data[2] >> 4).ToString() +            string datastr = (((byte)(data[0] << 4)) >> 4).ToString()            + (data[1] >> 4).ToString() + "" + (((byte)(data[1] << 4)) >> 4).ToString()            + (data[2] >> 4).ToString() + "" + (((byte)(data[2] << 4)) >> 4).ToString();            Effdata = Symbol + Convert.ToInt32(datastr).ToString();            return Effdata;        }        #endregion        #region        /// <summary>        /// 解析电量 4字节        /// </summary>        /// <param name="data"></param>        /// <returns></returns>        private string GetPowerData(byte[] data)        {            decimal para = 0.01M;            string PowerData = null;            string PowerDatastr = data[0].ToString("X2")                      + data[1].ToString("X2")                      + data[2].ToString("X2")                      + data[3].ToString("X2");            PowerData = (Convert.ToDecimal(PowerDatastr) * para).ToString();            return PowerData;        }        #endregion        #region        /// <summary>        /// 总运行时间hr        /// </summary>        /// <param name="data"></param>        /// <returns></returns>        private string GetHTotal(byte[] data)        {            decimal para = 0.01M;            string HTotal = null;            string HTotalstr = data[0].ToString("X2")                      + data[1].ToString("X2")                      + data[2].ToString("X2")                      + data[3].ToString("X2");            HTotal = (Convert.ToDecimal(HTotalstr) * para).ToString();            return HTotal;        }        #endregion        #region        /// <summary>        /// 今日运行时间:分钟数        /// </summary>        /// <param name="data"></param>        /// <returns></returns>        private string GetTodayRunTime(byte[] data)        {            string RunTime = null;            string RunTimestr = data[0].ToString("X2")                      + data[1].ToString("X2");            RunTime = Convert.ToInt32(RunTimestr).ToString();            return RunTime;        }        #endregion


 

原创粉丝点击