电子称串口读取数据(转)

时间:2024-03-05 12:27:43

 XK3168E 基本资料 
  分秤体跟仪表两部分,秤体即吊车下挂的部分,它跟仪表通过无线通讯,有效距离>100米,
  仪表部分有个串口,可以跟电脑串口连接,采用DB9连线,有2,3,5三根线,2,3两线交叉,5是地线,2,3线一根发数据一根是收数据
  将仪表的串口设置成9600波特率,8位无校验,连续模式
  当秤体有负重时仪表会每100毫秒发送帧数据,3.5分钟后每1秒发送,2.5小时后停止发送.

 串口通信的基本概念
 接收数据通过2号线一位一位的发送过来,每个位占用 1/BaudRate 秒时间
 波特率:即每秒种信号(电压)的最大改变次数,约等于每秒能发送多少bit
           串口采样按16倍波特率的频率进行 
 开始位:由空闲信号变成逻辑0,长度1bit
 数据位:即一桢中数据的位数,有,5,7,8等
 校验:即奇偶校验,长度1bit,可以不用
 停止位:一桢数据接受完后,空闲信号持续的时间,可以是1,2,1.5等(保持线路逻辑1时电压的时间,等于 1|2|1.5 * 1/波特率 (秒))
 数据帧: 开始位(1)+数据(5~8)+校验(0~1)+停止(1~2) 

 电子秤数据格式
 固定为 17个字节,采用ASCII,开始是stx(0x02) 结束是CL(0x13),1-3字节是状态子,4-9字节是重量信息10-15字节是皮重信息
 默认时4-9字节的重量信息的保留一位小数点,即在8与9字节间加入.

 代码

View Code
复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DotNet.ElecScales
{

    using System.IO.Ports;
    using System.Text;
    using System.Threading;
    /// <summary>
    /// 针对XK3168E
    /// 厂家:杭州福达电子设置厂
    /// 设置成 波特率9600, 8位无校验,连续模式
    /// 编写:Wdfrog
    /// http://www.cnblogs.com/wdfrog/archive/2012/10/25/2738257.html
    /// </summary>
    public class ElecScalesReader
    {
        #region 属性d定义
        /// <summary>
        /// 属性部分 
        /// </summary>
        private List<Byte> _BufferList = new List<byte>(1024 * 10);


        private byte C_STX = 0x02; //开始位标志
        private byte C_END = 0x0D; //结束位标志
        private int C_MaxQueueElem = 30;//队列里存放的最多元素个数
        private int C_FrameLength = 17;

        private bool Enabled = false;
        private Thread WorkThread { get; set; }



        //公开属性
        public Queue<GatherDataInfo> DataQueue { get; private set; }
        public SerialPort COMPort { get; private set; }
        public Exception LastError { get; set; }
        #endregion
        /// <summary>
        /// 构造
        /// </summary>
        public ElecScalesReader()
        {
            DataQueue = new Queue<GatherDataInfo>();

        }
        private void EnsureCOMPortOpen()
        {
            if (COMPort == null)
            {
                //配置COMPort
                COMPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
                COMPort.Encoding = Encoding.ASCII;
                //COMPort.DtrEnable = true;
            }
            if (!COMPort.IsOpen)
            {
                COMPort.Open();
            }
        }

        /// <summary>
        /// 格式-> 状态,读数,原始数据16进制表示,备注
        /// 状态-> 1:成功,0:无数据,4:错误
        /// </summary>
        /// <returns></returns>
        public string GetValue()
        {
            string valueTmp = "{0},{1},{2},{3}";//状态{1成功,0无数据,4错误},读数,原始数据16进制表示,备注
            try
            {
                if (WorkThread == null || WorkThread.IsAlive!=true )
                {
                    Launch();
                    Thread.Sleep(100);
                }
            }
            catch (Exception ex)
            {
                LastError = ex;
                return string.Format(valueTmp, "4", "", "", ex.Message);
            }

            GatherDataInfo data = new GatherDataInfo() { Status = 0, AddTime = DateTime.Now, Bytes = null, StrValue = Thread.CurrentThread.ManagedThreadId.ToString() + ":" + this.GetHashCode().ToString(), };
            lock (DataQueue)
            {
                if (DataQueue.Count > 0)
                {
                    data = DataQueue.Last();
                }
            }


            return string.Format(valueTmp, data.Status, data.StrValue, data.Bytes == null ? "" : BitConverter.ToString(data.Bytes.ToArray()), "");


        }
        /// <summary>
        /// 关闭COM
        /// </summary>
        public void Close()
        {
            this.Enabled = false;
            while (COMPort != null && COMPort.IsOpen) Thread.Sleep(10);
           
        }

        /// <summary>
        /// 启动
        /// </summary>
        private void Launch()
        {
            EnsureCOMPortOpen();
            Enabled = true;

            WorkThread = new Thread(DoReceive);
            WorkThread.IsBackground = true;
            WorkThread.Priority = ThreadPriority.Highest;
            WorkThread.Start();

        }
        private void DoReceive()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
            #region
            try
            {
                byte[] buffer = new byte[COMPort.ReadBufferSize];
                while (Enabled)
                {

                    Thread.Sleep(15);
                    if (COMPort.BytesToRead <= 0) continue;


                    var readLen = COMPort.Read(buffer, 0, COMPort.BytesToRead);

                    Array.Resize<byte>(ref buffer, readLen);
                    _BufferList.AddRange(buffer);
                    Array.Resize(ref buffer, COMPort.ReadBufferSize);

                    #region 数据解析
                    if (_BufferList.Count <= 0) return;
                    var stxIndex = _BufferList.IndexOf(C_STX);
                    if (stxIndex >= 0)
                    {
                        var endIndex = stxIndex + C_FrameLength - 1; //一个包17个字节
                        if (_BufferList.Count > endIndex)
                        {
                            byte[] frameBytes = new byte[C_FrameLength];
                            _BufferList.CopyTo(stxIndex, frameBytes, 0, C_FrameLength);
                            //清空该帧以及该帧前面的全部数据
                            _BufferList.RemoveRange(0, endIndex);
                            //验证有效性
                            if (frameBytes[frameBytes.Length - 1] == C_END)
                            {
                                var str = Encoding.ASCII.GetString(frameBytes, 4, 6);
                                var val = (str.Substring(0, 5) + "." + str.Substring(5, 1)).Trim();

                                //将数据入队列
                                var data = new GatherDataInfo() { Status = 1, AddTime = DateTime.Now, Bytes = new List<byte>(frameBytes), StrValue = val };
                                lock (DataQueue)
                                {
                                    DataQueue.Enqueue(data);
                                    if (DataQueue.Count > C_MaxQueueElem)
                                    {
                                        DataQueue.Dequeue();
                                    }
                                }

                            }
                            else
                            {
                                Console.WriteLine("无效帧,结尾不是CR符号!");
                            }

                            Console.WriteLine(BitConverter.ToString(frameBytes));
                        }


                    }
                    //已经收到17个字节但是还没有找到开始标志的
                    //则放弃缓存中的数据
                    if (_BufferList.Count > C_FrameLength && stxIndex < 0)
                    {
                        _BufferList.RemoveRange(0, _BufferList.Count);
                    }
                    #endregion



                }
            }
            catch (Exception ex)
            {
                LastError = ex;
                throw;
            }
            finally
            {
          
                if (COMPort != null && COMPort.IsOpen)
                {
                    COMPort.Close();
                }
            }
  #endregion

        }
    }




    /// <summary>
    /// 获取的有效桢信息
    /// </summary>
    public class GatherDataInfo
    {
        public DateTime? AddTime { get; set; }
        /// <summary>
        /// 字节信息
        /// </summary>
        public List<byte> Bytes { get; set; }
        /// <summary>
        /// 转化后的信息
        /// </summary>
        public string StrValue { get; set; }

        /// <summary>
        /// 1,有效果
        /// 0,无效
        /// </summary>
        public int Status { get; set; }
    }



    public class ElecScalesHelper
    {
        private static ElecScalesReader _Reader;
        public static ElecScalesReader Reader
        {
            get
            {
              
                if (_Reader == null)
                {

                    _Reader = new ElecScalesReader();

                }
         
                return _Reader;
            }

 

        }
        /// <summary>
        /// 格式-> 状态,读数,原始数据16进制表示,备注
        /// 状态-> 1:成功,0:无数据,4:错误
        /// </summary>
        /// <returns></returns>
        public static string GetValue()
        {
            lock (typeof(ElecScalesHelper))
            {
                return Reader.GetValue();
            }
            
        }
        /// <summary>
        /// 关闭COM
        /// </summary>
        public static string Close()
        {
         
                lock (typeof(ElecScalesHelper))
                {
                    Reader.Close();
                    _Reader = null;
                }
                return "";
        }
    }



}
复制代码

 参考资料
 http://cs.nju.edu.cn/yangxc/dcc2003.files/jszc-sub/comif-06.htm
 http://www.dotblogs.com.tw/billchung/category/5702.aspx?Show=All

 在线工具

 

http://www.cnblogs.com/wdfrog/archive/2012/10/25/2738257.html