zoukankan      html  css  js  c++  java
  • C#初入串口通信(串行通信)总结

     

    使用WinFrom来实现:

    首先要知道串口通信协议以及原理

    原理大概提一下:要自己翻阅看。(http://book.51cto.com/art/200911/162532.htm或者http://hi.baidu.com/fly514/item/54aeb9d731ddedb932db9006

    代码部分:

    实现串口通信有很多种办法,有COM组件(收费),有.net的serialPort串行端口控件等等,这里实现的方法是使用.NET提供的一个很方便的类:SerialPort。(这个类中一般简单的功能都可以实现,如果要实现的功能很变态的话,就另请高明吧)

     实现的功能很简单(就是发送数据和接收数据而已),这是我初学者的入门总结。




     

    首先,先将这些下拉空的值手动添加进去(第一个串行端口是程序实现的,也可以手动添加COM1等等)

    停止位:One    OnePointFive    Two


    数据位:8   7   6



    校验位:Even  Mark  None   Odd    Space


     

    波特率:300  600  1200  2400  4800  9600  19200  38400  43000  56000  57600  115200

    (还有其他数字的波特率,看实际情况而定了,这应该是常用的波特率了)



     

    这个类是在using System.IO.Ports命名空间下的类。 

     

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;

    namespace MyComm
    {
        public partial class Form2 : Form
        {
            public Form2()
            {
                InitializeComponent();
                //如果不写,当你接收数据并且把数据显示到文本框上的时候会直接报错的。
                //因为这是对 Windows 窗体控件进行线程安全调用
                //访问 Windows 窗体控件本质上不是线程安全的。
                //如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。
                //还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。
                //.NET Framework 有助于在以非线程安全方式访问控件时检测到这一问题。
                //在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,
                //则调试器会引发一个 InvalidOperationException,并提示消息:“从不是创建控件 control name 的线程访问它。”
                Form.CheckForIllegalCrossThreadCalls = false;
            }
            //定义SerialPort类
            SerialPort Myport = null;


            ///
            /// 窗体加载完成触发
            ///
            ///
            ///
            private void Form2_Load(object sender, EventArgs e)
            {
                //实例化
                Myport = new SerialPort();
                //这里需要添加引用Microsoft.VisualBasic的引用,提供操作计算机组件(如:音频,时钟,键盘文件系统等)的属性
                Microsoft.VisualBasic.Devices.Computer pc = new Microsoft.VisualBasic.Devices.Computer();
                //循环该计算机上所有串行端口的集合
                foreach (string s in pc.Ports.SerialPortNames)
                {
                    //串口名称添加到cbxPortName下拉框上
                    //一般计算机上是有COM1和COM2串口的,如果没有自己在cbxPortName下拉框里写COM1 和 COM2的字符串(如:this.cbxPortName.Items.Add("COM2"))
                    this.cbxPortName.Items.Add(s);
                }
                //防止报错,万一计算机上没有串口,就不走这一步
                if (pc.Ports.SerialPortNames.Count > 0)
                {
                    cbxPortName.SelectedIndex = 0;
                }
                cmbbaud.SelectedIndex = 0;
                cmbParity.SelectedIndex = 0;
                cmbBits.SelectedIndex = 0;
                cmbStop.SelectedIndex = 0;
            }


            ///
            /// 打开串口按钮
            ///
            ///
            ///
            private void btnOpen_Click(object sender, EventArgs e)
            {
                //设置串口端口
                Myport.PortName = cbxPortName.Text;
                //设置比特率
                Myport.BaudRate = Convert.ToInt32(cmbbaud.Text);
                //设置数据位
                Myport.DataBits = Convert.ToInt32(cmbBits.Text);
                //根据选择的数据,设置停止位
                //if (cmbStop.SelectedIndex == 0)
                //    Myport.StopBits = StopBits.None;
                if (cmbStop.SelectedIndex == 1)
                    Myport.StopBits = StopBits.One;
                if (cmbStop.SelectedIndex == 2)
                    Myport.StopBits = StopBits.OnePointFive;
                if (cmbStop.SelectedIndex == 3)
                    Myport.StopBits = StopBits.Two;

                //根据选择的数据,设置奇偶校验位
                if (cmbParity.SelectedIndex == 0)
                    Myport.Parity = Parity.Even;
                if (cmbParity.SelectedIndex == 1)
                    Myport.Parity = Parity.Mark;
                if (cmbParity.SelectedIndex == 2)
                    Myport.Parity = Parity.None;
                if (cmbParity.SelectedIndex == 3)
                    Myport.Parity = Parity.Odd;
                if (cmbParity.SelectedIndex == 4)
                    Myport.Parity = Parity.Space;

                //此委托应该是异步获取数据的触发事件,即是:当有串口有数据传过来时触发
                Myport.DataReceived += new SerialDataReceivedEventHandler(port1_DataReceived);//DataReceived事件委托
                //打开串口的方法
                try
                {
                    Myport.Open();
                    if (Myport.IsOpen)
                    {
                        MessageBox.Show("the port is opened!");
                    }
                    else
                    {
                        MessageBox.Show("failure to open the port!");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("failure to open the port!"+ex.ToString());
                }
            }


            ///
            /// 关闭串口的方法
            ///
            public void ClosePort()
            {
                Myport.Close();
                if (!Myport.IsOpen)
                {
                    Console.WriteLine("the port is already closed!");
                }
            }


            ///
            /// 发送按钮
            ///
            ///
            ///
            private void btnNotAutoSend_Click(object sender, EventArgs e)
            {
                //向串口发送数据的方法
                SendCommand(txtSend.Text.Trim());
            }

     

            ///
            /// 向串口发送数据的方法
            ///
            ///
            public void SendCommand(string CommandString)
            {
                //转换
                //串口只能读取ASCII码或者进制数(1,2,3.....的进制,一般是16进制)
                byte[] WriteBuffer = Encoding.ASCII.GetBytes(CommandString);
                //将数据缓冲区的数据写入到串口端口
                Myport.Write(WriteBuffer, 0, WriteBuffer.Length);
            }

     


            ///
            /// DataReceived事件委托的方法
            ///
            ///
            ///
            private void port1_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                try
                {
                    string currentline = "";
                    //循环接收串口中的数据
                    while (Myport.BytesToRead > 0)
                    {
                        char ch = (char)Myport.ReadByte();
                        currentline += ch.ToString();
                    }
                    //在这里对接收到的数据进行显示
                    //如果不在窗体加载的事件里写上:Form.CheckForIllegalCrossThreadCalls = false; 就会报错)
                    this.txtReceive.Text = currentline;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message.ToString());
                }
            }

        }
    }

     

    配合上“VSPM虚拟串口”用就很方便   :(根据http://blog.csdn.net/redhaste/article/details/4097863http://blog.csdn.net/gaojing007/article/details/5399503写的文章)


    附件下载(VSPM虚拟串口,C#中串口通信编程.doc,SerialPort程序例子):

    http://yunpan.cn/Q7Yi7geX988MY   提取码 167e

     

    在编程的过程中用到了几个工具:串口助手,VSPM虚拟串口,Configure Virtual Serial Port Driver。


  • 相关阅读:
    uva299 Train Swapping
    uva 10106 Product
    uva 340 MasterMind Hints
    uva 10115 Automatic Editing
    uva748 Exponentiation
    uva152 Tree's a Crowd
    uva 10420 List of Conquests
    uva 644 Immediate Decodability
    要知其所以然的学习(转载)
    持有书籍统计
  • 原文地址:https://www.cnblogs.com/xulang/p/5506187.html
Copyright © 2011-2022 走看看