分享

WPF中使用SerialPort实现串口通讯

 Jcstone 2013-09-25

WPF中使用SerialPort实现串口通讯

 来源:CSDN 作者:jane_sl  
C++中实现串口通讯一般都是使用ActiveX控件MSComm,于是下载了MSComm控件,根据博客中转载的文章:点击打开链接,将该控件导入到VS2010里面,但是它在工具栏中显示是灰色的,费了半天劲才知道MSComm不支持WPF,于是就开始了SerialPort的学习。 SerialPort的基本属性: BaseStream 获取 SerialPort 对象的基础 Stream 对象
  

  C++中实现串口通讯一般都是使用ActiveX控件MSComm,于是下载了MSComm控件,根据博客中转载的文章:点击打开链接,将该控件导入到VS2010里面,但是它在工具栏中显示是灰色的,费了半天劲才知道MSComm不支持WPF,于是就开始了SerialPort的学习。

  SerialPort的基本属性:

  BaseStream 获取 SerialPort 对象的基础 Stream 对象

  BaudRate 获取或设置串行波特率

  BreakState 获取或设置中断信号状态

  BytesToRead 获取接收缓冲区中数据的字节数

  BytesToWrite 获取发送缓冲区中数据的字节数

  CDHolding 获取端口的载波检测行的状态

  CtsHolding 获取“可以发送”行的状态

  DataBits 获取或设置每个字节的标准数据位长度

  DiscardNull 获取或设置一个值,该值指示 Null 字节在端口和接收缓冲区之间传输时是否被忽略

  DsrHolding 获取数据设置就绪 (DSR) 信号的状态

  DtrEnable 获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号

  Encoding 获取或设置传输前后文本转换的字节编码

  Handshake 获取或设置串行端口数据传输的握手协议

  IsOpen 获取一个值,该值指示 SerialPort 对象的打开或关闭状态

  NewLine 获取或设置用于解释 ReadLine( )和WriteLine( )方法调用结束的值

  Parity 获取或设置奇偶校验检查协议

  ParityReplace 获取或设置一个字节,该字节在发生奇偶校验错误时替换数据流中的无效字节

  PortName 获取或设置通信端口,包括但不限于所有可用的 COM 端口

  ReadBufferSize 获取或设置 SerialPort 输入缓冲区的大小

  ReadTimeout 获取或设置读取操作未完成时发生超时之前的毫秒数

  ReceivedBytesThreshold 获取或设置 DataReceived 事件发生前内部输入缓冲区中的字节数

  RtsEnable 获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号

  StopBits 获取或设置每个字节的标准停止位数

  WriteBufferSize 获取或设置串行端口输出缓冲区的大小

  WriteTimeout 获取或设置写入操作未完成时发生超时之前的毫秒数

  SerialPort类的常用方法

  方 法 名 称 说  明

  Close 关闭端口连接,将 IsOpen 属性设置为False,并释放内部 Stream 对象

  Open 打开一个新的串行端口连接

  Read 从 SerialPort 输入缓冲区中读取

  ReadByte 从 SerialPort 输入缓冲区中同步读取一个字节

  ReadChar 从 SerialPort 输入缓冲区中同步读取一个字符

  ReadLine 一直读取到输入缓冲区中的 NewLine 值

  ReadTo 一直读取到输入缓冲区中指定 value 的字符串

  Write 已重载。将数据写入串行端口输出缓冲区

  WriteLine 将指定的字符串和 NewLine 值写入输出缓冲区

  作者做了个简单的实例,在同一台电脑上实现发送和接收。只定义了三个控件:一个发送文本框txtSend,一个接受文本框txtReceive,一个发送按钮。在txtSend中输入文本,点击发送,txtReceive便能接收到txtSend中的数据。实现该实例最重要的事情是一定要计算机上串口上的2,3口短起来,由于对串口一无所知,作者在上面耗费了很长时间才找到症结所在。

  注释比较清晰,就直接上代码了:

  定义好委托:

        delegate void HandleInterfaceUpdateDelagate(string text);//委托;此为重点
        HandleInterfaceUpdateDelagate interfaceUpdateHandle;

  主体代码:

        /// <summary>
        /// 发送按钮的单击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, RoutedEventArgs e)
        {
            //实例化串口对象(默认:COMM1,9600,e,8,1) 
            SerialPort serialPort1 = new SerialPort();
            //更改参数
            serialPort1.PortName = "COM1";
            serialPort1.BaudRate = 19200;
            serialPort1.Parity = Parity.None;
            serialPort1.StopBits = StopBits.One;

            //上述步骤可以用在实例化时调用SerialPort类的重载构造函数
            //SerialPort serialPort = new SerialPort("COM1", 19200, Parity.Odd, StopBits.Two);

            //打开串口(打开串口后不能修改端口名,波特率等参数,修改参数要在串口关闭后修改)
            if (!serialPort1.IsOpen)
            {
                serialPort1.Open();
            }
            else
                MessageBox.Show("Port is open!");

            //用字节的形式发送数据
            SendBytesData(serialPort1);

            //开启接收数据线程
            ReceiveData(serialPort1);
        }


        /// <summary>
        /// 开启接收数据线程
        /// </summary>
        private void ReceiveData(SerialPort serialPort)
        {
            //同步阻塞接收数据线程
            Thread threadReceive = new Thread(new ParameterizedThreadStart(SynReceiveData));
            threadReceive.Start(serialPort);

            //也可用异步接收数据线程
            //Thread threadReceiveSub = new Thread(new ParameterizedThreadStart(AsyReceiveData));
            //threadReceiveSub.Start(serialPort);

        }

        //发送二进制数据
        private void SendBytesData(SerialPort serialPort)
        {
            byte[] bytesSend = System.Text.Encoding.Default.GetBytes(txtSend.Text);
            serialPort.Write(bytesSend, 0, bytesSend.Length);
            
        }

        //同步阻塞读取
        private void SynReceiveData(object serialPortobj)
        {
            
            SerialPort serialPort = (SerialPort)serialPortobj;
            System.Threading.Thread.Sleep(0);
            serialPort.ReadTimeout = 1000;
            try
            {
                int n = serialPort.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致  
                byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据  
                //received_count += n;//增加接收计数  
                serialPort.Read(buf, 0, n);//读取缓冲数据  
                //因为要访问ui资源,所以需要使用invoke方式同步ui
                interfaceUpdateHandle = new HandleInterfaceUpdateDelagate(UpdateTextBox);//实例化委托对象
                Dispatcher.Invoke(interfaceUpdateHandle, new string[] { Encoding.ASCII.GetString(buf) });  
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                //处理超时错误
            }

            serialPort.Close();

        }

        private void UpdateTextBox(string text)
        {
            txtReceive.Text = text;
        }

        //异步读取
        private void AsyReceiveData(object serialPortobj)
        {
            SerialPort serialPort = (SerialPort)serialPortobj;
            System.Threading.Thread.Sleep(500);
            try
            {
                int n = serialPort.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致  
                byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据  
                //received_count += n;//增加接收计数  
                serialPort.Read(buf, 0, n);//读取缓冲数据  
                //因为要访问ui资源,所以需要使用invoke方式同步ui。
                interfaceUpdateHandle = new HandleInterfaceUpdateDelagate(UpdateTextBox);//实例化委托对象
                Dispatcher.Invoke(interfaceUpdateHandle, new string[] { Encoding.ASCII.GetString(buf) }); 
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                //处理错误
            }
            serialPort.Close();
        }

  源码下载

  本文来自jane_sl的博客,原文地址:http://blog.csdn.net/jane_sl/article/details/7416450

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多