c# SerialPort类 串口通讯编程,用委托来实现异步 请帮帮我吧~~~

时间:2022-08-27 14:45:14
 public partial class demoControl : UserControl, IObjectSafety
    {
        public SerialPort comport = new SerialPort();
        public enum LogMsgType { Incoming, Outgoing, Normal, Warning, Error };

        #region  定义公共变量

        public int o = -1, c = -1, cp = -1, sp = -1, rp = -1, m = 1;
        string rStr = "";
        string sendCmd = "";
        int length = 15;
        //密码键盘
        bool f = false;
        int op = 0;


        bool fprint = false;

        #endregion


        public demoControl()
        {
            InitializeComponent();
            comport.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
        }

        private void demoControl_Load(object sender, EventArgs e)
        {
            printDXHM.PrintController = new System.Drawing.Printing.StandardPrintController();
            printJJFK.PrintController = new System.Drawing.Printing.StandardPrintController();
        }
      
        public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions)
        {
            // TODO: 添加 demoControl.GetInterfacceSafyOptions 实现 
            pdwSupportedOptions = 1;
            pdwEnabledOptions = 2;
        }

        public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions)
        {
            // TODO: 添加 demoControl.SetInterfaceSafetyOptions 实现         
        }


        //-----------------------------------------------------------------向密码键盘对应的COM2串口发送接收数据--开始--↓↓↓↓↓---------------------------------
        #region 向--密码键盘--对应的COM2串口---发送数据
        /// <summary>
        /// 向--密码键盘--对应的COM2串口发送数据
        /// </summary>
        /// <param name="sendstr"></param>
        /// <returns></returns>
        public int SendDateToCom2(string sendstr)
        {
            int i;
            try
            {
                byte[] data = HexStringToByteArray(sendstr);
                comport.DiscardInBuffer();
                comport.Write(data, 0, data.Length);
                i = 0;//成功
            }
            catch
            {
                i = 1;//失败
            }
            return i;
        }
        #endregion

        #region 向--密码键盘--对应的COM2串口---接收数据
        /// <summary>
        /// 向--密码键盘--对应的COM2串口接收数据
        /// </summary>
        /// <param name="sendstr"></param>
        /// <returns></returns>
        public string ReadDateToCom2()
        {
            string readStr = "";
            if (sendCmd == "1B 47 0D 0A")//在取密码问题上 害我一天加一夜
            {
                Thread.Sleep(25);
            }
            int bytes = comport.BytesToRead;           
            byte[] buffer = new byte[bytes];
            comport.Read(buffer, 0, bytes);
            readStr = ByteArrayToHexString(buffer);
            return readStr;
        }
        #endregion


      #region 读取密码:1B 47 0D 0A
        /// <summary>
        ///  读取密码:1B 47 0D 0A
        /// </summary>
        public string ReadKeyPwd()
        {
            string pwd = "";
            try
            {
                if (sp == 0)
                {
                    string str = "1B 47 0D 0A";
                    sendCmd =  "1B 47 0D 0A";
                    int sendrts = SendDateToCom2(str);
                    if (sendrts == 0)
                    {
                        //Thread.Sleep(100);//害我一天加一夜
                        Thread.Sleep(300);
                        pwd = rStr.Trim();
                        rp = 0;
                    }
                }
            }
            catch (Exception ex)
            {
                pwd = "";
            }
            return pwd;
        }
        #endregion

  #region 缓冲区存储的数据
        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {            
            string str = "";
            rStr = ReadDateToCom2();
            rStr = rStr.Replace(" ", "");
            if (m == 0)
            {               
                if (rStr == "02024F4B")
                {
                    str = "";
                }
                else if (rStr == "2A")
                {
                    str = rStr.Replace("2A", "*");
                }
                else if (rStr == "0D")
                {
                    str = "";
                    op = 1;
                    f = true;
                }
                else if (rStr == "1B" || rStr == "80")
                {
                    str = "";
                    op = 2;
                    f = true;
                }
                else if (rStr == "08")
                {
                    str = "";
                    op = 3;
                    f = true;
                }
            }
            else
            {
              
                str = HexToTenString(rStr);
            }
            Log(LogMsgType.Incoming, str);
        }
        #endregion

  #region 数据显示区
        private void Log(LogMsgType msgtype, string msg)
        {
            textBox1.Invoke(new EventHandler(delegate
            {
                if (textBox1.Text.Length < length)
                {
                    textBox1.AppendText(msg);
                    if (m == 0)
                    {
                        if (textBox1.Text.Length == 6)
                        {
                            op = 1;
                            f = true;
                        }
                    }
                }
            }));


下面是要问题的问题:
在这个程序中 读取密码时  我一直用Thread.Sleep(300);时间去等 要不返回来的值不对, 但是这样子做是很不科学的,有些速度快有些慢 所以导致最后返回的数据不一致~~~  我想用委托的方法来实现 希望有会的朋友帮帮我,给我贴出实现的代码,谢谢~~~

3 个解决方案

#1


异步串口是好的,提高效率有用。你用得着么?会不会吧问题复杂化?

#2


串口通讯使用一般有两种模式:
1 问答,就是你提到的定时读取.比如200豪秒返回不是我指定字节长度就当出错处理.开始下次通讯.
  否则就接收读取回来解析数据
2 触发接收,缓冲区有数据就触发datarecive事件,你要不断接收处理,比较被动.

你所提到的委托也可以,其实比较方便可以直接开启一个后台BackgroundWorker线程来完成通讯,只要将数据共享就可以了,不影响界面线程

#3


  rStr = ReadDateToCom2(); 
问题出在这句上面,rStr 是全局变量,你应该将每次收到的字符串雷加到rStr,而不是重新赋值。这样rStr里面只是大约在300ms内收到的内容,所以可能要好久; 
你改为rStr+= ReadDateToCom2();就可以了
  也不需要调用  Thread.Sleep(300); 

#1


异步串口是好的,提高效率有用。你用得着么?会不会吧问题复杂化?

#2


串口通讯使用一般有两种模式:
1 问答,就是你提到的定时读取.比如200豪秒返回不是我指定字节长度就当出错处理.开始下次通讯.
  否则就接收读取回来解析数据
2 触发接收,缓冲区有数据就触发datarecive事件,你要不断接收处理,比较被动.

你所提到的委托也可以,其实比较方便可以直接开启一个后台BackgroundWorker线程来完成通讯,只要将数据共享就可以了,不影响界面线程

#3


  rStr = ReadDateToCom2(); 
问题出在这句上面,rStr 是全局变量,你应该将每次收到的字符串雷加到rStr,而不是重新赋值。这样rStr里面只是大约在300ms内收到的内容,所以可能要好久; 
你改为rStr+= ReadDateToCom2();就可以了
  也不需要调用  Thread.Sleep(300);