基于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 }
#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 }
#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 }
#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 return; 20 } 21 } 22 else 23 { 24 MessageBox.Show("串口未打开!", "错误提示"); 25 return; 26 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源码