所有的代码都贴出来了,有需要的朋友可以自行选择性的看一下。
一、运用到知识
初步了解简单的modbus协议、会查询Nmodbus类库、不懂英文的会使用有道词典阅读部分英文文档、会简单的C#语言、了解SerialPort类库。
二、项目环境
Win10系统、8G运行内存、i7处理器、VisualStudio2015
三、项目搭建
1、新建一个命名为“MyConsoleDemo”窗体的项目
2、右击引用进入NuGet,安装NModbus4
四、代码实现
1、页面布局
using Modbus.Device;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
// 使用命名空间
namespace MyConsoleDemo
{
public partial class Form1 : Form
{
// 成员变量
private SerialPort sp;
private string protName;
private int baudRate;
private int deteBites;
private StopBits stopBits;
private Parity parity;
//构造方法
public Form1()
{
InitializeComponent();
SerialPortSet();
}
// 串口设置方法
private void SerialPortSet()
{
// sp = new SerialPort();
string [] PortNames = SerialPort.GetPortNames();
// IEnumerable<String> query = PortNames.OrderBy(x => x);
Array.Sort(PortNames); // 在出现字符“com1 , com2, com10”,会排序出错! ---- 未解决
// 获取所有串口号
foreach (String item in PortNames) // 无法使用实例引用来调用 sp.GetPortNames()报错
{
this.CB_SerialPort.Items.Add(item);
}
// 下拉框默认值设定
this.CB_SerialPort.SelectedIndex = 0;
this.CB_BaudRate.SelectedIndex = 0;
this.CB_ParityBit.SelectedIndex = 0;
this.CB_DateBits.SelectedIndex = 0;
this.CB_StopBits.SelectedIndex = 0;
this.CB_BufferSize.SelectedIndex = 0;
// this.CB_SerialPort.Text = "COM1"; 另一种设置下拉框默认值方式
}
// 打开串口
private void OpenSerialPortClick(object sender, EventArgs e)
{
// 实例化SerialPort对象
sp = new SerialPort();
//赋值
protName = this.CB_SerialPort.Text; // 设置串口号
// Console.WriteLine(sp.PortName);
baudRate = int.Parse(this.CB_BaudRate.Text); // 设置波特率
deteBites = int.Parse(this.CB_DateBits.Text); // 设置数据位
stopBits = (StopBits)Enum.Parse(typeof(StopBits), this.CB_StopBits.Text); //设置停止位
parity = (Parity)Enum.Parse(typeof(Parity), this.CB_ParityBit.Text); //设置校验位
// 串口设置
/*
* NONE
ODD
EVEN
MARK
SPACE
*/
sp.PortName = protName;
sp.BaudRate = baudRate;
sp.DataBits = deteBites;
sp.StopBits = stopBits;
sp.Parity = parity;
sp.Open();
}
// 关闭串口
private void CloseSerialPortClick(object sender, EventArgs e)
{
sp = new SerialPort();
//赋值
protName = this.CB_SerialPort.Text; // 设置串口号
// Console.WriteLine(sp.PortName);
baudRate = int.Parse(this.CB_BaudRate.Text); // 设置波特率
deteBites = int.Parse(this.CB_DateBits.Text); // 设置数据位
stopBits = (StopBits)Enum.Parse(typeof(StopBits), this.CB_StopBits.Text); //设置停止位
parity = (Parity)Enum.Parse(typeof(Parity), this.CB_ParityBit.Text); //设置校验位
sp.BaudRate = baudRate;
sp.DataBits = deteBites;
sp.StopBits = stopBits;
sp.Parity = parity;
sp.Close();
// 清空文本域的信息
RTB_OpenText.Text = "";
}
// 发送信号
private void SendSignalClick(object sender, EventArgs e)
{
// 获取文本域的值
//RichTextBox rb = new RichTextBox();
//this.RTB_OpenText.Text = "2324"; 设置文本域的值
string [] GetOpenText = RTB_OpenText.Lines;
//string OpenText = null;
ushort[] registers = (from x in GetOpenText select ushort.Parse(x)).ToArray();
foreach(ushort item in registers)
{
Console.WriteLine(item);
}
// 获取选择框的值
// if (CK_OpenSexadecimal.Checked) // 判断十六进制是否被中
//{
//OpenText = GetHexFromChs(OpenText); // 用户选中十六进制,发送信号文本域内容转化为十六进制
// }
// if (CK_OpenString.Checked) // 判断字符是否被选中
// {
//OpenText = GetChsFromHex(OpenText); // 用户选中字符,发送信号文本域内容转化为字符型
// }
// 发送信号逻辑
try
{
// 判断串口是否开启
if (sp.IsOpen)
{
// RTU
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(sp);
//
byte slaveID = 1;
// 地址域
ushort startAddress = 100;
master.WriteMultipleRegisters(slaveID, startAddress, registers);
// 串口已经开启就将文本域的值传输过去
//sp.Write(OpenText);
}
else
{
MessageBox.Show("串口未打开!");
}
}
catch(Exception ex)
{
// 捕获到异常
sp = new SerialPort();
// 刷新COM选项
CB_SerialPort.Items.Clear(); // 清空集合中的元素
/*
* AddRange:添加数据到集合
* -- 将ICollection接口的一个集合的所有元素到指定集合的末尾
* 将SerialPort.GetPortNames()集合的所有元素添加到CB_SerialPort.Items集合中
*/
CB_SerialPort.Items.AddRange(SerialPort.GetPortNames());
/// System.Media.SystemSounds.Beep.Play(); 开启背景音乐,提示音
MessageBox.Show(ex.Message);
}
}
// 字符串转16进制--由于使用的是Modbus协议暂时没有使用到数据类型转换
private string GetHexFromChs(string toSendHex)
{
if((toSendHex.Length % 2) != 0)
{
toSendHex += ""; //空格
}
Encoding chs = Encoding.GetEncoding("gb2312");
byte[] bytes = chs.GetBytes(toSendHex);
string str = "";
for (int i = 0; i < bytes.Length; i++)
{
str += string.Format("{0:X}", bytes[i]);
}
return str;
}
// 十六进制转化为字符串---由于使用的是Modbus协议暂时没有使用到数据类型转换
private string GetChsFromHex(string toSendChs)
{
// 判断文本内容是否为空
if (toSendChs == null)
{
}
if (toSendChs.Length % 2 != 0)
{
toSendChs += "20";//空格
}
// 需要将 hex 转换成 byte 数组。
byte[] bytes = new byte[toSendChs.Length / 2];
for (int i = 0; i < bytes.Length; i++)
{
try
{
// 每两个字符是一个 byte。
bytes[i] = byte.Parse(toSendChs.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");
}
}
// 获得 GB2312,Chinese Simplified。
Encoding chs = Encoding.GetEncoding("GB2312");
return chs.GetString(bytes);
}
private void ReceiptSignaClick(object sender, EventArgs e)
{
RTB_ReceiptText.Text = "";
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(sp);
byte slaveID = 1;
ushort startAddress = 100;
//master.ReadWriteMultipleRegisters(slaveID, startAddress);
// 串口已经开启就将文本域的值传输过去
//sp.Write(OpenText);
}
}
}