(Tips:本人纯萌新小白一枚,文章只为记录自己的编程历史,温故而知新,能帮助到大家倍感荣幸,有错误的地方劳烦指点!)
不多废话直接进入主题!
本文旨在基于Modbus协议、C#开发语言进行串口工具的开发工作:
首先是界面的设计:
初次设计,界面略显花哨,各位按需进行颜色的设置。
用到的控件有:label(文本)、textBox(文本框)、comboBox(下拉框)、button(按键)、groupBox(组合框)、timer(时钟)、serialPort(串口) 。
由于是初次设计,所以内容较为单薄,且有未实现的功能(例如10H指令并未实现)
首先是Form(主函数)的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using Modbus.Data;
using Modbus.Device;
using Modbus.Message;
using Modbus调试工具_demo_.Properties;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace Modbus调试工具_demo_
{
public partial class Form1 : Form
{
#region 一些定义
/// <summary>
/// 私有串口实例
/// </summary>
private SerialPort serialPort = new SerialPort();
//定义接收字节数组
byte[] Data = new byte[1024];
byte ReceiveByte;
int ReceiveByteCount = 0;
//定义设备地址
int CurrentAddr = 1;
int Word;
//定义返回报文
string ReceiveData;
#endregion
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
#region 打开窗口触发事件(存在问题需要修改!!!)
private void Form1_Load(object sender, EventArgs e)
{
//(待程序调整好后启用) MessageBox.Show("欢迎使用本软件!\r\n", "MB调试工具");
this.MaximumSize = this.Size;
this.MinimumSize = this.Size; //固定程序窗口大小;
button1.Text = "打开串口";
button1.BackColor = Color.Green;
button9.BackColor = Color.Yellow;
button3.Enabled = false;
button4.Enabled = false;
button5.Enabled = false;
button6.Enabled = false;
button7.Enabled = false;
checkBox1.Enabled = false;
timer3.Start();
this.textBox3.Text = Settings.Default.One;
this.textBox4.Text = Settings.Default.Two;
this.textBox5.Text = Settings.Default.Three;
this.textBox6.Text = Settings.Default.Four;
this.textBox7.Text = Settings.Default.Five;
this.textBox8.Text = Settings.Default.Six;
this.textBox9.Text = Settings.Default.Seven;
this.textBox10.Text = Settings.Default.Eight;
this.textBox11.Text = Settings.Default.Nine;
#region 保存输入数值代码段(存在错误)
/* string Data_Save = " ";
string[] Data_Set = { " " };
string Data_Path = Application.StartupPath + "\\config_data.ini";
try
{
StreamReader streamReader = new StreamReader(Data_Path);
Data_Save = streamReader.ReadToEnd();
streamReader.Close();
Data_Set = Regex.Split(Data_Save, "||");
}
catch { }
//USART_Scan(serialPort1, comboBox1);
if (Data_Set.Length > 12)
{
try
{
if (Data_Set[0] == "1")
{
checkBox1.Checked = true;
}
else
{
checkBox1.Checked = false;
}
comboBox2.Text = Data_Set[1];
comboBox3.Text = Data_Set[2];
comboBox4.Text = Data_Set[3];
comboBox5.Text = Data_Set[4];
textBox3.Text = Data_Set[5];
textBox4.Text = Data_Set[6];
textBox5.Text = Data_Set[7];
textBox6.Text = Data_Set[8];
textBox7.Text = Data_Set[9];
textBox8.Text = Data_Set[10];
textBox9.Text = Data_Set[11];
textBox10.Text = Data_Set[12];
textBox11.Text = Data_Set[13];
//代码段暂时存在错误,无法使用;
}
catch
{
checkBox1.Checked = false;
comboBox2.Text = "9600";
comboBox3.Text = "No Parity";
comboBox4.Text = "8";
comboBox5.Text = "1";
textBox3.Text = "";
textBox4.Text = "";
textBox5.Text = "";
textBox6.Text = "";
textBox7.Text = "";
textBox8.Text = "";
textBox9.Text = "";
textBox10.Text = "";
textBox11.Text = "";
}
}
else
{
comboBox2.Text = "9600";
comboBox3.Text = "No Parity";
comboBox4.Text = "8";
comboBox5.Text = "1";
} */
#endregion
}
#endregion
#region 开关串口
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口") //假设当前串口设备为关闭状态;
{
try
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
serialPort1.DataBits = Convert.ToInt32(comboBox4.Text);
serialPort1.Open();
button1.Text = "关闭串口";
comboBox1.Enabled = false;
comboBox2.Enabled = false;
button1.BackColor = Color.Red;
button3.Enabled = true;
button4.Enabled = true;
button5.Enabled = true;
button6.Enabled = true;
button7.Enabled = true;
checkBox1.Enabled = true;
}
catch
{
MessageBox.Show("打开串口失败,请检查串口!", "警告");
}
}
else
{
try
{
serialPort1.Close();
comboBox1.Enabled = true;
comboBox2.Enabled = true;
button1.Text = "打开串口";
button1.BackColor = Color.Green;
button3.Enabled = false;
button4.Enabled = false;
button5.Enabled = false;
button6.Enabled = false;
button7.Enabled = false;
checkBox1.Enabled = false;
textBox1.Text = "";
textBox2.Text = "";
}
catch
{
MessageBox.Show("关闭串口失败,请检查串口!", "警告");
}
}
}
#endregion
#region 自动获取可用的串口号
private void comboBox1_DropDown(object sender, EventArgs e)
{
USART_Scan(comboBox1);
}
public void USART_Scan(System.Windows.Forms.ComboBox MyBox) //搜索串口号并放到下拉列表中
{
MyBox.Items.Clear(); //清空ComboBox显示内容
string[] Serial_Name = System.IO.Ports.SerialPort.GetPortNames(); //获取串口名称 为字符串数组
if (Serial_Name.Length > 0)
{
Array.Sort(Serial_Name);
MyBox.Items.AddRange(Serial_Name);
}
if (MyBox.Items.Count != 0)
MyBox.SelectedIndex = 0;
}
#endregion
#region 清空textBox
private void button6_Click(object sender, EventArgs e)
{
textBox1.Text=" "; //一种清空textbox的方法;
}
private void button7_Click(object sender, EventArgs e)
{
textBox2.Clear(); //另一种清空textbox的方法;
}
#endregion
#region 03H代码的功能实现
/// <summary>
/// 03H发送命令
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
try
{
string send_byte = "";
Modbus_data modbus_Data = new Modbus_data();
byte[] data_re = modbus_Data.Order03H(Convert.ToByte(textBox3.Text),
Convert.ToUInt16(textBox4.Text), Convert.ToUInt16(textBox5.Text));
serialPort1.Write(data_re, 0, 8);
Word = Convert.ToUInt16(textBox5.Text);
for (int i = 0; i < data_re.Length; i++)
{
send_byte += data_re[i].ToString("X2") + " ";
}
textBox1.Text += send_byte + "\t";
Thread.Sleep(100);
textBox2.Text += ReceiveData + "\n";
if(ReceiveData != null)
{
ReceiveData = ReceiveData.Replace(" ", "");
ReceiveData = ReceiveData.Substring(6, Word * 4);
ReceiveData = string.Join(" ",
System.Text.RegularExpressions.Regex.Split(ReceiveData, "(?<=\\G.{4})(?!$)"));
}
}
catch (System.Exception ex)
{
MessageBox.Show("错误:" + ex.Message, "Modbus 错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
#endregion
#region 06H代码的功能实现
/// <summary>
/// 06H写入命令发送
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_Click(object sender, EventArgs e)
{
try
{
string send_byte = "";
Modbus_data modbus_Data = new Modbus_data();
byte[] data_se = modbus_Data.Order06H(Convert.ToByte(textBox6.Text),
Convert.ToUInt16(textBox7.Text), Convert.ToUInt16(textBox8.Text));
serialPort1.Write(data_se, 0, 8);
for (int i = 0; i < data_se.Length; i++)
{
send_byte += data_se[i].ToString("X2") + " ";
}
textBox1.Text += send_byte + "\t";
Thread.Sleep(100);
textBox2.Text += ReceiveData + "\n";
}
catch (System.Exception ex)
{
MessageBox.Show("错误:" + ex.Message, "Modbus 错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
#endregion
#region 10H代码的功能实现(存在问题需要修改!!!)
/// <summary>
/// 10H写入命令发送
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button5_Click(object sender, EventArgs e)
{
try
{
string send_byte = "";
Modbus_data modbus_Data = new Modbus_data();
byte[] data_re = modbus_Data.Order10H(Convert.ToByte(textBox9.Text),
Convert.ToUInt16(textBox10.Text), Convert.ToUInt16(textBox11.Text));
serialPort1.Write(data_re, 0, 8);
for (int i = 0; i < data_re.Length; i++)
{
send_byte += data_re[i].ToString("X2") + " ";
}
textBox1.Text += send_byte + "\t";
Thread.Sleep(100);
textBox2.Text += ReceiveData + "\n";
}
catch (System.Exception ex)
{
MessageBox.Show("错误:" + ex.Message, "Modbus 错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
//try
//{
// string send_byte = "";
// Modbus_data modbus_Data = new Modbus_data();
// byte[] data_re = modbus_Data.Order10H(Convert.ToByte(textBox9.Text),
// Convert.ToUInt16(textBox10.Text), Convert.ToUInt16(textBox11.Text));
// serialPort1.Write(data_re, 0, 8);
// for (int i = 0; i < data_re.Length; i++)
// {
// send_byte += data_re[i].ToString("X2") + " ";
// }
// textBox1.Text += send_byte + "\t";
// Thread.Sleep(100);
// textBox2.Text += ReceiveData + "\n";
//}
//catch (System.Exception ex)
//{
// MessageBox.Show("错误:" + ex.Message, "Modbus 错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
//}
#endregion
#region 接口接收到数据时的事件(10H代码需要在功能实现代码修改完后进行相应的修改!!!)
private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(SerialPort1_DataReceived);
//对serialPort1 注册一个事件委托
this.textBox2.Invoke(new MethodInvoker(delegate ()
{
textBox2.AppendText(serialPort1.ReadExisting());//这里用多行文本进行显示
textBox2.ScrollToCaret();
}));
if (serialPort1.IsOpen)
{
while (serialPort1.BytesToRead > 0)
{
ReceiveByte = (byte)serialPort1.ReadByte();
Data[ReceiveByteCount] = ReceiveByte;
ReceiveByteCount += 1;
if (ReceiveByteCount >= 1024)
{
ReceiveByteCount = 0;
//清除输入缓存区
serialPort1.DiscardInBuffer();
return;
}
}
}
//读取保持型寄存器 功能码0x03
if (Data[0] == (byte)CurrentAddr && Data[1] == 0x03 && ReceiveByteCount >= (Word * 2 + 5))
{
ReceiveData = "";
for (int i = 0; i < Word * 2 + 5; i++)
{
ReceiveData = ReceiveData + " " + Data[i].ToString("X2");
}
serialPort1.DiscardInBuffer();
}
//预置单字保持型寄存器 功能码0x06
if (Data[0] == (byte)CurrentAddr && Data[1] == 0x06 && ReceiveByteCount >= 8)
{
ReceiveData = "";
for (int i = 0; i < 8; i++)
{
ReceiveData = ReceiveData + " " + Data[i].ToString("X2");
}
serialPort1.DiscardInBuffer();
}
Array.Clear(Data, 0, Data.Length);
ReceiveByteCount = 0;
//预置多字保持型寄存器 功能码0x10
if (Data[0] == (byte)CurrentAddr && Data[1] == 0x06 && ReceiveByteCount >= 8)
{
ReceiveData = "";
for (int i = 0; i < 8; i++)
{
ReceiveData = ReceiveData + " " + Data[i].ToString("X2");
}
serialPort1.DiscardInBuffer();
}
Array.Clear(Data, 0, Data.Length);
ReceiveByteCount = 0;
//string dataRecive = serialPort1.ReadExisting();
//textBox2.AppendText(dataRecive);
}
#endregion
#region 清除收发缓存区数据的实现
private void button8_Click(object sender, EventArgs e)
{
textBox1.Clear();
textBox2.Clear();
}
#endregion
#region 03H指令自动发送的实现
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if(checkBox1.Checked)
{
checkBox1.BackColor = Color.Red;
comboBox6.Enabled = false; //界面改变;
try
{
timer1.Interval = Convert.ToUInt16(comboBox6.Text, 10);
}
catch
{
MessageBox.Show("输入时间有误,设定为默认值", "提示");
comboBox6.Text = "1000";
timer1.Interval = 1000;
}
timer1.Start();
}
else
{
checkBox1.BackColor = Color.DarkGray;
timer1.Stop();
comboBox6.Enabled = true;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
button3.PerformClick();
}
#endregion
#region 结束程序按键
private void button9_Click(object sender, EventArgs e)
{
System.Environment.Exit(0);
}
#endregion
#region 06H指令自动发送的实现
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
if (checkBox2.Checked)
{
checkBox2.BackColor = Color.Red;
comboBox7.Enabled = false; //界面改变;
try
{
timer2.Interval = Convert.ToUInt16(comboBox7.Text, 10);
}
catch
{
MessageBox.Show("输入时间有误,设定为默认值", "提示");
comboBox6.Text = "1000";
timer1.Interval = 1000;
}
timer2.Start();
}
else
{
checkBox2.BackColor = Color.DarkGray;
timer2.Stop();
comboBox7.Enabled = true;
}
}
private void timer2_Tick(object sender, EventArgs e)
{
button4.PerformClick();
}
#endregion
#region 窗口关闭时触发事件
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Settings.Default.One = this.textBox3.Text;
Settings.Default.Two = this.textBox4.Text;
Settings.Default.Three= this.textBox5.Text;
Settings.Default.Four = this.textBox6.Text;
Settings.Default.Five = this.textBox7.Text;
Settings.Default.Six = this.textBox8.Text;
Settings.Default.Seven = this.textBox9.Text;
Settings.Default.Eight = this.textBox10.Text;
Settings.Default.Nine = this.textBox11.Text;
Settings.Default.Save();
#region 存在问题待修复代码段
/* string Data_Save = "";
StreamWriter streamWriter = new StreamWriter("config_data.ini", false);
if(checkBox3.Checked)
{
Data_Save += "1" + "||";
}
else
{
Data_Save += "0" + "||";
}
Data_Save += comboBox1.Text.ToString() + "||";
Data_Save += comboBox2.Text.ToString() + "||";
Data_Save += comboBox3.Text.ToString() + "||";
Data_Save += comboBox4.Text.ToString() + "||";
Data_Save += comboBox5.Text.ToString() + "||";
Data_Save += textBox3.Text.ToString() + "||";
Data_Save += textBox4.Text.ToString() + "||";
Data_Save += textBox5.Text.ToString() + "||";
Data_Save += textBox6.Text.ToString() + "||";
Data_Save += textBox7.Text.ToString() + "||";
Data_Save += textBox8.Text.ToString() + "||";
Data_Save += textBox9.Text.ToString() + "||";
Data_Save += textBox10.Text.ToString() + "||";
Data_Save += textBox11.Text.ToString();
streamWriter.Write(Data_Save);
streamWriter.Close(); */
#endregion
}
#endregion
#region 发送缓存区数据保存
private void button10_Click(object sender, EventArgs e)
{
FileStream fs = new FileStream(@"Send_data.txt",FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(fs);
sw.Write(this.textBox1.Text + "\r\n");
sw.Close();
fs.Close();
MessageBox.Show("数据已保存!\r\n请查看根目录\r\nSend_data文档!", "提示");
}
#endregion
#region 接收缓存区数据保存
private void button11_Click(object sender, EventArgs e)
{
FileStream fs = new FileStream(@"Receive_data.txt", FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(fs);
sw.Write(this.textBox2.Text + "\r\n");
sw.Close();
fs.Close();
MessageBox.Show("数据已保存!\r\n请查看根目录\r\nReceive_data文档!", "提示");
}
#endregion
#region 时钟模块
private void timer3_Tick(object sender, EventArgs e)
{
label21.Text = System.DateTime.Now.ToString();
}
#endregion
}
}
其次是Program.cs的代码段:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Modbus调试工具_demo_
{
internal class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
最后是Modbus_data.cs的代码段(10H指令代码段貌似有错误):
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.IO.Ports;
namespace Modbus调试工具_demo_
{
internal class Modbus_data
{
#region 整形、字节、位互相转化
//整形转字节数组
private Byte[] intToBytes(int inInt, int outNum)
{
Byte[] outByte = new byte[outNum];
for (int i = 0; i < outNum; i++)
{
outByte[outNum - 1 - i] = (byte)(inInt & 0xFF);
inInt >>= 8;
}
return outByte;
}
//字节数组转整形
private int bytesToInt(byte[] inBytes)
{
int len = inBytes.Length;
if (len > 4) len = 4;
int outInt = 0;
for (int i = 0; i < len; i++)
{
outInt = (outInt << 8) | inBytes[i];
}
return outInt;
}
//Bool数组转Byte
private byte boolsToByte(bool[] bools)
{
if (bools != null && bools.Length > 0)
{
byte b = 0;
int len = bools.Length;
if (len > 8) len = 8;
for (int i = 0; i < len; i++)
{
if (bools[i]) b = (Byte)(b | (1 << i));
}
return b;
}
return 0;
}
//Byte转Bool数组
private bool[] byteToBools(byte inByte)
{
Boolean[] array = new Boolean[8];
for (int i = 0; i < 8; i++)
{ //对于byte的每bit进行判定
array[i] = (inByte & 1) == 1; //判定byte的最后一位是否为1,若为1,则是true;否则是false
inByte = (byte)(inByte >> 1); //将byte右移一位
}
return array;
}
#endregion
#region CRC表
private static readonly byte[] auchCRCHi = new byte[]//crc高位表
{
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
};
private static readonly byte[] auchCRCLo = new byte[]//crc低位表
{
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};
#endregion
#region CRC查表
public byte[] CRC16(byte[] buffer)
{
byte crcHi = 0xff; // 高位初始化
byte crcLo = 0xff; // 低位初始化
for (int i = 0; i < buffer.Length; i++)
{
int crcIndex = crcHi ^ buffer[i];
//查找crc表值
crcHi = (byte)(crcLo ^ auchCRCHi[crcIndex]);
crcLo = auchCRCLo[crcIndex];
}
return new byte[] { crcHi, crcLo };
}
#endregion
#region 03H功能码 //按照协议格式化 03 指令 返回值 :格式化后数据
public byte[] Order03H(byte Station, ushort inAddr, ushort inNum)
{
byte[] subuffer = new byte[6];
byte[] SendData = new byte[8];
subuffer[0] = Station; //站号
subuffer[1] = 0x03; //功能码
intToBytes(inAddr, 2).CopyTo(subuffer, 2); //起始地址
intToBytes(inNum, 2).CopyTo(subuffer, 4); //数据个数
subuffer.CopyTo(SendData, 0);
CRC16(subuffer).CopyTo(SendData, 6);
return SendData;
}
#endregion
#region 06H功能码 //按照协议格式化 06 指令 返回值 :格式化后数据
public byte[] Order06H(byte Station, ushort inAddr, ushort inNum)
{
byte[] subuffer = new byte[6];
byte[] SendData = new byte[8];
subuffer[0] = Station;
subuffer[1] = 0x06;
intToBytes(inAddr, 2).CopyTo(subuffer, 2);
intToBytes(inNum, 2).CopyTo(subuffer, 4);
subuffer.CopyTo(SendData, 0);
CRC16(subuffer).CopyTo(SendData, 6);
return SendData;
}
#endregion
#region 10H功能码
public bool Order10H(byte Station, ushort inAddr, short[] inShorts)
{
int len = inShorts.Length;
byte[] sendByte = new byte[len * 2];
for (int i = 0; i < len; i++)
{
intToBytes(inShorts[i], 2).CopyTo(sendByte, i * 2);
}
Byte[] subuffer = new Byte[len * 2 + 7];
subuffer[0] = Station; //站号
subuffer[1] = 0x10; //功能码
intToBytes(inAddr, 2).CopyTo(subuffer, 2); //起始地址
intToBytes(len, 2).CopyTo(subuffer, 4); //数据个数
subuffer[6] = (byte)(len * 2); //字节长度
sendByte.CopyTo(subuffer, 7);
byte[] ob = SendData(subuffer);
if (ob == null)
{
return false;
}
else
{
byte[] send_data = new byte[4];
byte[] rec_data = new byte[4];
Array.Copy(subuffer, 2, send_data, 0, 4);
Array.Copy(ob, 2, rec_data, 0, 4);
return CompareArray(send_data, rec_data);
}
}
private byte[] SendData(byte[] subuffer)
{
throw new NotImplementedException();
}
#endregion
#region 判断两个数组是否相等
public bool CompareArray(byte[] bt1, byte[] bt2)
{
if (bt1 == null && bt2 == null)
{
return true;
}
if (bt1 == null || bt2 == null)
{
return false;
}
int len = bt1.Length;
if (len != bt2.Length)
{
return false;
}
for (var i = 0; i < len; i++)
{
if (bt1[i] != bt2[i])
return false;
}
return true;
}
internal byte[] Order10H(byte v1, ushort v2, ushort v3)
{
throw new NotImplementedException();
}
#endregion
}
}
第一次发文,加之是一个古早的程序了,有许多存在纰漏之处,敬请谅解!!!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)