123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577 |
- using Modbus;
- using Modbus.Device;
- using Modbus.IO;
- using MV485.model;
- using System;
- using System.Collections.Generic;
- using System.IO.Ports;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace MV485.helper
- {
- //读取设备的基本参数
- public class RWBasicConfig
- {
- private SerialPort _serialPort;
- private ModbusSerialMaster _modbusMaster;
- private ModbusSerialTransport _modbusTransport;
- private byte[] sentData; //发送到设备的数据
- private byte[] recvData; //从设备接收的数据
- //private bool _isRead = false; //已经读取的标志
- //public bool IsRead { get; set; }
- private string _portName;
- private int _readBaudrate; //读时使用的波特率额
- private int _readDevId; //读时使用的地址
- private string _message;
- //public event Action<bool, string, int, byte> SearchFinished;
- public event Action<string> RWLog;
- public event Action<bool> SerialConnected; //串口是否已连接
- public event Action<bool> SerialStatusChanged; //串口连接状态变化
- public RWBasicConfig()
- {
- //IsRead = false;
- }
-
- public BasicConfig ReadBasicConfig(string portName,int baudrate,byte devId)
- {
- //IsRead = false;
- BasicConfig config = null;
- _portName = portName;
- _readBaudrate = baudrate;
- _readDevId = devId;
- if (OpenSerial(portName, baudrate))
- {
- config = GetBasicConfig(devId);
- }
- CloseSerial();
- //IsRead = true;
- return config;
- }
- public bool WriteBasicConfig(BasicConfig readConfig, BasicConfig writeConfig)
- {
- //设置波特率
- try
- {
- if (OpenSerial(_portName, _readBaudrate))
- //if(OpenSerial("COM1",14400))
- {
- //地址要最后设置
- bool blSetDeviceAddress = true;
- if (readConfig.DeviceAddress != writeConfig.DeviceAddress)
- {
- blSetDeviceAddress = SetDeviveAddress(readConfig.DeviceAddress, writeConfig.DeviceAddress);
- }
- //波特率要最后设置,因为改变波特率设备要重启
- bool blSetBaudRate = true;
- if (readConfig.BaudRate != writeConfig.BaudRate)
- {
- blSetBaudRate = SetBaudRate(readConfig.DeviceAddress, writeConfig.BaudRate);
- }
- //IsRead = false;
- return blSetBaudRate && blSetDeviceAddress;
- }
- }
- catch { }
- finally
- {
- CloseSerial();
- }
- return false;
- }
- //获取485参数
- private BasicConfig GetBasicConfig(byte devId)
- {
- BasicConfig config = null;
- try
- {
- string deviceType = GetDeviceType(devId);
- string deviceSn = GetDeviceSn(devId);
- string fireware = GetFireware(devId);
- byte devAddress = GetDeiveAddress(devId);
- //bool blBaudRate = GetBaudrate(devId, out int baudrate, out string parityName, out string stopbitsName);
- bool blBaudRate = GetBaudrate(devId, out int baudrate);
- bool blParity = GetPartyName(devId, out string parityName);
- bool blStopbits = GetStopbitsName(devId, out string stopbitsName);
- if (!string.IsNullOrEmpty(deviceType) && !string.IsNullOrEmpty(deviceSn) &&
- !string.IsNullOrEmpty(fireware) && blBaudRate && blParity && blStopbits)
- {
- config = new BasicConfig()
- {
- DeviceType = deviceType,
- DeviceSn = deviceSn,
- FireWare = fireware,
- DeviceAddress = devAddress,
- BaudRate = baudrate,
- ParityName = parityName,
- StopbitsName = stopbitsName
- };
- }
- else
- {
- _message = "读取基本参数失败";
- RWLog?.Invoke(_message);
- }
- }
- catch{}
- return config;
- }
- private string GetDeviceType(byte devId)
- {
- string devType = "";
- try
- {
- //D2为模块名称
- ushort[] modelNameRegisters = _modbusMaster.ReadHoldingRegisters(devId, 0xD2, 1);
- //printModbusSRData("模块名称");
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
- ushort modelName = modelNameRegisters[0]; //一个寄存器的内容
- devType = "0x" + modelName.ToString("X4");
- _message = $"获取设备类型: {modelName}({devType}),{srMsg}";
- RWLog?.Invoke(_message);
- }
- catch (Exception ex)
- {
- sentData = _modbusTransport.GetLastSentData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex}";
- _message = $"获取设备类型出错,{srMsg},{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return devType;
- }
- private string GetDeviceSn(byte devId)
- {
- string deviceSn = "";
- try
- {
- //E5~E7读取SN
- ushort[] snRegisters = _modbusMaster.ReadHoldingRegisters(devId, 0xE5, 3); // 读取 3 个寄存器
- // 解析 BCD 码
- deviceSn = Tools.SNBcdToString(snRegisters);
- //Console.WriteLine("设备序列号: " + deviceSn);
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
- _message = $"获取设备SN: {deviceSn},{srMsg}";
- RWLog?.Invoke(_message);
- }
- catch (Exception ex)
- {
- _message = $"获取设备SN出错,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return deviceSn;
- }
- //获取固件版本
- private string GetFireware(byte devId)
- {
- string fireware = "";
- try
- {
- //D4~D5固件版本号
- ushort[] firewareRegisters = _modbusMaster.ReadHoldingRegisters(devId, 0xD4, 2);
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
- string mcuVer = $"{(firewareRegisters[0] & 0xFF).ToString("D2")}." +
- $"{(firewareRegisters[1] >> 8).ToString("D2")}." +
- $"{(firewareRegisters[1] & 0xFF).ToString("D2")}";
- fireware = mcuVer;
- _message = $"获取固件版本: {mcuVer},{srMsg}";
- RWLog?.Invoke(_message);
- }
- catch(Exception ex)
- {
- _message = $"获取固件版本出错,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return fireware;
- }
- private byte GetDeiveAddress(byte devId)
- {
- byte devAddress = 0;
- try
- {
- //F0模块ID,即站地址
- ushort[] slaveAddressRegisters = _modbusMaster.ReadHoldingRegisters(devId, 0xF0, 1);
- byte slaveAdress = (byte)(slaveAddressRegisters[0] & 0xFF);
- devAddress = slaveAdress;
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
-
- _message = $"获取485地址: {slaveAdress},{srMsg}";
- RWLog?.Invoke(_message);
- }
- catch (Exception ex)
- {
- _message = $"获取485地址出错,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return devAddress;
- }
- //不能一起读
- public bool GetBaudrate(byte devId,out int baudrate,out string parity,out string stopbits)
- {
- bool blResult = false;
- baudrate = -1;
- parity = "";
- stopbits = "";
- try
- {
- ushort[] baudRateTypeRegisters = _modbusMaster.ReadHoldingRegisters(devId, 0xF2, 3);
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
- byte bauddRateType = (byte)(baudRateTypeRegisters[0] & 0xFF);
- byte parityCheckType = (byte)(baudRateTypeRegisters[1] & 0xFF);
- byte stopbitsType = (byte)(baudRateTypeRegisters[2] & 0xFF);
- baudrate = Tools.GetBaudRate(bauddRateType);
- parity = Tools.GetParityCheck(parityCheckType);
- stopbits = Tools.GetStopBits(stopbitsType);
- _message = $"获取波特率:{bauddRateType}({baudrate},校验和:{parityCheckType}({parity}),停止位:{stopbitsType}({stopbits}),{srMsg}";
- RWLog?.Invoke(_message);
- }
- catch(SlaveException ex)
- {
- }
- catch (Exception ex)
- {
- _message = $"获取波特率、校验位、停止位出错,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return blResult;
- }
- public bool GetBaudrate(byte devId, out int baudrate)
- {
- baudrate = -1;
- try
- {
- ushort[] baudRateTypeRegisters = _modbusMaster.ReadHoldingRegisters(devId, 0xF2, 1);
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
- byte bauddRateType = (byte)(baudRateTypeRegisters[0] & 0xFF);
- baudrate = Tools.GetBaudRate(bauddRateType);
- _message = $"获取波特率: {bauddRateType}({baudrate}),{srMsg}";
- RWLog?.Invoke(_message);
- return true;
- }
- catch (SlaveException ex)
- {
- _message = $"获取波特率Modbus错误,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- catch (TimeoutException ex)
- {
- _message = $"获取波特率超时错误,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- catch (Exception ex)
- {
- _message = $"获取波特率出错,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return false;
- }
- public bool GetPartyName(byte devId, out string partyName)
- {
- partyName = "";
- try
- {
- ushort[] parityCheckTypeRegisters = _modbusMaster.ReadHoldingRegisters(devId, 0xF3, 1);
- byte parityCheckType = (byte)(parityCheckTypeRegisters[0] & 0xFF);
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
- partyName = Tools.GetParityCheck(parityCheckType);
- _message = $"获取校验和: {parityCheckType}({partyName}),{srMsg}";
- RWLog?.Invoke(_message);
- return true;
- }
- catch (SlaveException ex)
- {
- _message = $"获取校验和Modbus错误,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- catch (TimeoutException ex)
- {
- _message = $"获取校验和超时错误,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- catch (Exception ex)
- {
- _message = $"获取校验和出错,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return false;
- }
- public bool GetStopbitsName(byte devId, out string stopbitsName)
- {
- stopbitsName = "";
- try
- {
- //F4(这一位,MCU程序中并未起作用)
- ushort[] stopbitsTypeRegisters = _modbusMaster.ReadHoldingRegisters(devId, 0xF4, 1);
- byte stopbitsType = (byte)(stopbitsTypeRegisters[0] & 0xFF);
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
- stopbitsName = Tools.GetStopBits(stopbitsType);
- _message = $"获取停止位: {stopbitsType}({stopbitsName}),{srMsg}";
- RWLog?.Invoke(_message);
- return true;
- }
- catch (SlaveException ex)
- {
- _message = $"获取停止位Modbus错误,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- catch (TimeoutException ex)
- {
- _message = $"获取停止位超时错误,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- catch (Exception ex)
- {
- _message = $"获取停止位出错,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return false;
- }
- private bool SetBaudRate(byte devId,int newBaudrate )
- {
- ushort newBaudrateType = Tools.GetBaudRateType(newBaudrate);
- try
- {
- // 发送 Modbus 命令修改地址
- _modbusMaster.WriteSingleRegister(devId, 0xF2, newBaudrateType);
- //await _modbusMaster.WriteSingleRegisterAsync(devId, 0xF2, newBaudrateType);
- //_modbusMaster.WriteSingleRegister(devId, 0xF0, newDeviceAddress);
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
- _message = $"设置波特率: {newBaudrateType}({newBaudrate}),{srMsg}";
- RWLog?.Invoke(_message);
- return true;
- }
- catch (SlaveException ex)
- {
- _message = $"设置波特率: {newBaudrateType}({newBaudrate})Modbus错误,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- catch (TimeoutException ex)
- {
- sentData = _modbusTransport.GetLastSentData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex}";
- _message = $"设置波特率: {newBaudrateType}({newBaudrate})超时错误,{srMsg}";
- RWLog?.Invoke(_message);
- }
- catch (Exception ex)
- {
- _message = $"设置波特率: {newBaudrateType}({newBaudrate})出错,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return false;
- }
- private bool SetDeviveAddress(byte devId, byte newDeviceAddress)
- {
- try
- {
- // 发送 Modbus 命令修改地址
- _modbusMaster.WriteSingleRegister(devId, 0xF0, newDeviceAddress);
- sentData = _modbusTransport.GetLastSentData();
- recvData = _modbusTransport.GetLastReceivedData();
- string sendDataHex = BitConverter.ToString(sentData).Replace("-", " ");
- string recvDataHex = BitConverter.ToString(recvData).Replace("-", " ");
- string srMsg = $"发送: {sendDataHex},接收: {recvDataHex}";
- _message = $"设置地址: {newDeviceAddress},{srMsg}";
- RWLog?.Invoke(_message);
- return true;
- }
- catch (SlaveException ex)
- {
- _message = $"设置地址Modbus错误,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- catch (TimeoutException ex)
- {
- _message = $"设置地址超时错误,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- catch (Exception ex)
- {
- _message = $"设置地址出错,{ex.Message}";
- RWLog?.Invoke(_message);
- }
- return false;
- }
- private bool OpenSerial(string portName, int baudRate)
- {
- CloseSerial();
- try
- {
- //除去波特率外,其它参数默认为不会被修改
- SerialPort serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
- serialPort.ReadTimeout = 100; //读取的超时时间应该短一些
- serialPort.WriteTimeout = 100;
- serialPort.Open();
- _serialPort = serialPort;
- _modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort);
- _modbusTransport = (ModbusSerialTransport)_modbusMaster.Transport;
- //_modbusTransport.Retries = 1;
- //_modbusTransport.WaitToRetryMilliseconds = 1000;
- //_modbusTransport.RetryOnOldResponseThreshold = 500;
- _message = $"串口{portName}连接成功";
- RWLog?.Invoke(_message);
- Logger.Info(_message);
- SerialConnected?.Invoke(true);
- return true;
- }
- catch (Exception ex)
- {
- _message = $"串口{portName}连接失败";
- RWLog?.Invoke(_message);
- SerialConnected?.Invoke(false);
- Logger.Info(_message);
- Logger.Error(ex.Message);
- return false;
- }
- }
- private void CloseSerial()
- {
- try
- {
- if (_serialPort != null)
- {
- if (_serialPort.IsOpen)
- {
- _serialPort.Close();
- _message = $"串口{_portName}已关闭";
- SerialStatusChanged?.Invoke(false); //串口关闭
- RWLog?.Invoke(_message);
- Logger.Info(_message);
- }
- _serialPort.Dispose();
- _serialPort = null;
- }
- _modbusTransport?.Dispose();
- _modbusTransport = null;
- }
- catch (Exception ex)
- {
- _message = $"关闭串口{_portName}失败: {ex.Message}";
- RWLog?.Invoke(_message);
- Logger.Error(_message);
- }
- }
- //------------------------------------------------------------------
- }
- }
|