c# 串口

記錄一下事件通過。數組

如今的項目是採集儀表的數據。之前都是配置好串口,波特率,數據位,中止位,校驗位而後就能夠接受儀表發送來的數據進行解析了。緩存

如今遇到了一種新的儀表,分爲兩個模式。一個是數據模式,像其餘儀表同樣,將儀表的數據主動發送給串口,可是不能接受命令數據。一種是命令模式,能夠接受命令數據,可是不會主動發送數據。也就是說你想要實現遠程控制儀表,給他發送命令的話,就須要主動發送獲取數據的命令去主動讀數。this

/// <summary>
/// 串口類
/// </summary>
private SerialPort _spCom;  這是微軟提供的串口類spa

/// <summary>
        ///     打開串口,並註冊數據接收方法
        /// </summary>
        /// <returns></returns>
        public bool Open()
        {
            var rtn = false;
            if (_curWeightCfg != null)//_curWeightCfg 是從配置文件中讀取配置的串口信息,COM口,波特率,數據位,中止位,校驗位
            {
                WeightDeviceLogger.Debug(
                    string.Format("設置串口參數。ComPort={0},Baudrate={1},DataBits={2}, Parity={3},StopSize={4}",
                        _curWeightCfg.ComPort, _curWeightCfg.Baudrate, _curWeightCfg.ByteSize, _curWeightCfg.Parity,
                        _curWeightCfg.StopSize));

                _spCom = new SerialPort(_curWeightCfg.ComPort, int.Parse(_curWeightCfg.Baudrate))
                {
                    DataBits = _curWeightCfg.ByteSize,
                    ReadBufferSize = 100
                };
               
                //奇偶校驗
                if (_curWeightCfg.Parity == ParityType.Even)
                {
                    _spCom.Parity = Parity.Odd;
                }
                else if (_curWeightCfg.Parity == ParityType.Odd)
                {
                    _spCom.Parity = Parity.Even;
                }
                else
                {
                    _spCom.Parity = Parity.None;
                }
                //中止位
                if (_curWeightCfg.StopSize == StopBitsType.One)
                {
                    _spCom.StopBits = StopBits.One;
                }
                else if (_curWeightCfg.StopSize == StopBitsType.OnePointFive)
                {
                    _spCom.StopBits = StopBits.OnePointFive;
                }
                else if (_curWeightCfg.StopSize == StopBitsType.Two)
                {
                    _spCom.StopBits = StopBits.Two;
                }
                else
                {
                    _spCom.StopBits = StopBits.None;
                }

                _spCom.DataReceived += new SerialDataReceivedEventHandler(_spCom_DataReceived);
                try
                {
                    WeightDeviceLogger.Debug("表頭打開串口。IsOpen=" + _spCom.IsOpen);
                    _spCom.Open();
                    _closeComPort = false;

                    ThreadStart ts1 = GetWeight;// 開啓一個線程,發送讀取數據命令,以後讀取數據,解析數據,再經過委託事件傳遞給程序
                    _threadWeight1 = new Thread(ts1)
                    {
                        IsBackground = true,//表示後臺線程
                    };
                    _threadWeight1.Start();

                    WeightDeviceLogger.Debug("啓動表頭獲取數據線程成功。");
                    
                    rtn = true;
                }
                catch (Exception ex)
                {
                    WeightDeviceLogger.Error("打開表頭失敗。", ex);
                    ShowErrorMsg(ErrorType.Error, "打開串口失敗.");
                }
            }
            else
            {
                WeightDeviceLogger.Error("表頭配置信息不存在。");
                ShowErrorMsg(ErrorType.Error, "配置信息不存在.");
            }
            return rtn;
        }
/// <summary>
        ///     提取重量數據
        /// </summary>
        private void GetWeight()
        {
            while (true)
            {
                if (_spCom.IsOpen)
                {
                    if (isclearzero)
                    {
                        continue;
                    }

                    try
                    {
                        Thread.Sleep(100);

                        ComSend(s1);//發送獲取數據命令  s1是儀表廠家提供的讀數命令16進制字符"01 03 00 01 00 04 15 C9"

                        var readDataLen = _spCom.BytesToRead;//獲取接受緩衝區的字節數
                        var buf = new byte[readDataLen];//建立一個和接收區字節數同樣的字節數組用來接收數據
                        _isDataReceiving = true;
                        Thread.Sleep(100);//發送讀數命令以後要等一會再讀取數據
                        var length = _spCom.Read(buf, 0, readDataLen);//從緩衝區讀取readDataLen長度的數據寫入buf字節數組
                        _isDataReceiving = false;
                        if (length <= 0) continue;

                        var aaa = System.Text.Encoding.Default.GetString(buf);//將字節數組轉換成字符串
                        var weightTemp = aaa.Substring(3, 7);//從字符串中截取使用的那幾位數據

                        if (!_canRaiseWeightDataEvent) continue;//判斷程序是否暫停取數

                        OnGetWeightData(weightTemp, "");//將數據發送給程序使用
                    }
                    catch(Exception e)
                    {
                        WeightDeviceLogger.Debug("讀取數據線程出現錯誤"+e.Message);
                    }

                }
            }
            
        }
private void ComSend(string obj)//發送數據 獨立線程方法 發送數據時UI能夠響應
        {
            if (Sending)
            {
                return;
            }
            //lock (this)//因爲send()中的if (Sending == true) return,因此這裏不會產生阻塞,若是沒有那句,屢次啓動該線程,會在此處排隊
            {
                Sending = true;//正在發生狀態字
                byte[] sendBuffer = null;//發送數據緩衝區
                string sendData = obj;//複製發送數據,以避免發送過程當中數據被手動改變
                if (true)//16進制發送
                {
                    try //嘗試將發送的數據轉爲16進制Hex
                    {
                        sendData = sendData.Replace(" ", "");//去除16進制數據中全部空格
                        sendData = sendData.Replace("\r", "");//去除16進制數據中全部換行
                        sendData = sendData.Replace("\n", "");//去除16進制數據中全部換行
                        if (sendData.Length == 1)//數據長度爲1的時候,在數據前補0
                        {
                            sendData = "0" + sendData;
                        }
                        else if (sendData.Length % 2 != 0)//數據長度爲奇數位時,去除最後一位數據
                        {
                            sendData = sendData.Remove(sendData.Length - 1, 1);
                        }

                        List<string> sendData16 = new List<string>();//將發送的數據,2個合爲1個,而後放在該緩存裏 如:123456→12,34,56
                        for (int i = 0; i < sendData.Length; i += 2)
                        {
                            sendData16.Add(sendData.Substring(i, 2));
                        }
                        sendBuffer = new byte[sendData16.Count];//sendBuffer的長度設置爲:發送的數據2合1後的字節數
                        for (int i = 0; i < sendData16.Count; i++)
                        {
                            sendBuffer[i] = (byte)(Convert.ToInt32(sendData16[i], 16));//發送數據改成16進制
                        }
                    }
                    catch //沒法轉爲16進制時,出現異常
                    {
                        WeightDeviceLogger.Debug("沒法轉爲16進制時,出現異常");
                        Sending = false;//關閉正在發送狀態
                        //_spCom.Abort();//終止本線程
                        return;//輸入的16進制數據錯誤,沒法發送,提示後返回  
                    }

                }
                else //ASCII碼文本發送
                {
                    sendBuffer = System.Text.Encoding.Default.GetBytes(sendData);//轉碼
                }
                try//嘗試發送數據
                {//若是發送字節數大於1000,則每1000字節發送一次
                    //int sendTimes = (sendBuffer.Length / 1000);//發送次數
                    //for (int i = 0; i < sendTimes; i++)//每次發生1000Bytes
                    //{
                    //    //_spCom.Write(sendBuffer, sendTimes * 1000, sendBuffer.Length % 1000);
                    //    _spCom.Write(sendBuffer, 0, sendBuffer.Length); //發送sendBuffer中從第i * 1000字節開始的1000Bytes
                    //}
                    //if (sendBuffer.Length % 1000 != 0)//發送字節小於1000Bytes或上面發送剩餘的數據
                    //{
                    //    //_spCom.Write(sendBuffer, sendTimes * 1000, sendBuffer.Length % 1000);
                    //    _spCom.Write(sendBuffer, 0, sendBuffer.Length);
                    //}
                    _spCom.Write(sendBuffer, 0, sendBuffer.Length);
                }
                catch(Exception ex)//若是沒法發送,產生異常
                {
                    WeightDeviceLogger.Debug("指令發送錯誤"+ex.Message);
                }
                //sendScrol.ScrollToBottom();//發送數據區滾動到底部
                Sending = false;//關閉正在發送狀態
            }

        }
相關文章
相關標籤/搜索