常用小功能之串口数据传输

COM1

设计页面:

常用小功能之串口数据传输

源码:

       public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                SerialPort sp = new SerialPort(this.txtPort.Text, 9600, Parity.None, 8, StopBits.One);
                //SerialPort sp = new SerialPort(this.txtPort.Text);
                byte[] m = new byte[13];
                m[0] = 0x42;

                byte[] cardnoArr = System.Text.Encoding.ASCII.GetBytes(this.txtMsg.Text);

                for (int i = 1; i <= 10; i++ )
                {
                    if (i <= cardnoArr.Length)
                    {
                        m[i] = cardnoArr[i - 1];
                    }
                    else 
                    {
                        m[i] = 0x20;
                    }
                   
                }

                int v = 0;
                for (int i = 0; i < 11; i++ )
                {
                    v += m[i];
                }

                m[12] = (byte)(v);
                m[11] = (byte)(v >> 8);

                //打开新的串行端口连接
                sp.Open();
                //丢弃来自串行驱动程序的接受缓冲区的数据
                sp.DiscardInBuffer();
                //丢弃来自串行驱动程序的传输缓冲区的数据
                sp.DiscardOutBuffer();

                //使用缓冲区的数据将指定数量的字节写入串行端口
                sp.Write(m, 0, m.Length);
                //关闭端口连接
                sp.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            
        }

        private string StringToHexString(string s, Encoding encode)
        {
            byte[] b = encode.GetBytes(s);//按照指定编码将string编程字节数组
            string result = string.Empty;
            for (int i = 0; i < b.Length; i++)//逐字节变为16进制字符,以%隔开
            {
                result += "%" + Convert.ToString(b[i], 16);
            }
            return result;
        }

COM2

设计页面

常用小功能之串口数据传输

代码:

       public Form1()
        {
            InitializeComponent();
        }

        private ILog logger = LogManager.GetLogger(typeof(Form1));

        /// <summary>
        /// 接收串口数据线程
        /// </summary>
        private Thread recMsgThread;

        /// <summary>
        /// 解析数据处理队列
        /// </summary>
        private WorkQueue<byte[]> parseDataProcQueue = new WorkQueue<byte[]>();

        /// <summary>
        /// 刷卡事件处理队列
        /// </summary>
        private WorkQueue<long> creditCardEventProcQueue = new WorkQueue<long>();

        private SerialPort sp = null;

        private bool shouldStop = false;

        private void Form1_Load(object sender, EventArgs e)
        {
            parseDataProcQueue.WorkSequential = true;
            parseDataProcQueue.UserWork += new UserWorkEventHandler<byte[]>(ParsedData_UserWork);

            creditCardEventProcQueue.UserWork += new UserWorkEventHandler<long>(CreditCardEvent_UserWork); 
        }

        /// <summary>
        /// 接收串口数据
        /// </summary>
        private void RecPortMsg()
        {
            byte[] b;
            byte[] recArr;
            

            while (!shouldStop)
            {
                try
                {
                    sp = new SerialPort(txtPort.Text, 9600, Parity.None, 8, StopBits.One);
                    //sp = new SerialPort(txtPort.Text);
                    //打开新的串行端口连接
                    sp.Open();

                    logger.Info(string.Format("SerialPort open success.{0}", txtPort.Text));


                    //丢弃来自串行驱动程序的接受缓冲区的数据
                    sp.DiscardInBuffer();
                    //丢弃来自串行驱动程序的传输缓冲区的数据
                    sp.DiscardOutBuffer();

                    StringBuilder sb = new StringBuilder();

                    while (!shouldStop)
                    {
                        b = new byte[32];
                        //从串口输入缓冲区读取一些字节
                        int n = sp.Read(b, 0, b.Length);

                        if(n > 0)
                        {
                            recArr = new byte[n];

                            for (int i = 0; i < n; i++ )
                            {
                                recArr[i] = b[i];
                            }

                            //放入解析队列
                            parseDataProcQueue.EnqueueItem(recArr);
                        }

                        //当前线程挂起200毫秒
                        System.Threading.Thread.Sleep(200);
                    }
                }
                catch (Exception ex)
                {

                    logger.Error(string.Format("RecPortMsg error.{0}", ex.Message));
                }

                System.Threading.Thread.Sleep(2000);
            }

            if (null != sp)
            {
                //关闭端口连接
                sp.Close();
            }
            
        }


        //10进制卡号按以下格式编码(16进制):42 xx xx xx xx xx xx 20 20 20 20 HH LL
        //注:通信包定长13bytes,包头以'B'开始,16进制0x42;
        //后跟10位卡号,以16进制ASCII码值发送;
        //卡号不满10位时,后补0x20(空格);
        //校验码计算:前11位的16进制值累加,2bytes,高位bytes+低位bytes。


        //数据包
        private byte[] dataPacket = new byte[13];
        private int i_data = 0;
        private bool hasFind = false;

        /// <summary>
        /// 解析数据-工作处理
        /// </summary>
        private void ParsedData_UserWork(object sender, WorkQueue<byte[]>.EnqueueEventArgs e)
        {
            byte bStart = 0x42; //通讯包头部

            byte[] recArr = e.Item;

            try
            {
                foreach (byte b in recArr)
                {
                    if (b == bStart)
                    {
                        hasFind = true;
                        dataPacket = new byte[13];
                        i_data = 0;
                    }

                    if (hasFind)
                    {
                        if (i_data <= 12)
                        {
                            dataPacket[i_data++] = b;

                            if (i_data == 13) //完整包
                            {

                                //校验数据有效性
                                if (CheckDataValid(dataPacket))
                                {
                                    //解析获取卡号
                                    long cardno = parseCardNo(dataPacket);

                                    logger.InfoFormat("Rec CardNo:{0}", cardno);

                                    //回复
                                    if (null != sp)
                                    {
                                        byte[] postdata = new byte[2];
                                        //返回成功
                                        postdata[0] = 0x44;
                                        postdata[1] = 0x59;
                                        sp.Write(postdata, 0, postdata.Length);
                                    }


                                    //放入刷卡事件处理队列
                                    creditCardEventProcQueue.EnqueueItem(cardno);
                                }

                                hasFind = false;
                            }
                        }

                    }
                }
            }
            catch (Exception ex1)
            {
                logger.Error(string.Format("Parse data error.{0}", ex1.Message));
            }
            
        }

        /// <summary>
        /// 校验数据包是否是有效的
        /// 校验码计算:前11位的16进制值累加,2bytes,高位bytes+低位bytes。
        /// </summary>
        /// <param name="dataPacket"></param>
        /// <returns></returns>
        private bool CheckDataValid(byte[] dataPacket)
        {
            bool valid = false;

            int v = 0;
            for (int i = 0; i < 11; i++)
            {
                v += dataPacket[i];
            }

            byte LL = (byte)(v);
            byte HH = (byte)(v >> 8);

            if (dataPacket[11] == HH && dataPacket[12] == LL)
            {
                valid = true;
            }

            return valid;
        }

        //解析获取卡号
        private long parseCardNo(byte[] dataPacket) 
        {
            byte bSpace = 0x20; //空格

            //获取卡号
            string s_cardno = "";
            long cardno = 0;

            for (int i = 1; i < 11; i++)
            {
                if (dataPacket[i] != bSpace)
                {
                    s_cardno += (char)dataPacket[i];
                }

            }

            cardno = long.Parse(s_cardno);

            return cardno;
        }

        /// <summary>
        /// 刷卡事件-工作处理
        /// </summary>
        private void CreditCardEvent_UserWork(object sender, WorkQueue<long>.EnqueueEventArgs e)
        {
            long cardno = e.Item;
            ShowCardNo(cardno.ToString());
        }

        /// <summary>
        /// 显示卡号
        /// </summary>
        /// <param name="msg"></param>
        private void ShowCardNo(string msg)
        {
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(delegate { ShowCardNo(msg); }));
                return;
            }

            txtMsg.Text = msg;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            recMsgThread = new Thread(new ThreadStart(RecPortMsg));
            recMsgThread.Start();

            button1.Enabled = false;
            button2.Enabled = true;

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Stop();

            button2.Enabled = false;
            button1.Enabled = true;
            
        }


        private void Stop()
        {
            this.shouldStop = true;

            if (null != recMsgThread)
            {
                recMsgThread.Abort();
            }

            if (null != sp)
            {
                //关闭端口连接
                sp.Close();
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Stop();
        }