#winform入门第二课 通信界面设置

通信界面的设计,485通信需要有检验位,停止位,数据位,波特率四个参数设置,以及有关于电脑的串口号选择。
设计一个大概的界面,这些中文都可以右击属性,名字直接改就好了。
在这里插入图片描述
我们可以对这些选择添加选择项目,并通过索引赋予其初始选择的项,例如波特率有1200,2400,4800,9600,通过this.comboBox2.SelectedIndex刚打开时默认选择9600波特率

private void Form2_Load(object sender, EventArgs e)
        {
  
            for (int i = 0; i < 10; i++)//最大支持到串口 10,可根据自己需求增加
            {
                this.comboBox1.Items.Add("COM" + (i + 1).ToString());
            }
            this.comboBox1.SelectedIndex = 0;       //刚开始默认的选择位

            this.comboBox2.Items.Add("1200");           //数据通信速率选择
            this.comboBox2.Items.Add("4800");
            this.comboBox2.Items.Add("9600");
            this.comboBox2.Items.Add("115200");
            this.comboBox2.SelectedIndex = 2;

            this.comboBox5.Items.Add("奇校验");        //检验选择
            this.comboBox5.Items.Add("偶校验");
            this.comboBox5.Items.Add("无");
            this.comboBox5.SelectedIndex = 0;

            this.comboBox4.Items.Add("1");              //数据位数选择
            this.comboBox4.Items.Add("2");
            this.comboBox4.Items.Add("3");
            this.comboBox4.Items.Add("4");
            this.comboBox4.Items.Add("5");
            this.comboBox4.Items.Add("6");
            this.comboBox4.Items.Add("7");
            this.comboBox4.Items.Add("8");
            this.comboBox4.SelectedIndex = 7;

            this.comboBox3.Items.Add("1");              //停止位选择
            this.comboBox3.Items.Add("2");
            this.comboBox3.Items.Add("无");
            this.comboBox3.SelectedIndex = 0;
           
            Form1 form = new Form1();
            form.ShowDialog();
            this.Hide();
            
        }

检测是否有可用 的电脑串口号

我的电脑串口插上去是3,所以1到10够用了,有一些串口的串口号超过10的时候,这里循环检测的时候就要增加 i 的数值了,确保你的串口号在循环检测内,不然会检测不到。这部分代码是在串口检测按钮的代码内,双极检测串口即可进入代码段:


 private void button1_Click(object sender, EventArgs e)
        {
            bool comExistence = false;//有可用串口标志位
            this.comboBox1.Items.Clear();
            for (int i = 0; i < 10; i++)
            {
                try
                {
                    SerialPort sp = new SerialPort("COM" + (i + 1).ToString());
                    sp.Open();
                    sp.Close();
                    this.comboBox1.Items.Add("COM" + (i + 1).ToString());
                    comExistence = true;

                }
                catch (Exception)
                {
                    continue;
                }
            }
            if (comExistence)
            {
                this.comboBox1.SelectedIndex = 0;//使 ListBox 显示第 1 个添加的索引
            }
            else
            {
                MessageBox.Show("没有找到可用串口!", "错误提示");
            }
        }

检查完串口之后,我们就根据串口通信要求去设置,串口通信,需要设置波特率,校验位,停止位,数据位。

 private void SetPortProperty()//设置串口的属性
        {
            sp = new SerialPort();
            sp.PortName = this.comboBox1.Text.Trim();//设置串口名
            sp.BaudRate = Convert.ToInt32(this.comboBox2.Text.Trim());//设置串口的波特率
            float f = Convert.ToSingle(this.comboBox3.Text.Trim());//设置停止位
            if (f == 0)
            {
                sp.StopBits = StopBits.None;
            }
            else if (f == 1)
            {
                sp.StopBits = StopBits.One;
            }
            else if (f == 1.5)
            {
                sp.StopBits = StopBits.OnePointFive;
            }
            else if (f == 2)
            {
                sp.StopBits = StopBits.Two;
            }
            else
            {
                sp.StopBits = StopBits.One;
            }
            sp.DataBits = Convert.ToInt16(this.comboBox4.Text.Trim());//设置数据位
            string s = this.comboBox5.Text.Trim(); //设置奇偶校验位
            if (s.CompareTo("无") == 0)
            {
                sp.Parity = Parity.None;
            }
            else if (s.CompareTo("奇校验") == 0)
            {
                sp.Parity = Parity.Odd;
            }
            else if (s.CompareTo("偶校验") == 0)
            {
                sp.Parity = Parity.Even;
            }
            else
            {
                sp.Parity = Parity.None;
            }

            sp.ReadTimeout = -1;//设置超时读取时间
            sp.RtsEnable = true;

            sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
           

        }

打开串口

设置完之后,就可以去打开串口,这部分代码在打开串口的按钮内:
在打开串口时,同时也检查一遍波特率等是否设置了,没有设置会显示报错

 private void button2_Click(object sender, EventArgs e)
        {
            if (isOpen == false)
            {
                if (!CheckPortSetting())//检测串口设置
                {
                    MessageBox.Show("串口未设置!", "错误提示");
                    return;
                }
                if (!isSetProperty)//串口未设置则设置串口
                {
                    SetPortProperty();
                    isSetProperty = true;
                }
                try//打开串口
                {
                    sp.Open();
                    isOpen = true;
                    button2.Text = "关闭串口";
                    //串口打开后则相关的串口设置按钮便不可再用
                    comboBox1.Enabled = false;
                    comboBox2.Enabled = false;
                    comboBox4.Enabled = false;
                    comboBox5.Enabled = false;
                    comboBox3.Enabled = false;

                }
                catch (Exception)
                {
                    //打开串口失败后,相应标志位取消
                    isSetProperty = false;
                    isOpen = false;
                    MessageBox.Show("串口无效或已被占用!", "错误提示");
                }

            }
            else
            {

                try//打开串口
                {
                    sp.Close();
                    isOpen = false;
                    isSetProperty = false;
                    button2.Text = "打开串口";
                    //关闭串口后,串口设置选项便可以继续使用
                    comboBox1.Enabled = true;
                    comboBox2.Enabled = true;
                    comboBox4.Enabled = true;
                    comboBox5.Enabled = true;
                    comboBox3.Enabled = true;

                }
                catch (Exception)
                {
                    MessageBox.Show("关闭串口时发生错误!", "错误提示");
                }
            }
        }

发送数据

打开串口后,就是发送数据了
在发送数据那个按钮内:

  if (isOpen)
            {
                if (this.textBox2.Text == "")//写串口数据
                {
                    MessageBox.Show("请输入数据!", "错误提示");
                    return;
                }
                else
                {
                    Send_485();
                }
            }
            else 
            {
                MessageBox.Show("串口未打开,请打开串口!", "错误提示");
            }

然后写Send_485()函数的代码,这一部分是讲text1里面的文本数值转化为int类型的数组,因为我们写进去是文本类型的,需要转换,而且这个框内只能写0-f,不然会报错, throw new ArgumentException(“hex is not a valid hex number!”, “hex”);跳到这一行函数

 public void Send_485()
        {
            byte[] sendbuf = new byte[textBox2.Text.Length / 2]; //tbxSendData.Text.ToCharArray();
            for (int i = 0; i < sendbuf.Length; i++)
            {
                try
                {
                    // 每两个字符是一个 byte,将字符转化为数值形式,在放入数组内 
                    sendbuf[i] = byte.Parse(textBox2.Text.Substring(i * 2, 2),
                    System.Globalization.NumberStyles.HexNumber);
                }
                catch
                {
                    // Rethrow an exception with custom message. 
                    throw new ArgumentException("hex is not a valid hex number!", "hex");
                }
             
        
            }
            SendModbusData(ref sendbuf);
        }

以下是SendModbusData(ref sendbuf)的代码:

public bool SendModbusData(ref byte[] values)
        {
            string result = string.Join(",", values);
            if (sp.IsOpen)
            {
                //Clear in/out buffers:
                sp.DiscardOutBuffer();//清空发送、接收缓冲区字节
                sp.DiscardInBuffer();
                textBox1.Text = result;
                //Function 3 response buffer:
                byte[] response = new byte[values.Length +2];
                //把value数组复制到response数组
                Array.Copy(values, response, values.Length);

                byte[] CRC = new byte[2];
                GetCRC(response, ref CRC);

                response[0] = Convert.ToByte(response[0]);//地址
                response[1] = Convert.ToByte(response[1]);//功能
                //values[2] = (byte)(Convert.ToByte(values[2])>>8);//寄存器地址
                response[2] = Convert.ToByte(response[2]);
                response[3] = Convert.ToByte(response[3]);
                //values[2] = (byte)(Convert.ToByte(values[]) >> 8);//寄存器个数
                response[4] = Convert.ToByte(response[4]);
                response[5] = Convert.ToByte(response[5]);
                response[response.Length - 2] = CRC[0];
                response[response.Length - 1] = CRC[1];
                values = response; //返回带有 CRC 验证的modbus 数据包
                Console.WriteLine(values.Length);
                for (int i=0;i<values.Length;i++)
                {
                Console.WriteLine(values[i]);//控制台输出打包后的Modbus数据
                }
        
                //Send modbus message to Serial Port:
                try
                {
                    sp.Write(values, 0, values.Length);
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
    
            }
            else
            {
                MessageBox.Show("串口未打开!");
                return false;
            }

        }

这里需要CRC校验:

public void GetCRC(byte[] message, ref byte[] CRC)
        {
            ushort CRCFull = 0xFFFF;
            byte CRCHigh = 0xFF, CRCLow = 0xFF;
            char CRCLSB;
            for (int i = 0; i < (message.Length) - 2; i++)
            {
                CRCFull = (ushort)(CRCFull ^ message[i]);
                for (int j = 0; j < 8; j++)
                {
                    CRCLSB = (char)(CRCFull & 0x0001);
                    CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF);
                    if (CRCLSB == 1)
                    CRCFull = (ushort)(CRCFull ^ 0xA001);
                }
            }
            CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
            CRC[0] = CRCLow = (byte)(CRCFull & 0xFF);
        }

以上就是通过winform向485通信发送的代码,将485串口插入电脑上,仿真时发送数据即会有数据发出,可以通过示波器去捕捉波形来验证。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值