OKLE.cs
6.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OnlineStore.DeviceLibrary
{
public class OKLE
{
private byte[] buffer;
private bool receive;
private System.IO.Ports.SerialPort port;
public OKLE()
{
port = new System.IO.Ports.SerialPort
{
BaudRate = 9600, //设备支持4800,9600,19200,38400,57600,115200
DataBits = 8,
StopBits = System.IO.Ports.StopBits.One,
Parity = System.IO.Ports.Parity.None
};
port.DataReceived += Port_DataReceived;
}
/// <summary>
/// 打开或关闭状态
/// </summary>
public bool IsOpen { get { return port.IsOpen; } }
/// <summary>
/// 打开串口
/// </summary>
/// <param name="comName">串口名</param>
public void Open(string comName)
{
port.PortName = comName;
try
{
port.Open();
}
catch (Exception ex)
{
}
}
/// <summary>
/// 关闭串口
/// </summary>
public void Close()
{
port.Close();
}
/// <summary>
/// 读取数据
/// </summary>
/// <param name="addr">起始地址</param>
/// <returns></returns>
public int Read(short addr)
{
if (!IsOpen) return 0;
byte[] cmd = ReadCmd(addr, 1);
receive = false;
port.Write(cmd, 0, cmd.Length);
bool rtn = WaitReceive();
if (rtn) rtn = SameReturn(cmd);
if (rtn)
{
int num = buffer[3] * 256 + buffer[4];
return num;
}
else
{
return 0;
}
}
/// <summary>
/// 读取数据
/// </summary>
/// <param name="addr">起始地址</param>
/// <param name="count">寄存器数量</param>
/// <returns></returns>
public int[] Read(short addr, short count)
{
if (!IsOpen) return null;
byte[] cmd = ReadCmd(addr, count);
receive = false;
port.Write(cmd, 0, cmd.Length);
bool rtn = WaitReceive();
if (rtn) rtn = SameReturn(cmd);
if (rtn)
{
int len = buffer[2]; //字节数
int[] num = new int[len / 2];
for (int i = 0; i < num.Length; i++)
{
int idx = 3 + i * 2;
num[i] = buffer[idx] * 256 + buffer[idx + 1];
}
return num;
}
else
{
return null;
}
}
/// <summary>
/// 等待数据接收
/// </summary>
/// <returns></returns>
private bool WaitReceive()
{
int sum = 0;
while (true)
{
System.Threading.Thread.Sleep(50);
sum += 50;
if (receive) return true;
if (!IsOpen) return false;
if (sum >= 3000) return false;
}
}
/// <summary>
/// 串口数据接收
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
System.Threading.Thread.Sleep(50);
byte[] buff = new byte[port.ReadBufferSize];
int len = port.Read(buff, 0, buff.Length);
Array.Copy(buff, buffer, len);
receive = true;
}
/// <summary>
/// CRC16冗余校验
/// </summary>
/// <param name="buff"></param>
/// <param name="count"></param>
/// <param name="high"></param>
/// <param name="low"></param>
private void CRC16(byte[] buff, int count, out byte high, out byte low)
{
int crc = 0xFFFF;
int bit;
for (int i = 0; i < count; i++)
{
crc ^= buff[i];
for (int j = 0; j < 8; j++)
{
bit = crc & 1;
crc >>= 1;
if (bit == 0)
{
//crc >>= 1;
}
else
crc ^= 0xA001;
}
}
low = Convert.ToByte(crc & 255);
high = Convert.ToByte((crc >> 8) & 255);
}
/// <summary>
/// 读取命令,功能码03
/// </summary>
/// <param name="addr"></param>
/// <param name="count"></param>
/// <returns></returns>
private byte[] ReadCmd(short addr, short count)
{
byte[] addrArr = BitConverter.GetBytes(addr);
byte[] countArr = BitConverter.GetBytes(count);
byte[] cmd = new byte[8];
cmd[0] = 0x01; //模块地址
cmd[1] = 0x03; //功能码
cmd[2] = addrArr[1]; //高8位
cmd[3] = addrArr[0]; //低8位
cmd[4] = countArr[1]; //高8位
cmd[5] = countArr[0]; //低8位
//CRC16校验
CRC16(cmd, 6, out byte high, out byte low);
cmd[6] = low;
cmd[7] = high;
return cmd;
}
/// <summary>
/// 判断是同一条命令的返回值
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
private bool SameReturn(byte[] cmd)
{
//同一个功能码应答
if (cmd[0] == buffer[0] && cmd[1] == buffer[1])
{
//CRC校验是否相同
int len = cmd.Length - 2;
CRC16(cmd, len, out byte high, out byte low);
return cmd[len] == low && cmd[len + 1] == high;
}
else
{
return false;
}
}
}
}