增加Modbus协议,实现了协议解析,部分从机,未实现主机
This commit is contained in:
parent
3a7dd0feb2
commit
f93f352d5b
|
@ -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<ushort>();
|
||||
|
||||
// 直接计算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;
|
||||
}
|
|
@ -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位字 读写 通过应用程序可改变这种类型的数据
|
||||
*
|
||||
*/
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
#include "Slave.h"
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef __Slave_H__
|
||||
#define __Slave_H__
|
||||
|
||||
#include "Sys.h"
|
||||
|
||||
// Modbus从机
|
||||
class Slave
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue