diff --git a/TinyNet/Master.cpp b/Modbus/Master.cpp similarity index 100% rename from TinyNet/Master.cpp rename to Modbus/Master.cpp diff --git a/TinyNet/Master.h b/Modbus/Master.h similarity index 100% rename from TinyNet/Master.h rename to Modbus/Master.h diff --git a/Modbus/Modbus.cpp b/Modbus/Modbus.cpp new file mode 100644 index 00000000..83993ae3 --- /dev/null +++ b/Modbus/Modbus.cpp @@ -0,0 +1,65 @@ +#include "Modbus.h" + +Modbus::Modbus() +{ + Address = 0; + Code = 0; + Error = 0; + Length = 0; + + Crc = 0; + Crc2 = 0; +} + +bool Modbus::Read(MemoryStream& ms) +{ + if(ms.Remain() < 4) return false; + + byte* buf = ms.Current(); + assert_ptr(buf); + uint p = ms.Position(); + + Address = ms.ReadByte(); + Code = ms.ReadByte(); + + if(Code & 0x80) + { + Code &= 0x7F; + Error = 1; + } + + Length = ms.Remain() - 2; + ms.Read(&Data, 0, Length); + + Crc = ms.Read(); + + // 直接计算Crc16 + Crc2 = Sys.Crc16(buf, ms.Position() - p - 2); +} + +void Modbus::Write(MemoryStream& ms) +{ + uint p = ms.Position(); + + ms.Write(Address); + + byte code = Code; + if(Error) code |= 0x80; + ms.Write(code); + + if(Length > 0) ms.Write(Data, 0, Length); + + byte* buf = ms.Current(); + byte len = ms.Position() - p; + // 直接计算Crc16 + Crc = Crc2 = Sys.Crc16(buf - len, len); + + ms.Write(Crc); +} + +void Modbus::SetError(ModbusErrors::Errors error) +{ + Code |= 0x80; + Length = 1; + Data[0] = error; +} diff --git a/Modbus/Modbus.h b/Modbus/Modbus.h new file mode 100644 index 00000000..aa8225cb --- /dev/null +++ b/Modbus/Modbus.h @@ -0,0 +1,75 @@ +#ifndef __Slave_H__ +#define __Slave_H__ + +#include "Sys.h" +#include "Stream.h" + +class ModbusErrors +{ +public: + // 错误代码 + enum Errors + { + // 错误的功能代码 + Code = 1, + + // 错误的数据地址 + Address = 2, + + // 错误的数据值 + Value = 3, + + // 错误的个数 + Count, + + // 处理出错 + Process, + + // 错误的数据长度 + Length, + + // Crc校验错误 + Crc + }; +}; + +// Modbus消息实体 +class Modbus +{ +private: + +public: + byte Address; // 地址 + byte Code; // 功能码 + byte Error; // 是否异常 + + byte Length; // 数据长度 + byte Data[32]; // 数据 + + ushort Crc; // 校验码 + ushort Crc2; // 动态计算得到的校验码 + + Modbus(); + + bool Read(MemoryStream& ms); + void Write(MemoryStream& ms); + + void SetError(ModbusErrors::Errors error); +private: +}; + +#endif + +/* + * GB/T 19582.1-2008 基于Modbus协议的工业自动化网络规范 + * 请求响应:1字节功能码|n字节数据|2字节CRC校验 + * 异常响应:1字节功能码+0x80|1字节异常码 + * + * Modbus数据模型基本表 + * 基本表 对象类型 访问类型 注释 + * 离散量输入 单个位 只读 I/O系统可提供这种类型的数据 + * 线圈 单个位 读写 通过应用程序可改变这种类型的数据 + * 输入寄存器 16位字 只读 I/O系统可提供这种类型的数据 + * 保持寄存器 16位字 读写 通过应用程序可改变这种类型的数据 + * + */ diff --git a/Modbus/Slave.cpp b/Modbus/Slave.cpp new file mode 100644 index 00000000..e68a5c8b --- /dev/null +++ b/Modbus/Slave.cpp @@ -0,0 +1,43 @@ +#include "Slave.h" + +Slave(ITransport* port) +{ + _port = port; + + Address = 0; +} + +Slave::~Slave() +{ + delete _port; + _port = NULL; +} + +void Slave::OnReceive(ITransport* transport, byte* buf, uint len, void* param) +{ + assert_ptr(param); + + Slave* slave = (Slave*)param; + + MemoryStream ms(buf, len); + Modbus entity; + if(!entity.Read(ms)) return; + + slave->Dispatch(entity); +} + +// 分发处理消息。返回值决定是否响应 +bool Slave::Dispatch(Modbus& entity) +{ + // 是否本地地址,或者本地是否0接收所有消息 + if(Address && Address != entity.Address) return false; + + // 检查Crc + if(entity.Crc != enable.Crc2) + { + entity.SetError(ModbusErrors::Crc); + return true; + } + + return true; +} diff --git a/Modbus/Slave.h b/Modbus/Slave.h new file mode 100644 index 00000000..569d7cda --- /dev/null +++ b/Modbus/Slave.h @@ -0,0 +1,25 @@ +#ifndef __Slave_H__ +#define __Slave_H__ + +#include "Sys.h" + +// Modbus从机 +class Slave +{ +private: + ITransport* _port; // 传输口 + +public: + byte Address; // 地址 + + Slave(ITransport* port); + ~Slave(); + +private: + static void OnReceive(ITransport* transport, byte* buf, uint len, void* param); + + // 分发处理消息。返回值决定是否响应 + bool Dispatch(Modbus& entity); +}; + +#endif diff --git a/TinyNet/Slave.cpp b/TinyNet/Slave.cpp deleted file mode 100644 index b82b2e46..00000000 --- a/TinyNet/Slave.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "Slave.h" diff --git a/TinyNet/Slave.h b/TinyNet/Slave.h deleted file mode 100644 index a61030dd..00000000 --- a/TinyNet/Slave.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __Slave_H__ -#define __Slave_H__ - -#include "Sys.h" - -// Modbus从机 -class Slave -{ -private: - -public: -private: -}; - -#endif