大家好,又见面了,我是你们的朋友全栈君。
SpSetup 类 与Globalspace类
public partial class SpSetup : Form
{
#region 定义变量
/// <summary>
/// 发送报文
/// </summary>
public byte[] sendData = new byte[8];
#endregion
#region 构造读取状态报文
/// <summary>
/// 构造读取状态报文
/// </summary>
public void GetSendData()
{
byte[] data = new byte[6];
byte[] Address = Globalspace.intToHexByte(Globalspace.startAddress);
byte[] nubmer = Globalspace.intToHexByte(Globalspace.registerNumber);
data[0] = Globalspace.ID; //从机地址
data[1] = Convert.ToByte(Globalspace.modbusPointType.readHoldingRegister); //功能号 - 读取保持寄存器
data[2] = Address[0]; //数据地址
data[3] = Address[1]; //数据地址
data[4] = nubmer[0]; //数据
data[5] = nubmer[1]; //数据
for (int i = 0; i < 6; i++)
{
sendData[i] = data[i]; //报文是用串口发送的
}
Byte[] CRC = new Byte[2];
CRC = Globalspace.CRC_16(data); //进行CRC效验
sendData[6] = CRC[0];
sendData[7] = CRC[1];
}
#endregion
}
class Globalspace
{
#region 定义变量
/// <summary>
/// 定义串口
/// </summary>
public static SerialPort sp = new SerialPort();
/// <summary>
/// Modbus 通讯地址
/// </summary>
public static byte ID = 2;
/// <summary>
/// Modbus 功通讯能码
/// </summary>
public enum modbusPointType
{
readCoilStatus = 01, //读取线圈状态
readInputStatus = 02, //读取输入状态
readHoldingRegister = 03, //读取保持寄存器
readInputRegister = 04, //读取输入寄存器
writeSingleCoil = 05, //强置单线圈
writeSingleRegister = 06, //保持寄存器写入(仅一点)
writeMultipleCoil = 15, //强置多线圈
writeMultipleRegister = 16,//预置多寄存器
};
/// <summary>
/// 起始地址
/// </summary>
public static int startAddress = 99;//读D100地址内容
/// <summary>
/// 读取数量
/// </summary>
public static int registerNumber = 1;//读一个
/// <summary>
/// 读写标志位 true —读;false —写。
/// </summary>
public static bool readORwrite = true;
/// <summary>
/// 读完成标志
/// </summary>
public static bool readDone = true; //读取数据完成后,清零
/// <summary>
/// 写完成标志
/// </summary>
public static bool writeDone = true;//写入数据完成后,清零
/// <summary>
/// 创建发送表
/// </summary>
public static ArrayList sendList = new ArrayList();//创建发送表
/// <summary>
/// 创建接收表
/// </summary>
public static ArrayList receivedList = new ArrayList();//创建接收表
/// <summary>
/// 读数据定时器
/// </summary>
public static System.Timers.Timer readTimer = new System.Timers.Timer(2000);
/// <summary>
/// 写数据定时器
/// </summary>
public static System.Timers.Timer writeTimer = new System.Timers.Timer(2000);
public static string Info = "";
/// <summary>
/// 监听
/// </summary>
public static TcpListener listener;
/// <summary>
/// TCP/IP连接标志
/// </summary>
public static bool TcpIP = false;
public static bool TH_SP = false;
/// <summary>
/// PLC通讯标志
/// </summary>
public static bool PLC = false;
/// <summary>
/// 接收数据
/// </summary>
public static ArrayList receivedDataList= new ArrayList();
/// <summary>
/// 检测结果
/// </summary>
public static string testResult; //1-通过;0-失败;2-定位失败!
#endregion
#region CRC_16计算
/// <summary>
/// CRC_16计算
/// </summary>
/// <param name="data">数据</param>
/// <returns>返回CRC值</returns>
public static Byte[] CRC_16(Byte[] data) //CRC验证码计算
{
Byte[] CRC = new byte[2];
UInt16 Reg_Crc = 0xFFFF;
for (int i = data.Length; i > 0; i--)
{
Reg_Crc ^= data[data.Length - i];
for (int j = 0; j < 8; j++)
{
if ((Reg_Crc & 0x01) == 1)
{
Reg_Crc >>= 1;
Reg_Crc ^= 0xA001;
}
else
{
Reg_Crc >>= 1;
}
}
}
CRC[0] = (byte)(Reg_Crc & 0xFF);
CRC[1] = (byte)(Reg_Crc >>= 8);
return CRC;
}
public static Byte[] CRC_16(ArrayList sendData) //CRC验证码计算
{
byte[] send = new byte[sendData.ToArray().Length];
Object[] obj = Globalspace.sendList.ToArray();
for (int i = 0; i < sendData.ToArray().Length; i++)
{
send[i] = (byte)obj[i];
}
Byte[] CRC = new byte[2];
UInt16 Reg_Crc = 0xFFFF;
for (int i = send.Length; i > 0; i--)
{
Reg_Crc ^= send[send.Length - i];
for (int j = 0; j < 8; j++)
{
if ((Reg_Crc & 0x01) == 1)
{
Reg_Crc >>= 1;
Reg_Crc ^= 0xA001;
}
else
{
Reg_Crc >>= 1;
}
}
}
CRC[0] = (byte)(Reg_Crc & 0xFF);
CRC[1] = (byte)(Reg_Crc >>= 8);
return CRC;
}
#endregion
#region 接收数据完成事件
/// <summary>
/// 接收数据完成事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
Control.CheckForIllegalCrossThreadCalls = false;
int n = sp.BytesToRead; //接收字节数
receivedList.Clear(); //清空接收缓存
byte[] Buuf = new byte[n]; //接收字符串
byte[] Data = new byte[n - 2];
byte[] Data_CRC = new byte[2];
sp.Read(Buuf, 0, n);
if (n <= 8)
{
for (int i = 0; i < n; i++)
{
if (i < n - 2)
{
Data[i] = Buuf[i]; //分离CRC重构字符串
}
receivedList.Add(Buuf[i]);
}
Data_CRC = CRC_16(Data); //计算CRC_16校验码
//WriteLog();
if (Data[0] == ID)
{
if (readORwrite)
{
byte[] temp = ReadData(Data, Data_CRC, Buuf, n);
if(Buuf[2]>2) //读处理
{
receivedDataList.Clear();
for(int i=0;i<temp.Length;i++)
{
receivedDataList.Add(temp[i]);
}
}
else
{
if(temp[1]==(byte)0x01)
{
PLC = true;
}
else
{
PLC = false;
}
}
}
else
{
//WriteData(Data, Data_CRC, Buuf, n);//写处理
writeDone = true;
}
}
else
{
//MessageBox.Show("通讯错误:设备地址错误!", "系统提示");
}
}
}
catch (Exception err)
{
//MessageBox.Show(err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
#endregion
#region 读状态方法
/// <summary>
/// 读状态
/// </summary>
/// <param name="Data">数据</param>
/// <param name="Data_CRC">CRC 验证码</param>
/// <param name="Buuf">接收数据</param>
/// <param name="n">数据长度</param>
private static byte[] ReadData(byte[] Data, byte[] Data_CRC, byte[] Buuf, int n)
{
byte[] dataTemp = new byte[Buuf.Length-5];
if(n > 6) //小于7抛弃报文
{
if (Data[1] == Convert.ToByte(modbusPointType.readHoldingRegister))
{
if (Buuf[n - 2] == Data_CRC[0] && Buuf[n - 1] == Data_CRC[1])
{
for (int i = 0; i < dataTemp.Length;i++ )
{
dataTemp[i] = Buuf[i + 3];
}
readDone = true;
return dataTemp;
}
else
{
MessageBox.Show("通讯错误:读取CRC校验码错误!", "系统提示");
return dataTemp;
}
}
else
{
MessageBox.Show("通讯错误:读取功能码错误!", "系统提示");
return dataTemp;
}
}
else
{
readDone = false;
return dataTemp;
}
}
#endregion
#region 写数据方法
/// <summary>
/// 写数据
/// </summary>
/// <param name="Data">数据</param>
/// <param name="Data_CRC">CRC_16校验码</param>
/// <param name="Buuf">收到报文</param>
/// <param name="n">收到数据长度</param>
private static void WriteData(byte[] Data, byte[] Data_CRC, byte[] Buuf, int n)
{
if (n > 6)
{
if (Data[1] == Convert.ToByte(modbusPointType.writeMultipleRegister) || Data[1] == Convert.ToByte(modbusPointType.writeSingleRegister))
{
if (Buuf[n - 2] == Data_CRC[0] && Buuf[n - 1] == Data_CRC[1])
{
writeDone = true;
}
else
{
MessageBox.Show("通讯错误:写入CRC校验码错误!", "系统提示");
}
}
else
{
MessageBox.Show("通讯错误:写入功能码错误!", "系统提示");
}
}
}
#endregion
#region int转换byte
/// <summary>
/// int转换byte
/// </summary>
/// <param name="inInt"></param>
/// <returns></returns>
public static byte[] intToHexByte(int inInt)
{
string hexString = inInt.ToString("x4"); //X:代表16进制 //4:代表每次的数据位数,当位数不足时自动补0
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
{
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
return returnBytes;
}
public static byte[] intToHexByte2(int inIt)
{
byte[] returnByte = BitConverter.GetBytes(inIt);
return returnByte;
}
#endregion
#region short转换byte
/// <summary>
/// short转换byte
/// </summary>
/// <param name="inShort"></param>
/// <returns></returns>
public static byte[] shortToByte(short inShort)
{
byte[] abyte0 = new byte[2];
abyte0[1] = (byte)(0xff & inShort);
abyte0[0] = (byte)((0xff00 & inShort) >> 8);
return abyte0;
}
public static byte[] shortToByte2(short inShort)
{
byte[] returnBytes = BitConverter.GetBytes(inShort);
return returnBytes;
}
#endregion
#region 通讯超时处理
/// <summary>
/// 通讯超时处理
/// </summary>
public static void Timeout()
{
if (readORwrite)
{
readTimer.Elapsed += new System.Timers.ElapsedEventHandler(ReadOut);//到达时间的时候执行事件;
readTimer.AutoReset = true;//设置是执行一次(false)还是一直执行(true);
readTimer.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件;
}
else
{
writeTimer.Elapsed += new System.Timers.ElapsedEventHandler(WriteOut);//到达时间的时候执行事件;
writeTimer.AutoReset = false;//设置是执行一次(false)还是一直执行(true);
writeTimer.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件;
}
}
/// <summary>
/// 读超时事件
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
public static void ReadOut(object source, System.Timers.ElapsedEventArgs e)
{
readDone = true;
}
/// <summary>
/// 写超时事件
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
public static void WriteOut(object source, System.Timers.ElapsedEventArgs e)
{
writeDone = true;
}
#endregion
#region 报文日志
/// <summary>
/// 入日志文件
/// </summary>
/// <param name="data">报文</param>
public static void WriteLog()
{
FileStream tempStream = new FileStream(Environment.CurrentDirectory + @"\Log.txt", FileMode.Append);
StreamWriter writer = new StreamWriter(tempStream);
string[] data = new string[receivedList.Count];
string st = null;
for (int j = 0; j < receivedList.Count; j++)
{
data[j] = receivedList[j].ToString();
st = st + data[j] + " ";
}
writer.WriteLine("接收数据:" + st + "\n");
writer.Close();
tempStream.Close();
}
#endregion
#region 配置文件操作
/// <summary>
/// 读取数据
/// </summary>
/// <param name="patch">文件路径</param>
/// <param name="line">行数</param>
/// <returns>返回字符串</returns>
public static string ReadeFile(string patch, int line)
{
string readstr;
string strTemp = "";
FileStream tempStream = new FileStream(patch, FileMode.Open);
StreamReader reader = new StreamReader(tempStream);
for (int i = 1; !reader.EndOfStream; i++)
{
if (i == line)
{
strTemp = reader.ReadLine();
}
else
{
reader.ReadLine();
}
}
reader.Close();
reader.Dispose();
readstr = strTemp;
return readstr;
}
/// <summary>
/// 更改数据
/// </summary>
/// <param name="curLine">修改的行数</param>
/// <param name="newLineValue">保存的值</param>
/// <param name="patch">文件的路径</param>
public static void EditFile(int curLine, string newLineValue, string patch)
{
FileStream fs = new FileStream(patch, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, Encoding.GetEncoding("utf-8"));
string line = sr.ReadLine();
StringBuilder sb = new StringBuilder();
for (int i = 1; line != null; i++)
{
sb.Append(line + "\r\n");
if (i != curLine - 1)
line = sr.ReadLine();
else
{
sr.ReadLine();
line = newLineValue;
}
}
sr.Close();
fs.Close();
FileStream fs1 = new FileStream(patch, FileMode.Open, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs1);
sw.Write(sb.ToString());
sw.Close();
fs.Close();
}
#endregion
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/157958.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...