终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

749 lines
28 KiB

  1. using BPASmartClient.Helper;
  2. using BPASmartClient.Message;
  3. //using BPASmartClient.Message;
  4. using NModbus;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.Linq;
  9. using System.Net.Sockets;
  10. using System.Text;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. namespace BPASmartClient.Modbus
  14. {
  15. public class ModbusTcp
  16. {
  17. //private volatile static ModbusTcp _Instance;
  18. //public static ModbusTcp GetInstance => _Instance ?? (_Instance = new ModbusTcp());
  19. //private ModbusTcp() { }
  20. private ModbusFactory modbusFactory;
  21. private IModbusMaster master;
  22. private TcpClient tcpClient;
  23. private ManualResetEvent mre = new ManualResetEvent(false);
  24. public string IPAdress;
  25. public int Port;
  26. public Action<string> Show { get; set; }
  27. public Action<string> ShowEx { get; set; }
  28. /// <summary>
  29. /// 连接plc 原料设备成功
  30. /// </summary>
  31. public Action ConnectOk { get; set; }
  32. public Action ConnectFail { get; set; }
  33. public Action Disconnect { get; set; }
  34. public bool IsReconnect { get; set; } = false; //true=启用重连,false=禁用重连
  35. /// <summary>
  36. /// 判断是否连接成功
  37. /// </summary>
  38. public bool Connected => tcpClient == null ? false : tcpClient.Connected;
  39. /// <summary>
  40. /// ModbusTcp 连接设备
  41. /// </summary>
  42. /// <param name="ip">ip 地址</param>
  43. /// <param name="port">端口号,默认502</param>
  44. public void ModbusTcpConnect(string ip, int port = 502)
  45. {
  46. Show?.Invoke($"设备【{ip}:{port}】连接中。。。。");
  47. IPAdress = ip;
  48. Port = port;
  49. modbusFactory = new ModbusFactory();
  50. Connect();
  51. if (Connected)
  52. {
  53. master.Transport.ReadTimeout = 3000;//读取超时时间
  54. master.Transport.WriteTimeout = 3000;//写入超时时间
  55. master.Transport.Retries = 10;//重试次数
  56. ConnectOk?.Invoke();
  57. Show?.Invoke($"设备【{ip}:{port}】连接成功");
  58. }
  59. else
  60. {
  61. ConnectFail?.Invoke();
  62. }
  63. }
  64. public void Dispose()
  65. {
  66. master.Dispose();
  67. Disconnect?.Invoke();
  68. }
  69. private void Connect()
  70. {
  71. bool ErrorFlag = false;
  72. while (!Connected)
  73. {
  74. try
  75. {
  76. tcpClient = new TcpClient(IPAdress, Port);
  77. //mre.Reset();
  78. //tcpClient.BeginConnect(IPAdress, Port, (res) => { mre.Set(); }, null);
  79. //if (!mre.WaitOne(1500, false)) break;
  80. master = modbusFactory.CreateMaster(tcpClient);
  81. }
  82. catch (Exception ex)
  83. {
  84. if (!ErrorFlag)
  85. {
  86. ShowEx?.Invoke($"ModbusTcp 连接失败,IP = {IPAdress},Port = {Port}");
  87. ShowEx?.Invoke(ex.ToString());
  88. ErrorFlag = true;
  89. }
  90. if (!IsReconnect) break;
  91. Thread.Sleep(3000);
  92. }
  93. }
  94. if (ErrorFlag && IsReconnect) Show?.Invoke("ModbusTcp 重连成功!");
  95. }
  96. /// <summary>
  97. /// 获取 M 区 和 VW 区的Modbus的地址
  98. /// </summary>
  99. /// <param name="address"></param>
  100. /// <returns></returns>
  101. public int GetAddress(string address)
  102. {
  103. if (address == null) return -1;
  104. if (address.Length > 0)
  105. {
  106. address = address.Trim();
  107. if (address.ToUpper().Contains("GM") && address.Length >= 3)
  108. {
  109. var res = address.Remove(0, 2);
  110. if (res != null && res.Length > 0)
  111. {
  112. return int.Parse(res) + 4096;
  113. }
  114. }
  115. else if (address.ToUpper().Contains("M") && address.Length >= 4)
  116. {
  117. var res = address.Substring(1).Split('.');
  118. if (res != null && res.Length == 2)
  119. {
  120. if (int.TryParse(res[0], out int firstAddress) && int.TryParse(res[1], out int ExitAddress))
  121. {
  122. if (ExitAddress >= 0 && ExitAddress <= 7)
  123. {
  124. return (firstAddress * 8) + 320 + ExitAddress;
  125. }
  126. }
  127. }
  128. }
  129. else if (address.ToUpper().Contains("I") && address.Length >= 2)
  130. {
  131. var res = address.Substring(1).Split('.');
  132. if (res != null && res.Length == 2)
  133. {
  134. if (int.TryParse(res[0], out int firstAddress) && int.TryParse(res[1], out int ExitAddress))
  135. {
  136. if (ExitAddress >= 0 && ExitAddress <= 7)
  137. {
  138. return (firstAddress * 8) + ExitAddress;
  139. }
  140. }
  141. }
  142. }
  143. else if (address.ToUpper().Contains("GI") && address.Length >= 3)
  144. {
  145. var res = address.Remove(0, 2);
  146. if (res != null && res.Length > 0)
  147. {
  148. return int.Parse(res);
  149. }
  150. }
  151. else if (address.ToUpper().Contains("LB") && address.Length >= 3)
  152. {
  153. var res = address.Substring(2);
  154. if (res != null && res.Length > 0)
  155. {
  156. if (int.TryParse(res, out int firstAddress))
  157. {
  158. return firstAddress;
  159. }
  160. }
  161. }
  162. else if ((address.ToUpper().Contains("VW") || address.ToUpper().Contains("VD")) && address.Length >= 3)
  163. {
  164. var res = address.Substring(2);
  165. if (res != null && int.TryParse(res, out int tempAddress))
  166. {
  167. return (tempAddress / 2) + 100;
  168. }
  169. }
  170. else if (address.ToUpper().Contains("LW") && address.Length >= 3)
  171. {
  172. var res = address.Substring(2);
  173. if (res != null && int.TryParse(res, out int LwAddress))
  174. {
  175. return LwAddress;
  176. }
  177. }
  178. else if (address.ToUpper().Contains("D") && address.Length == 5)
  179. {
  180. try
  181. {
  182. //D1001
  183. string head = (Convert.ToInt32(address.Substring(1, 1))).ToString();
  184. int num = Convert.ToInt32(address.Substring(2, 3));
  185. int len = num.ToString().Length;
  186. string tail = string.Empty;
  187. switch (len)
  188. {
  189. case 1:
  190. if ((Convert.ToInt32(address.Substring(4, 1))).ToString().Length > 1)
  191. {
  192. tail = "0" + (Convert.ToInt32(address.Substring(4, 1))).ToString();
  193. }
  194. else
  195. {
  196. tail = "00" + (Convert.ToInt32(address.Substring(4, 1))).ToString();
  197. }
  198. break;
  199. case 2:
  200. if ((Convert.ToInt32(address.Substring(3, 2))).ToString().Length > 2)
  201. {
  202. tail = (Convert.ToInt32(address.Substring(3, 2))).ToString();
  203. }
  204. else
  205. {
  206. tail = "0" + (Convert.ToInt32(address.Substring(3, 2))).ToString();
  207. }
  208. break;
  209. case 3:
  210. tail = (Convert.ToInt32(address.Substring(2, 3))).ToString();
  211. break;
  212. }
  213. address = head + tail;
  214. return Convert.ToInt32(address);
  215. }
  216. catch (Exception)
  217. {
  218. //打印日志
  219. }
  220. }
  221. }
  222. return -1;
  223. }
  224. private void ExceptionHandling(Exception ex)
  225. {
  226. if (ex.InnerException is SocketException)
  227. {
  228. if (IsReconnect)
  229. {
  230. tcpClient = null;
  231. Connect();
  232. }
  233. Disconnect?.Invoke();
  234. }
  235. }
  236. public short ReadShort(string address)
  237. {
  238. var res = Read(address);
  239. if (res != null && res is short[] shorts && shorts.Length == 1)
  240. {
  241. return shorts[0];
  242. }
  243. return 0;
  244. }
  245. public object Read(string address, ushort len = 1, byte slaveAddress = 1)
  246. {
  247. if (address == null || tcpClient == null) return default(object);
  248. ushort startAddress = (ushort)GetAddress(address);
  249. CommandType commandType = CommandType.Coils;
  250. try
  251. {
  252. if (address.ToUpper().Contains("M") || address.ToUpper().Contains("GM"))
  253. {
  254. commandType = CommandType.Coils;
  255. return master.ReadCoils(slaveAddress, startAddress, len);
  256. }
  257. else if (address.ToUpper().Contains("VD"))
  258. {
  259. commandType = CommandType.HoldingRegisters;
  260. var var1 = master.ReadHoldingRegisters(slaveAddress, startAddress, len);
  261. var var2 = master.ReadHoldingRegisters(slaveAddress, (ushort)(startAddress + 1), len);
  262. int dest = 0;
  263. dest |= (var2[0] & 0x0000ffff);
  264. dest = (dest << 16) | (var1[0] & 0x0000ffff);
  265. return dest;
  266. }
  267. else if (address.ToUpper().Contains("VW") || address.ToUpper().Contains("LW") || address.ToUpper().Contains("D"))
  268. {
  269. commandType = CommandType.HoldingRegisters;
  270. return master.ReadHoldingRegisters(slaveAddress, startAddress, len);
  271. }
  272. else if (address.ToUpper().Contains("VD"))
  273. {
  274. commandType = CommandType.HoldingRegisters;
  275. var var1 = master.ReadHoldingRegisters(slaveAddress, startAddress, len);
  276. var var2 = master.ReadHoldingRegisters(slaveAddress, (ushort)(startAddress + 2), len);
  277. int dest = 0;
  278. dest |= (var2[0] & 0x0000ffff);
  279. dest = (dest << 16) | (var1[0] & 0x0000ffff);
  280. return dest;
  281. }
  282. else if (address.ToUpper().Contains("I"))
  283. {
  284. commandType = CommandType.Inputs;
  285. return master.ReadInputs(slaveAddress, startAddress, len);
  286. }
  287. else if (address.ToUpper().Contains("LB"))
  288. {
  289. commandType = CommandType.Coils;
  290. return master.ReadCoils(slaveAddress, startAddress, len);
  291. }
  292. }
  293. catch (Exception ex)
  294. {
  295. ShowEx?.Invoke($"读取地址:【{address}:= {startAddress}】,读取类型:【{commandType.ToString()}】出错,{ex.ToString()}");
  296. ExceptionHandling(ex);
  297. }
  298. return default(object);
  299. }
  300. /// <summary>
  301. /// 写入数据
  302. /// </summary>
  303. /// <typeparam name="T"></typeparam>
  304. /// <param name="address">写入地址</param>
  305. /// <param name="value">写入值</param>
  306. /// <param name="Retries">重试次数</param>
  307. /// <param name="slaveAddress">从站地址</param>
  308. /// <returns></returns>
  309. public bool Write<T>(string address, T value, int Retries = 1, byte slaveAddress = 1)
  310. {
  311. int count = 0;
  312. if (Retries == 1 || Retries == 0)
  313. {
  314. return TempWrite(address, value, slaveAddress);
  315. }
  316. else if (Retries > 1)
  317. {
  318. bool isok = false;
  319. while (count < Retries)
  320. {
  321. count++;
  322. TempWrite(address, value, slaveAddress);
  323. var res = Read(address);
  324. if (res != null && res.ToString() == value.ToString())
  325. {
  326. isok = true;
  327. break;
  328. }
  329. }
  330. return isok;
  331. }
  332. return false;
  333. }
  334. private bool TempWrite<T>(string address, T value, byte slaveAddress = 1)
  335. {
  336. if (address == null || tcpClient == null)
  337. {
  338. Show?.Invoke("写入失败,地址为空或断开连接");
  339. return false;
  340. }
  341. ushort startAddress = (ushort)GetAddress(address);
  342. CommandType commandType = CommandType.Coils;
  343. try
  344. {
  345. if (address.ToUpper().Contains("M"))
  346. {
  347. commandType = CommandType.Coils;
  348. if (value is bool boolValue)
  349. master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
  350. else if (value is bool[] boolsValue)
  351. master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
  352. else return false;
  353. }
  354. if (address.ToUpper().Contains("GM") && address.Length >= 3)
  355. {
  356. commandType = CommandType.Coils;
  357. if (value is bool boolValue)
  358. master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
  359. else if (value is bool[] boolsValue)
  360. master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
  361. else return false;
  362. }
  363. else if (address.ToUpper().Contains("LB"))
  364. {
  365. commandType = CommandType.Coils;
  366. if (value is bool boolValue)
  367. master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
  368. else if (value is bool[] boolsValue)
  369. master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
  370. else return false;
  371. }
  372. else if (address.ToUpper().Contains("VD"))
  373. {
  374. commandType = CommandType.HoldingRegisters;
  375. if (value is int intValue)
  376. {
  377. var val1 = (UInt16)intValue;
  378. var val2 = Convert.ToUInt16(intValue >> 16 & 0x0000ffff);
  379. master.WriteSingleRegister(slaveAddress, startAddress, val1);
  380. master.WriteSingleRegister(slaveAddress, (ushort)(startAddress + 1), val2);
  381. }
  382. else return false;
  383. }
  384. else if (address.ToUpper().Contains("VW") || address.ToUpper().Contains("LW") || address.ToUpper().Contains("D"))
  385. {
  386. commandType = CommandType.HoldingRegisters;
  387. if (value is ushort ushortValue)
  388. master.WriteSingleRegister(slaveAddress, startAddress, ushortValue);
  389. else if (value is ushort[] ushortsValue)
  390. {
  391. int len = 100;
  392. if (ushortsValue.Length > len)
  393. {
  394. List<ushort[]> ushortLists = new List<ushort[]>();
  395. for (int i = 0; i < ushortsValue.Length / len; i++)
  396. {
  397. ushortLists.Add(ushortsValue.Skip(0).Take(len).ToArray());
  398. }
  399. int y = ushortsValue.Length % len;
  400. if (y > 0)
  401. {
  402. ushortLists.Add(ushortsValue.Skip(ushortsValue.Length - y).Take(y).ToArray());
  403. }
  404. foreach (var item in ushortLists)
  405. {
  406. master.WriteMultipleRegisters(slaveAddress, startAddress, item);
  407. startAddress += (ushort)item.Length;
  408. }
  409. }
  410. else
  411. {
  412. master.WriteMultipleRegisters(slaveAddress, startAddress, ushortsValue);
  413. }
  414. }
  415. else return false;
  416. }
  417. else if (address.ToUpper().Contains("I"))
  418. {
  419. commandType = CommandType.Inputs;
  420. }
  421. //Show?.Invoke($"成功,地址:{address},值:{value}");
  422. return true;
  423. }
  424. catch (Exception ex)
  425. {
  426. ShowEx?.Invoke($"写入地址:【{address}:= {startAddress}】,写入类型:【{commandType.ToString()}】出错,{ex.ToString()}");
  427. ExceptionHandling(ex);
  428. return false;
  429. }
  430. }
  431. #region 字符串数据读写
  432. /// <summary>
  433. /// 赋值string
  434. /// </summary>
  435. /// <param name="StartAddress"></param>
  436. /// <param name="value"></param>
  437. /// <returns></returns>
  438. public void SetString(string StartAddress, string value)
  439. {
  440. //获取指定的编码不存在的时候需要安装 System.Text.Encoding.CodePages nuget包
  441. //然后使用下面的代码就可以获取了
  442. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  443. var bytes = Encoding.GetEncoding("gb2312")?.GetBytes(value);
  444. Write(StartAddress, bytes.BytesToUshorts());
  445. }
  446. /// <summary>
  447. /// 获取string
  448. /// </summary>
  449. /// <param name="StartAddress"></param>
  450. /// <param name="len"></param>
  451. /// <returns></returns>
  452. public string GetString(string StartAddress, ushort len)
  453. {
  454. var res = Read(StartAddress, len);
  455. if (res != null && res is ushort[] ushorts)
  456. {
  457. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  458. return Encoding.GetEncoding("gb2312")?.GetString(ushorts.UshortsToBytes()).Trim(new char[] { '\0' });
  459. }
  460. return String.Empty;
  461. }
  462. #endregion
  463. #region 浮点数数据读写
  464. /// <summary>
  465. /// 赋值Real类型数据
  466. /// </summary>
  467. /// <param name="StartAddress"></param>
  468. /// <param name="value"></param>
  469. public bool SetReal(string StartAddress, float value, int Retries = 1)
  470. {
  471. var bytes = BitConverter.GetBytes(value);
  472. return Write(StartAddress, bytes.BytesToUshorts(), Retries);
  473. }
  474. /// <summary>
  475. /// 获取float类型数据
  476. /// </summary>
  477. /// <param name="StartAddress"></param>
  478. /// <returns></returns>
  479. public float GetReal(string StartAddress)
  480. {
  481. var res = Read(StartAddress, 2);
  482. if (res != null && res is ushort[] ushorts)
  483. {
  484. return BitConverter.ToSingle(ushorts.UshortsToBytes(), 0);
  485. }
  486. return 0;
  487. }
  488. #endregion
  489. #region 整数数据读写
  490. /// <summary>
  491. /// 赋值Real类型数据
  492. /// </summary>
  493. /// <param name="StartAddress"></param>
  494. /// <param name="value"></param>
  495. public void SetUint(string StartAddress, uint value)
  496. {
  497. var bytes = BitConverter.GetBytes(value);
  498. Write(StartAddress, bytes.BytesToUshorts());
  499. }
  500. /// <summary>
  501. /// 获取float类型数据
  502. /// </summary>
  503. /// <param name="StartAddress"></param>
  504. /// <returns></returns>
  505. public uint GetUint(string StartAddress)
  506. {
  507. var res = Read(StartAddress, 2);
  508. if (res != null && res is ushort[] ushorts)
  509. {
  510. return BitConverter.ToUInt32(ushorts.UshortsToBytes(), 0);
  511. }
  512. return 0;
  513. }
  514. #endregion
  515. #region 批量数据读取
  516. /// <summary>
  517. /// 读取多个线圈
  518. /// </summary>
  519. /// <param name="startAddress"></param>
  520. /// <param name="num"></param>
  521. /// <param name="slaveAddress"></param>
  522. /// <returns></returns>
  523. public bool[] ReadCoils(ushort startAddress, ushort num, byte slaveAddress = 1)
  524. {
  525. return master.ReadCoils(slaveAddress, startAddress, num);
  526. }
  527. /// <summary>
  528. /// 读取多个输入线圈
  529. /// </summary>
  530. /// <param name="startAddress"></param>
  531. /// <param name="num"></param>
  532. /// <param name="slaveAddress"></param>
  533. /// <returns></returns>
  534. public bool[] ReadInputs(ushort startAddress, ushort num, byte slaveAddress = 1)
  535. {
  536. return master.ReadInputs(slaveAddress, startAddress, num);
  537. }
  538. /// <summary>
  539. /// 读取多个保持寄存器
  540. /// </summary>
  541. /// <param name="startAddress"></param>
  542. /// <param name="num"></param>
  543. /// <param name="slaveAddress"></param>
  544. /// <returns></returns>
  545. public ushort[] ReadHoldingRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
  546. {
  547. return master.ReadHoldingRegisters(slaveAddress, startAddress, num);
  548. }
  549. /// <summary>
  550. /// 读取多个输入寄存器
  551. /// </summary>
  552. /// <param name="startAddress"></param>
  553. /// <param name="num"></param>
  554. /// <param name="slaveAddress"></param>
  555. /// <returns></returns>
  556. public ushort[] ReadInputRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
  557. {
  558. return master.ReadInputRegisters(slaveAddress, startAddress, num);
  559. }
  560. #endregion
  561. #region 批量数据写入
  562. /// <summary>
  563. /// 写入多个线圈
  564. /// </summary>
  565. /// <param name="startAddress"></param>
  566. /// <param name="value"></param>
  567. /// <param name="slaveAddress"></param>
  568. public void WriteMultipleCoils(ushort startAddress, bool[] value, byte slaveAddress = 1)
  569. {
  570. master.WriteMultipleCoils(slaveAddress, startAddress, value);
  571. }
  572. /// <summary>
  573. /// 写入多个寄存器
  574. /// </summary>
  575. /// <param name="startAddress"></param>
  576. /// <param name="value"></param>
  577. /// <param name="slaveAddress"></param>
  578. public void WriteMultipleRegisters(ushort startAddress, ushort[] value, byte slaveAddress = 1)
  579. {
  580. master.WriteMultipleRegisters(slaveAddress, startAddress, value);
  581. }
  582. #endregion
  583. #region 单个数据读取
  584. /// <summary>
  585. /// 读取单个线圈
  586. /// </summary>
  587. /// <param name="startAddress"></param>
  588. /// <param name="slaveAddress"></param>
  589. /// <returns></returns>
  590. public bool ReadCoils(ushort startAddress, byte slaveAddress = 1)
  591. {
  592. var result = master.ReadCoils(slaveAddress, startAddress, 1);
  593. if (result == null) return false;
  594. if (result.Length == 1) return result[0];
  595. return false;
  596. //return master.ReadCoils(slaveAddress, startAddress, 1)[0];
  597. }
  598. /// <summary>
  599. /// 读取单个输入线圈
  600. /// </summary>
  601. /// <param name="startAddress"></param>
  602. /// <param name="slaveAddress"></param>
  603. /// <returns></returns>
  604. public bool ReadInputs(ushort startAddress, byte slaveAddress = 1)
  605. {
  606. var result = master.ReadInputs(slaveAddress, startAddress, 1);
  607. if (result == null) return false;
  608. if (result.Length == 1) return result[0];
  609. return false;
  610. //return master.ReadInputs(slaveAddress, startAddress, 1)[0];
  611. }
  612. /// <summary>
  613. /// 读取单个保持寄存器
  614. /// </summary>
  615. /// <param name="startAddress"></param>
  616. /// <param name="slaveAddress"></param>
  617. /// <returns></returns>
  618. public ushort ReadHoldingRegisters(ushort startAddress, byte slaveAddress = 1)
  619. {
  620. if (tcpClient == null) return 0;
  621. ushort[] result = null;
  622. try
  623. {
  624. result = master.ReadHoldingRegisters(slaveAddress, startAddress, 1);
  625. }
  626. catch (Exception ex)
  627. {
  628. ShowEx?.Invoke(ex.ToString());
  629. tcpClient = null;
  630. Connect();
  631. }
  632. if (result == null) return 0;
  633. if (result.Length == 1) return result[0];
  634. return 0;
  635. //return master.ReadHoldingRegisters(slaveAddress, startAddress, 1)[0];
  636. }
  637. /// <summary>
  638. /// 读取单个输入寄存器
  639. /// </summary>
  640. /// <param name="startAddress"></param>
  641. /// <param name="slaveAddress"></param>
  642. /// <returns></returns>
  643. public ushort ReadInputRegisters(ushort startAddress, byte slaveAddress = 1)
  644. {
  645. var result = master.ReadInputRegisters(slaveAddress, startAddress, 1);
  646. if (result == null) return 0;
  647. if (result.Length == 1) return result[0];
  648. return 0;
  649. //return master.ReadInputRegisters(slaveAddress, startAddress, 1)[0];
  650. }
  651. #endregion
  652. #region 单个数据写入
  653. /// <summary>
  654. /// 写入单个线圈
  655. /// </summary>
  656. /// <param name="startAddress"></param>
  657. /// <param name="value"></param>
  658. /// <param name="slaveAddress"></param>
  659. public void WriteSingleCoil(ushort startAddress, bool value, byte slaveAddress = 1)
  660. {
  661. master.WriteSingleCoil(slaveAddress, startAddress, value);
  662. }
  663. /// <summary>
  664. /// 写入单个寄存器
  665. /// </summary>
  666. /// <param name="startAddress"></param>
  667. /// <param name="value"></param>
  668. /// <param name="slaveAddress"></param>
  669. public void WriteSingleRegister(ushort startAddress, ushort value, byte slaveAddress = 1)
  670. {
  671. master.WriteSingleRegister(slaveAddress, startAddress, value);
  672. }
  673. #endregion
  674. }
  675. public enum CommandType
  676. {
  677. /// <summary>
  678. /// 线圈操作
  679. /// </summary>
  680. Coils,
  681. /// <summary>
  682. /// 输入线圈操作
  683. /// </summary>
  684. Inputs,
  685. /// <summary>
  686. /// 保持寄存器操作
  687. /// </summary>
  688. HoldingRegisters,
  689. /// <summary>
  690. /// 输入寄存器操作
  691. /// </summary>
  692. InputRegisters,
  693. }
  694. }