通过串口进行通信 :
1、将 NMobus 类库导入工程中,添加引用、命名空间。工程属性必须配置 为 .NET 4.0。
2、创建 SerialPort 类的一个实例,配置参数,打开串口,如:
public SerialPort port = new SerialPort(“ COM1” )//创建串口
port.BaudRate = 9600;//配置
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.Open();//打开串口
3、调用相应方法创建 Modbus 主站,如:
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(port); //创建 Rtu 传输模式、通过串口 port 通信的主站 master IModbusSerialMaster master = ModbusSerialMaster.CreateAscii(port); //ASCII传输模式
4、配置参数,如:
master.Transport.ReadTimeout = 1000;//读取串口数据超时为 1000ms master.Transport.WriteTimeout = 1000;//写入串口数据超时
master.Transport.Retries = 3;//重试次数
master.Transport.WaitToRetryMilliSeconds = 250;//重试间隔
5、调用相应方法执行功能,如:
try
{
master.WriteMultipleRegisters(slaveId, startAddress, registers); }
有以下几种功能:
//读线圈,参数:从站地址 (8位 ) 、起始地址 (16位 ) 、数量 (16位 ) ;返回布尔型数 组
bool[] ReadCoils(byte slaveAddress, ushort startAddress, ushort numberOfPoints);
//读输入离散量,参数:从站地址 (8位 ) 、起始地址 (16位 ) 、数量 (16位 ) ;返回布 尔型数组
bool[] ReadInputs(byte slaveAddress, ushort startAddress, ushort numberOfPoints);
//读保持寄存器,参数:从站地址 (8位 ) 、起始地址 (16位 ) 、数量 (16位 ) ;返回 16位整型数组
ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort
numberOfPoints);
//读输入寄存器,参数:从站地址 (8位 ) 、起始地址 (16位 ) 、数量 (16位 ) ;返回 16位整型数组
ushort[] ReadInputRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints);
//写单个线圈,参数:从站地址 (8位 ) ,线圈地址 (16位 ) ,线圈值 (布尔型 ) void WriteSingleCoil(byte slaveAddress, ushort coilAddress, bool value);
//写单个寄存器,参数:从站地址 (8位 ) ,寄存器地址 (16位 ) ,寄存器值 (16位 ) void WriteSingleRegister(byte slaveAddress, ushort registerAddress, ushort value);
//写多个寄存器,参数:从站地址 (8位 ) ,起始地址 (16位 ) ,寄存器值 (16位整型 数组 )
void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] data);
//写多个线圈,参数:从站地址 (8位 ) ,起始地址 (16位 ) ,线圈值 (布尔型数组 ) void WriteMultipleCoils(byte slaveAddress, ushort startAddress, bool[] data);
//读写多个寄存器,参数:从站地址 (8位 ) ,读起始地址 (16位 ) ,数量 (16位 ) ,写 起始地址 (16位 ) ,写入值 (16位整型数组 ) ;返回 16位整型数组
ushort[] ReadWriteMultipleRegisters(byte slaveAddress, ushort startReadAddress, ushort numberOfPointsToRead, ushort startWriteAddress, ushort[] writeData);
6、使用 catch 语句捕捉异常:
如果执行没有出错,则不抛出异常,如果是执行读操作则能得到相应的 返回值。
响应超时会抛出 TimeoutException 类型的异常 ;
接收到从站的异常响应时会抛出 SlaveException 类型的异常, 这一类异常 包含 SlaveExceptionCode 属性,即异常码,通过判断异常码能得知出错的原因。
// create and start the TCP slave
TcpListener slaveTcpListener = new TcpListener(address, port);
slaveTcpListener.Start();
ModbusSlave slave = ModbusTcpSlave.CreateTcp(slaveID, slaveTcpListener);
Thread slaveThread = new Thread(slave.Listen);
slaveThread.Start();
// create the master
TcpClient masterTcpClient = new TcpClient(address.ToString(), port);
ModbusIpMaster master = ModbusIpMaster.CreateTcp(masterTcpClient);
ushort numInputs = 5;
ushort startAddress = 100;
// read five register values
ushort[] inputs = master.ReadInputRegisters(startAddress, numInputs);
for (int i = 0; i < numInputs; i++)
Console.WriteLine("Register {0}={1}", startAddress + i, inputs[i]);
// clean up
masterTcpClient.Close();
slaveTcpListener.Stop();
// output
// Register 100=0
// Register 101=0
// Register 102=0
// Register 103=0
// Register 104=0
Modbus serial ASCII master and slave example.
using (SerialPort masterPort = new SerialPort("COM1"))
using (SerialPort slavePort = new SerialPort("COM2"))
{
// configure serial ports
masterPort.BaudRate = slavePort.BaudRate = 9600;
masterPort.DataBits = slavePort.DataBits = 8;
masterPort.Parity = slavePort.Parity = Parity.None;
masterPort.StopBits = slavePort.StopBits = StopBits.One;
masterPort.Open();
slavePort.Open();
// create modbus slave on seperate thread
byte slaveID = 1;
ModbusSlave slave = ModbusSerialSlave.CreateAscii(slaveID, slavePort);
Thread slaveThread = new Thread(new ThreadStart(slave.Listen));
slaveThread.Start();
// create modbus master
ModbusSerialMaster master = ModbusSerialMaster.CreateAscii(masterPort);
master.Transport.Retries = 5;
ushort startAddress = 100;
ushort numRegisters = 5;
// read five register values
ushort[] registers = master.ReadHoldingRegisters(slaveID, startAddress, numRegisters);
for (int i = 0; i < numRegisters; i++)
Console.WriteLine("Register {0}={1}", startAddress + i, registers[i]);
}
// output
// Register 100=0
// Register 101=0
// Register 102=0
// Register 103=0
// Register 104=0
Write and Read 32 bit value example.
uint largeValue = UInt16.MaxValue + 5;
ushort lowOrderValue = BitConverter.ToUInt16(BitConverter.GetBytes(largeValue), 0);
ushort highOrderValue = BitConverter.ToUInt16(BitConverter.GetBytes(largeValue), 2);
// write large value in two 16 bit chunks
master.WriteMultipleRegisters(slaveID, startAddress, new ushort[] { lowOrderValue, highOrderValue });
// read large value in two 16 bit chunks and perform conversion
ushort[] registers = master.ReadHoldingRegisters(slaveID, startAddress, 2);
uint value = ModbusUtility.GetUInt32(registers[1], registers[0]);
NModbus
http://web.archive.org/web/20090601225835/http://www...
第4页??共6页
2011/07/06??9:49
Logging example.
NModbus uses log4net. Your application can easily be configured to capture the NModbus log
statements, as well as your own. Try adding the following xml to your application's configuration
settings. NModbusConsoleAppender consumes only log statements of level INFO and higher
while NModbusFileAppender consumes all log statements (output to NModbusLog.txt).
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<root>
<level value="DEBUG" />
<appender-ref ref="NModbusFileAppender" />
<appender-ref ref="NModbusConsoleAppender" />
</root>
<appender name="NModbusFileAppender" type="log4net.Appender.FileAppender">
<file value="NModbusLog.txt" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %logger %method - %message%newline" />
</layout>
</appender>
<appender name="NModbusConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %logger %method - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
</filter>
</appender>
</log4net>
To configure log4net based on your application's configuration settings add the following line.
log4net.Config.XmlConfigurator.Configure();
Example log4net appender output for a the modbus serial RTU master write registers example.
// ConsoleAppender
INFO Modbus.IO.ModbusTransport UnicastMessage - TX: 1, 16, 0, 100, 0, 3, 6, 0, 1, 0, 2, 0, 3
INFO Modbus.IO.ModbusTransport UnicastMessage - RX: 1, 16, 0, 100, 0, 3
// FileAppender (NModbusLog.txt)
INFO Modbus.IO.ModbusTransport UnicastMessage - TX: 1, 16, 0, 100, 0, 3, 6, 0, 1, 0, 2, 0, 3
DEBUG Modbus.IO.ModbusRtuTransport Read - Read 4 bytes.
DEBUG Modbus.IO.ModbusRtuTransport ReadResponse - Frame start 1, 16, 0, 100.
DEBUG Modbus.IO.ModbusRtuTransport Read - Read 4 bytes.
DEBUG Modbus.IO.ModbusRtuTransport ReadResponse - Frame end 0, 3, 193, 215.
INFO Modbus.IO.ModbusTransport UnicastMessage - RX: 1, 16, 0, 100, 0, 3
For more information visit the
log4net
project page.
Add your own custom messages.
So your device has custom messages? Not a problem, NModbus exposes interfaces IModbusMessage and
IModbusMessageWithData just for that reason. Simply implement custom request and response messages
and call the appropriate ModbusMaster.ExecuteCustomMessage overload.
Example from a test demonstrationg both ExecuteCustomMessage overloads:
ushort testAddress = 120;
ushort[] testValues = new ushort[] { 10, 20, 30, 40, 50 };
CustomReadHoldingRegistersRequest readRequest = new CustomReadHoldingRegistersRequest(3, SlaveAddress, testAddress, (ushort) testValue
CustomWriteMultipleRegistersRequest writeRequest = new CustomWriteMultipleRegistersRequest(16, SlaveAddress, testAddress, new RegisterCo
ushort[] originalValues = Master.ExecuteCustomMessage<CustomReadHoldingRegistersResponse, ushort>(readRequest);
Master.ExecuteCustomMessage<CustomWriteMultipleRegistersResponse>(writeRequest);
ushort[] newValues = Master.ExecuteCustomMessage<CustomReadHoldingRegistersResponse, ushort>(readRequest);
Assert.AreEqual(testValues, newValues);
writeRequest = new CustomWriteMultipleRegistersRequest(16, SlaveAddress, testAddress, new RegisterCollection(originalValues));
Master.ExecuteCustomMessage<CustomWriteMultipleRegistersResponse>(writeRequest);
Check out these example custom message implementations:
CustomReadHoldingRegistersRequest
CustomReadHoldingRegistersResponse
NModbus
CustomWriteMultipleRegistersRequest
CustomWriteMultipleRegistersResponse
NModbus