基于Modbus的C#串口调试开发

Posted 蜗牛噢

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Modbus的C#串口调试开发相关的知识,希望对你有一定的参考价值。

说明:本文主要研究的是使用C# WinForm开发的串口调试软件(其中包含Modbus协议相关操作)。Modbus相关协议可以查阅百度文库等,可参考: 《http://wenku.baidu.com/link?url=J-QZeQVLfvfZh7_lh8Qf0MdwANZuVjEoTqox6zJYrSnKyfgES2RTb_bjC5ZTn8-xgsuUAyiELRYVA3-3FBkBGywWhQ9YGoavJOzwB0IxTyK 》。

  (1)先测试串口设置,发送和接收数据。

  (2)发送modbus的命令帧数据和使用DataReceived接收缓冲区的数据。

 

一、简单的串口调试工具

  下图为串口调试工具的界面,主要包括串口基本设置,功能操作,状态框以及发送接收框。由于这里只是简单的初始化数据,所以当需要发送数据的时候需要点击“串口检测”,来测试当前可用的串口,然后输入需要发送的数据,最后点击“发送数据”(由于测试需要,让发送什么数据就返回什么数据,这里的底层硬件做了短接处理,使用短接貌P30-P31,具体操作可以自行百度)

  

  

  1.1 发送数据操作

    (1)点击 串口检测

    (2)输入发送数据

    (3)点击 发送数据

    下面开始时具体代码:

    #1 软件打开时候初始化操作:Form1_Load(),主要初始化操作串口设置的下拉列表。

 1 private void Form1_Load(object sender, EventArgs e)
 2         {
 3             
 4             //设置窗口大小固定
 5             this.MaximumSize = this.Size;
 6             this.MinimumSize = this.Size;
 7 
 8             //1、设置串口下拉列表
 9             for ( int i = 0; i < 10; i++ ) 
10             {
11                 cbxCOMPort.Items.Add("COM" + (i + 1).ToString());
12             }
13             cbxCOMPort.SelectedIndex = 2;//默认选项
14 
15 
16             //2、设置常用波特率
17             int bt = 300;
18             for (int i = 0; i < 8; i++)
19             {
20                 cbxBaudRate.Items.Add(bt.ToString());
21                 bt *= 2;
22             }
23 
24             cbxBaudRate.Items.Add("38400");
25             cbxBaudRate.Items.Add("43000");
26             cbxBaudRate.Items.Add("56000"); 
27             cbxBaudRate.Items.Add("57600");
28             cbxBaudRate.Items.Add("115200");
29             cbxBaudRate.SelectedIndex = 5;
30 
31 
32             //3、列出停止位
33             cbxStopBits.Items.Add("0");
34             cbxStopBits.Items.Add("1");
35             cbxStopBits.Items.Add("1.5");
36             cbxStopBits.Items.Add("2");
37             cbxStopBits.SelectedIndex = 1;
38 
39             //4、设置奇偶检验
40             cbxParity.Items.Add("");
41             cbxParity.Items.Add("奇校验");
42             cbxParity.Items.Add("偶校验");
43             cbxParity.SelectedIndex = 0;
44 
45             //5、设置数据位
46             cbxDataBits.Items.Add("8");
47             cbxDataBits.Items.Add("7");
48             cbxDataBits.Items.Add("6");
49             cbxDataBits.Items.Add("5");
50             cbxDataBits.SelectedIndex = 0;
51 
52 
53         }
private void Form1_Load(object sender, EventArgs e)

 

    

    #2 检查串口基本设置的参数:CheckPortSetting(),

 1 /// <summary>
 2         /// 【检测端口设置】
 3         /// </summary>
 4         /// <returns></returns>
 5         private bool CheckPortSetting()
 6         {
 7             //检测端口设置
 8             if (cbxCOMPort.Text.Trim() == "" || cbxBaudRate.Text.Trim() == "" || cbxStopBits.Text.Trim() == "" || cbxParity.Text.Trim() == "" || cbxDataBits.Text.Trim() == "")
 9                 return false;
10             return true;
11         }
private bool CheckPortSetting()

 

    #3 设置串口属性,创建SerialPort对象  

 1 /// <summary>
 2         /// 【设置串口属性】
 3         /// </summary>
 4         private void SetPortProperty()
 5         {
 6             //1、设置串口的属性
 7             sp = new SerialPort();
 8 
 9             sp.ReceivedBytesThreshold = 1;//获取DataReceived事件发生前内部缓存区字节数
10             sp.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);//设置委托
11 
12             sp.PortName = cbxCOMPort.Text.Trim();
13 
14             //2、设置波特率
15             sp.BaudRate =  Convert.ToInt32( cbxBaudRate.Text.Trim());
16 
17             //3、设置停止位
18             float f = Convert.ToSingle( cbxStopBits.Text.Trim());
19 
20             if (f == 0) 
21             {
22                 sp.StopBits = StopBits.None;//表示不使用停止位
23             }
24             else if (f == 1.5)
25             {
26                 sp.StopBits = StopBits.OnePointFive;//使用1.5个停止位
27             }
28             else if (f == 2)
29             {
30                 sp.StopBits = StopBits.Two;//表示使用两个停止位
31             }
32             else
33             {
34                 sp.StopBits = StopBits.One;//默认使用一个停止位
35             }
36 
37             //4、设置数据位
38             sp.DataBits = Convert.ToInt16(cbxDataBits.Text.Trim());
39 
40             //5、设置奇偶校验位
41             string s = cbxParity.Text.Trim();
42             if (s.CompareTo("") == 0) 
43             {
44                 sp.Parity = Parity.None;//不发生奇偶校验检查
45             }
46             else if (s.CompareTo("奇校验") == 0)
47             {
48                 sp.Parity = Parity.Odd;//设置奇校验
49             }
50             else if (s.CompareTo("偶校验") == 0)
51             {
52                 sp.Parity = Parity.Even;//设置偶检验
53             }
54             else
55             {
56                 sp.Parity = Parity.None;
57             }
58 
59             //6、设置超时读取时间
60             sp.ReadTimeout = -1;
61 
62             //7、打开串口
63             try
64             {
65                 sp.Open();
66                 isOpen = true;
67             }
68             catch(Exception)
69             {
70                 lblStatus.Text = "打开串口错误!";
71             }
72 
73         }
private void SetPortProperty()

 

     

    #4 “发送数据”按钮点击事件:btnSend_Click(), 在发送数据需要进行,#2,#3验证,然后开始通过串口对象写入数据

 1     /// <summary>
 2         /// 【发送数据】
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void btnSend_Click(object sender, EventArgs e)
 7         {
 8             //发送串口数据
 9 
10             //1、检查串口设置
11             if (!CheckPortSetting()) 
12             {
13                 MessageBox.Show("串口未设置!", "错误提示");
14                 return;
15             }
16 
17             //2、检查发送数据是否为空
18             if(tbxSendData.Text.Trim() == ""){
19                  MessageBox.Show("发送数据不能为空");
20                  return;
21             }
22 
23             //3、设置
24             if (!isSetProperty) 
25             {
26                 SetPortProperty();
27                 isSetProperty = true;
28             }
29 
30             //4、写串口数据
31             if (isOpen)
32             {
33                 //写出口数据
34                 try
35                 {
36                     sp.Write(tbxSendData.Text);
37                     tbxStatus.Text = "发送成功!";
38                     
39 
40                     tbxRecvData.Text += sp.ReadLine();//读取发送的数据                    
41 
42                 }
43                 catch
44                 {
45                     tbxStatus.Text = "发送数据错误";
46                 }
47             }
48             else
49             {
50                 MessageBox.Show("串口未打开", "错误提示");
51             }
52 
53             
54         }                        

 

 

  1.2 接受数据操作

    接收数据和发送数据有点类似   

 1 /// <summary>
 2         /// 【读取数据】
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void btnRecv_Click(object sender, EventArgs e)
 7         {
 8             if(isOpen) 
 9             { 
10                 try  
11                 {
12                     //读取串口数据
13   
14                     tbxRecvData.Text += sp.ReadLine()+"\\r\\n"15                 }  
16                 catch(Exception) 
17                 {  
18                     lblStatus.Text = "读取串口时发生错误!"19                     return20                 } 
21             } 
22             else 
23             {  
24               MessageBox.Show("串口未打开!""错误提示"); 
25               return26                 
27             } 
28         }

 

 

  最后附上该窗体的后台代码:Form1.cs 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.IO.Ports;
  7 using System.Linq;
  8 using System.Text;
  9 using System.Threading.Tasks;
 10 using System.Windows.Forms;
 11 
 12 
 13 namespace 串口调试
 14 {
 15     public partial class Form1 : Form
 16     {
 17         SerialPort sp = null;
 18 
 19         bool isOpen = false;//是否打开
 20 
 21         bool isSetProperty = false;//是否通过串口设置
 22 
 23 
 24         public Form1()
 25         {
 26             InitializeComponent();
 27         }
 28 
 29         private void Form1_Load(object sender, EventArgs e)
 30         {
 31             
 32             //设置窗口大小固定
 33             this.MaximumSize = this.Size;
 34             this.MinimumSize = this.Size;
 35 
 36             //1、设置串口下拉列表
 37             for ( int i = 0; i < 10; i++ ) 
 38             {
 39                 cbxCOMPort.Items.Add("COM" + (i + 1).ToString());
 40             }
 41             cbxCOMPort.SelectedIndex = 2;//默认选项
 42 
 43 
 44             //2、设置常用波特率
 45             int bt = 300;
 46             for (int i = 0; i < 8; i++)
 47             {
 48                 cbxBaudRate.Items.Add(bt.ToString());
 49                 bt *= 2;
 50             }
 51 
 52             cbxBaudRate.Items.Add("38400");
 53             cbxBaudRate.Items.Add("43000");
 54             cbxBaudRate.Items.Add("56000"); 
 55             cbxBaudRate.Items.Add("57600");
 56             cbxBaudRate.Items.Add("115200");
 57             cbxBaudRate.SelectedIndex = 5;
 58 
 59 
 60             //3、列出停止位
 61             cbxStopBits.Items.Add("0");
 62             cbxStopBits.Items.Add("1");
 63             cbxStopBits.Items.Add("1.5");
 64             cbxStopBits.Items.Add("2");
 65             cbxStopBits.SelectedIndex = 1;
 66 
 67             //4、设置奇偶检验
 68             cbxParity.Items.Add("");
 69             cbxParity.Items.Add("奇校验");
 70             cbxParity.Items.Add("偶校验");
 71             cbxParity.SelectedIndex = 0;
 72 
 73             //5、设置数据位
 74             cbxDataBits.Items.Add("8");
 75             cbxDataBits.Items.Add("7");
 76             cbxDataBits.Items.Add("6");
 77             cbxDataBits.Items.Add("5");
 78             cbxDataBits.SelectedIndex = 0;
 79 
 80 
 81         }
 82 
 83 
 84         /// <summary>
 85         /// 【串口检测按钮】
 86         /// </summary>
 87         /// <param name="sender"></param>
 88         /// <param name="e"></param>
 89         private void btnCheckCOM_Click(object sender, EventArgs e)
 90         {
 91             //1、检测哪些端口可用
 92             cbxCOMPort.Items.Clear();
 93             cbxCOMPort.Text = "";
 94             
 95             lblStatus.Text = "执行中...";
 96             string str = "";
 97             for (int i = 0; i < 10; i++)
 98             {
 99                 try
100                 {
101             ////把所有可能的串口都测试一遍,打开关闭操作,只有可用的串口才可会放到下拉列表中
102                     SerialPort sp = new SerialPort("COM" + (i + 1).ToString());
103                     sp.Open();
104                     sp.Close();
105                     cbxCOMPort.Items.Add("COM" + (i + 1).ToString());
106                 }
107                 catch
108                 {
109                     str += "COM" + (i + 1).ToString() + "";
110                     continue;
111                 }
112             }
113         
114         //如果当前下拉列表有可用的串口,则默认选择第一个
115             if(cbxCOMPort.Items.Count > 0)
116                 cbxCOMPort.SelectedIndex = 0;
117             lblStatus.Text = "完成";
118             tbxStatus.Text = str;
119         }
120 
121 
122         /// <summary>
123         /// 【检测端口设置】
124         /// </summary>
125         /// <returns></returns>
126         private bool CheckPortSetting()
以上是关于基于Modbus的C#串口调试开发的主要内容,如果未能解决你的问题,请参考以下文章

串口通讯继电器-modbus通信上位机调试软件工具项目开发案例

C# 开发Modbus Rtu客户端 modbus测试Demo,Modbus 串口通信 , 虚拟MODBUS-RTU测试

RS485串口继电器modbus RTU读写通信调试软件工具和python源码

RS485串口继电器modbus RTU读写通信调试软件工具和python源码

modbus主机从机虚拟串口调试软件

modbus主机从机虚拟串口调试软件