dgiot/apps/dgiot_modbus/include/dgiot_modbus.hrl

141 lines
8.4 KiB
Erlang
Raw Normal View History

2021-07-05 17:20:37 +08:00
-define(DGIOT_MODBUS_TCP_DTU, dgiot_modbus_tcp_dtu_ets).
-record(state, {
id,
devaddr = <<>>,
heartcount = 0,
regtype = <<>>,
head = "xxxxxx0eee",
len = 0,
app = <<>>,
product = <<>>,
deviceId = <<>>,
scale = 10,
temperature = 0,
2021-07-19 16:21:40 +08:00
env = <<>>,
2022-02-10 17:38:31 +08:00
dtutype = <<>>,
2022-05-17 21:18:23 +08:00
hb = 60,
maxaddr = 0
2021-07-05 17:20:37 +08:00
}).
2021-06-30 09:57:07 +08:00
-define(READ_DISCRETE_INPUTS, 2).
-define(READ_COILS, 1).
-define(WRITE_SINGLE_COIL, 5).
-define(WRITE_MULTIPLE_COILS, 15).
-define(READ_INPUT_REGISTERS, 4).
-define(READ_HOLDING_REGISTERS, 3).
-define(WRITE_SINGLE_HOLDING_REGISTER, 6).
-define(WRITE_MULTIPLE_HOLDING_REGISTERS, 16).
-define(ILLEGAL_FUNCTION, 1).
-define(ILLEGAL_DATA_ADDRESS, 2).
-define(ILLEGAL_DATA_VALUE, 3).
-define(SLAVE_DEVICE_FAILURE, 4).
-define(ACKNOWLEDGE, 5).
-define(SLAVE_DEVICE_BUSY, 6).
-define(NEGATIVE_ACKNOWLEDGE, 7).
-define(MEMORY_PARITY_ERROR, 8).
-define(GATEWAY_PATH_UNAVAILABLE, 10).
-define(GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND, 11).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2021-08-27 16:58:39 +08:00
-define(FC_READ_COILS, 16#01). %读线圈寄存器
-define(FC_READ_INPUTS, 16#02). %读离散输入寄存器
-define(FC_READ_HREGS, 16#03). %读保持寄存器
-define(FC_READ_IREGS, 16#04). %读输入寄存器
2021-06-30 09:57:07 +08:00
2021-08-27 16:58:39 +08:00
-define(FC_WRITE_COIL, 16#05). %写单个线圈寄存器
-define(FC_WRITE_HREG, 16#06). %写单个保持寄存器
-define(FC_WRITE_COILS, 16#0f). %写多个线圈寄存器
-define(FC_WRITE_HREGS, 16#10). %写多个保持寄存器
2021-06-30 09:57:07 +08:00
%%_____________________________________________
%%表2 ModBus功能码与数据类型对应表 |
%%|代码 |功能 |数据类型 |
%%|01 |读 |位 |
%%|02 |读 |位 |
%%|03 |读 |整型、字符型、状态字、浮点型 |
%%|04 |读 |整型、状态字、浮点型 |
%%|05 |写 |位 |
%%|06 |写 |整型、字符型、状态字、浮点型 |
%%|08 |N/A |重复“回路反馈”信息 |
%%|15 |写 |位 |
%%|16 |写 |整型、字符型、状态字、浮点型 |
%%——————————————————————————————————————————————
2022-08-30 20:21:09 +08:00
-record(rtu_req, {slaveId, funcode, address, registersnumber, dataByteSize, quality, data}).
2021-06-30 09:57:07 +08:00
-record(rtu_pdu, {slaveId, funcode, dataByteSize, data}).
2021-08-27 16:58:39 +08:00
-record(tcp_request, {sock, tid = 1, address = 1, function, start, data}).
2021-06-30 09:57:07 +08:00
-record(tcp_request1, {
id,
tid = 1,
address = 1,
function,
start,
data,
env = #{}
}).
%%_________________________________________________________________________________________________________________________________________________________________
%%表1 ModBus功能码
%%_________________________________________________________________________________________________________________________________________________________________
%%|功能码 | 名称 | 作用
%%|01 |读取线圈状态 |取得一组逻辑线圈的当前状态ON/OFF)
%%|02 |读取输入状态 |取得一组开关输入的当前状态ON/OFF)
%%|03 |读取保持寄存器 | 在一个或多个保持寄存器中取得当前的二进制值
%%|04 |读取输入寄存器 | 在一个或多个输入寄存器中取得当前的二进制值
%%|05 |强置单线圈 |强置一个逻辑线圈的通断状态
%%|06 |预置单寄存器 |把具体二进值装入一个保持寄存器
%%|07 |读取异常状态 |取得8个内部线圈的通断状态这8个线圈的地址由控制器决定用户逻辑可以将这些线圈定义以说明从机状态短报文适宜于迅速读取状态
%%|08 |回送诊断校验 |把诊断校验报文送从机,以对通信处理进行评鉴
%%|09 |编程只用于484 | 使主机模拟编程器作用修改PC从机逻辑
%%|10 |控询只用于484 | 可使主机与一台正在执行长程序任务从机通信探询该从机是否已完成其操作任务仅在含有功能码9的报文发送后本功能码才发送
%%|11 |读取事件计数 |可使主机发出单询问,并随即判定操作是否成功,尤其是该命令或其他应答产生通信错误时
%%|12 |读取通信事件记录 |可是主机检索每台从机的ModBus事务处理通信事件记录。如果某项事务处理完成记录会给出有关错误
%%|13 |编程184/384 484 584 |可使主机模拟编程器功能修改PC从机逻辑
%%|14 |探询184/384 484 584 |可使主机与正在执行任务的从机通信定期控询该从机是否已完成其程序操作仅在含有功能13的报文发送后本功能码才得发送
%%|15 |强置多线圈 |强置一串连续逻辑线圈的通断
%%|16 |预置多寄存器 |把具体的二进制值装入一串连续的保持寄存器
%%|17 |报告从机标识 |可使主机判断编址从机的类型及该从机运行指示灯的状态
%%|18 |884和MICRO 84 |可使主机模拟编程功能修改PC状态逻辑
%%|19 |重置通信链路 |发生非可修改错误后,是从机复位于已知状态,可重置顺序字节
%%|20 |读取通用参数584L |显示扩展存储器文件中的数据信息
%%|21 |写入通用参数584L |把通用参数写入扩展存储文件,或修改之
%%|2264 | |保留作扩展功能备用
%%|6572 |保留以备用户功能所用 |留作用户功能的扩展编码
%%|73119 |非法功能 |
%%|120127| 保留 |留作内部作用
%%|128255| 保留 |用于异常应答
%%__________________________________________________________________________________________________________________________________________________________________
%%modbus完整支持很多功能码但是实际在应用的时候常用的也就那么几个。具体如下
%%
%%0x01: 读线圈寄存器
%%0x02: 读离散输入寄存器
%%0x03: 读保持寄存器
%%0x04: 读输入寄存器
%%0x05: 写单个线圈寄存器
%%0x06: 写单个保持寄存器
%%0x0f: 写多个线圈寄存器
%%0x10: 写多个保持寄存器
%%如上所示一共8种功能码。这其中有涉及到线圈、离散输入、保持、输入四种寄存器。这名字也不知道谁起的让人看了一点不通俗易懂搞得晕晕乎乎。实际上你要是看清他的本质就很简单了。下面分别解释一下
%%
%%线圈寄存器实际上就可以类比为开关量每个bit都对应一个信号的开关状态。所以一个byte就可以同时控制8路的信号。比如控制外部8路io的高低。 线圈寄存器支持读也支持写写在功能码里面又分为写单个线圈寄存器和写多个线圈寄存器。对应上面的功能码也就是0x01 0x05 0x0f
%%
%%离散输入寄存器如果线圈寄存器理解了这个自然也明白了。离散输入寄存器就相当于线圈寄存器的只读模式他也是每个bit表示一个开关量而他的开关量只能读取输入的开关信号是不能够写的。比如我读取外部按键的按下还是松开。所以功能码也简单就一个读的 0x02
%%
%%保持寄存器这个寄存器的单位不再是bit而是两个byte也就是可以存放具体的数据量的并且是可读写的。比如我我设置时间年月日不但可以写也可以读出来现在的时间。写也分为单个写和多个写所以功能码有对应的三个0x03 0x06 0x10
%%
%%输入寄存器只剩下这最后一个了这个和保持寄存器类似但是也是只支持读而不能写。一个寄存器也是占据两个byte的空间。类比我我通过读取输入寄存器获取现在的AD采集值。对应的功能码也就一个 0x04
%%
%%对应的错误返回:
%%在对应功能码基础上加上0x80
%%
%%1、“01”读取线圈状态发送
%%————————————————
%%版权声明本文为CSDN博主「JiaoCL」的原创文章遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。
%%原文链接https://blog.csdn.net/liboxiu/article/details/86473516
2022-02-21 14:16:09 +08:00
-define(MODBUS_RTU, <<"MODBUSRTU">>).
2022-05-17 21:18:23 +08:00
-define(MODBUS_TCP, <<"MODBUSTCP">>).