FlexLua DTU01 Modbus 函数库
Modbus数据转换
r1 = LIB_MbRtuMasterSendTrans(p1~p4)
函数描述: 根据p1不同的modbus功能码以及p1之后的参数,生成符合modbus协议格式的hex数据流,并以table数组形式返回
| p1 | 字符串类型 |
|---|---|
| p1可为如下八个Modbus功能码之一 "01","02","03","04","05","06","0F","10" |
| p2 | 整数型 |
|---|---|
| 需要通信的从机地址,1~255 |
| p3和p4 | 数据类型不固定 |
|---|---|
| 当p1="01"时,表示读线圈。p3=起始地址(0-0xFFFF),p4=个数(1-256) | |
| 当p1="02"时,表示读离散输入量。p3=起始地址(0-0xFFFF),p4=个数(1-256) | |
| 当p1="03"时,表示读保持寄存器。p3=起始地址(0-0xFFFF),p4=个数(1-100) | |
| 当p1="04"时,表示读输入寄存器。p3=起始地址(0-0xFFFF),p4=个数(1-100) | |
| 当p1="05"时,表示写单个线圈。p3=起始地址(0-0xFFFF),p4=线圈值(0或1) | |
| 当p1="06"时,表示写单个寄存器。p3=起始地址(0-0xFFFF),p4=16位寄存器值 | |
| 当p1="0F"时,表示写多个线圈。p3=起始地址(0-0xFFFF),p4=数组,数组中元素的个数等于要写入的线圈个数,0和1代表线圈值 ,注意:元素个数不能超过256个 | |
| 当p1="10"时,表示写多个寄存器。p3=起始地址(0-0xFFFF),p4=数组,数组中元素的个数等于要写入的寄存器个数,值即是要写入的寄存器的值 ,注意:元素个数不能超过123个 |
| r1 | 数组类型 |
|---|---|
| 返回的数组即为符合modbus协议格式的hex数据流数组 |
应用示例:
--读线圈(设备地址=0x03,起始地址=0x0000,个数=3)
LIB_Uart0Send(LIB_MbRtuMasterSendTrans("01", 0x03, 0x0000, 3))
--读离散输入量(设备地址=0x03,起始地址=0x0000,个数=2)
LIB_Uart0Send(LIB_MbRtuMasterSendTrans("02", 0x03, 0x0000, 2))
--读保持寄存器(设备地址=0x03,起始地址=0x0000,个数=1)
LIB_Uart0Send(LIB_MbRtuMasterSendTrans("03", 0x03, 0x0000, 1))
--读输入寄存器(设备地址=0x03,起始地址=0x0000,个数=5)
LIB_Uart0Send(LIB_MbRtuMasterSendTrans("04", 0x03, 0x0000, 5))
--写单个线圈(设备地址=0x03,起始地址=0x0000,线圈值=0)
LIB_Uart0Send(LIB_MbRtuMasterSendTrans("05", 0x03, 0x0000, 0))
--写单个寄存器(设备地址=0x03,起始地址=0x0000,寄存器值=0x1234)
LIB_Uart0Send(LIB_MbRtuMasterSendTrans("06", 0x03, 0x0000, 0x1234))
--写多个线圈(设备地址=0x03,起始地址=0x0000)
tab = {1,0,1,1}--写入的四个线圈值分别为1,0,1,1
LIB_Uart0Send(LIB_MbRtuMasterSendTrans("0F", 0x03, 0x0000, tab))
--写多个寄存器(设备地址=0x03,起始地址=0x0000)
tab = {0x2222, 0x3333}--写入的两个寄存器值分别为0x2222,0x3333
LIB_Uart0Send(LIB_MbRtuMasterSendTrans("10", 0x03, 0x0000, tab))
r1,r2 = LIB_MbRtuMasterRecvTrans(p1,p2)
函数描述: 根据p1功能码的类型,将从机发来的应答结果hex数据流数组p2解析出结果
| p1 | 字符串类型 |
|---|---|
| p1可为如下八个Modbus功能码之一 "01","02","03","04","05","06","0F","10" |
| p2 | table型 |
|---|---|
| 从机发来的应答数据(需要被解析的数据流数组) |
| r1 | 整数型,表示结果 |
|---|---|
| r1大于0表示应答正确,小于等于零表示有问题。例如-1表示应答报文格式有问题,其他值为Modbus异常 |
| r2 | table型 |
|---|---|
| r2仅在读取类型的功能码时才会有,根据读取的类容不同,返回的table包含的数据意义也不同,比如"01"时包含的是各个线圈的值,"03"时包含的是各个寄存器的值 |
应用示例:
--例如我们通过recv_flag,recv_tab=LIB_Uart0Recv()获取到recv_tab数组中包含的从机发来的应答数据流
--解析从机发来的读线圈应答
if recv_flag == 1 then
result,content=LIB_MbRtuMasterRecvTrans("01",recv_tab)
if result > 0 then --打印content数组中的所有结果
for i, v in ipairs(content) do
print(i, v)
end
else
print("fail,re=%d",result)
end
end
--解析从机发来的读离散输入量应答
if recv_flag == 1 then
result,content=LIB_MbRtuMasterRecvTrans("02",recv_tab)
if result > 0 then --打印content数组中的所有结果
for i, v in ipairs(content) do
print(i, v)
end
else
print("fail,re=%d",result)
end
end
--解析从机发来的读保持寄存器应答
if recv_flag == 1 then
result,content=LIB_MbRtuMasterRecvTrans("03",recv_tab)
if result > 0 then --打印content数组中的所有结果
for i, v in ipairs(content) do
print(i, v)
end
else
print("fail,re=%d",result)
end
end
--解析从机发来的读输入寄存器应答
if recv_flag == 1 then
result,content=LIB_MbRtuMasterRecvTrans("04",recv_tab)
if result > 0 then --打印content数组中的所有结果
for i, v in ipairs(content) do
print(i, v)
end
else
print("fail,re=%d",result)
end
end
--解析从机发来的写单个线圈应答
if recv_flag == 1 then
result=LIB_MbRtuMasterRecvTrans("05",recv_tab)
if result > 0 then
print("write single coil ok")
else
print("fail")
end
end
--解析从机发来的写单个寄存器应答
if recv_flag == 1 then
result=LIB_MbRtuMasterRecvTrans("06",recv_tab)
if result > 0 then
print("write single register ok")
else
print("fail")
end
end
--解析从机发来的写多个线圈应答
if recv_flag == 1 then
result=LIB_MbRtuMasterRecvTrans("0F",recv_tab)
if result > 0 then
print("write multiple coil ok")
else
print("fail")
end
end
--解析从机发来的写多个寄存器应答
if recv_flag == 1 then
result=LIB_MbRtuMasterRecvTrans("10",recv_tab)
if result > 0 then
print("write multiple register ok")
else
print("fail")
end
end
RS485 Modbus数据采集极简函数(Uart1)
LIB_ModbusToJsonConfig(p1)
函数描述: 配置RS485 Modbus转Json功能(固定使用Uart1接口),并设置将要转换出来的Json最大字符串长度限制 注意:调用该函数前需要调用LIB_Uart1Rs485Config()函数
| p1 | 整数型 |
|---|---|
| 设置 Json 最大字符串长度,该值必须小于256 |
应用示例:
--配置RS485 Modbus转Json功能,并设置最终Json字符串最大长度为180字节
--例如mqtt单包传输字符串不能超过180字节,所以这里设置180
LIB_ModbusToJsonConfig(180)
--完整应用示例请参考LIB_ModbusToJsonSendCheck()函数的介绍
LIB_ModbusToJsonAdd(p1,p2,p3,p4)
函数描述: 增加一条需要读取的Modbus数据的寄存器起始地址、该数据的类型、小数个数、以及该数据的Json名称
| p1 | 整数型 |
|---|---|
| 需要读取的某个数据的寄存器起始地址,该值必须小于65536 |
| p2 | 字符串型 |
|---|---|
| "S_AB":带符号16位整数,AB型 | |
| "S_BA":带符号16位整数,BA型 | |
| "U_AB":不带符号16整数,AB型 | |
| "U_BA":不带符号16整数,BA型 | |
| "UL_ABCD":不带符号32位整数,ABCD型 | |
| "UL_CDAB":不带符号32位整数,CDAB型 | |
| "UL_BADC":不带符号32位整数,BADC型 | |
| "UL_DCBA":不带符号32位整数,DCBA型 | |
| "L_ABCD":带符号32位整数,ABCD型 | |
| "L_CDAB":带符号32位整数,CDAB型 | |
| "L_BADC":带符号32位整数,BADC型 | |
| "L_DCBA":带符号32位整数,DCBA型 | |
| "F_ABCD":32位浮点数,ABCD型 | |
| "F_CDAB":32位浮点数,CDAB型 | |
| "F_BADC":32位浮点数,BADC型 | |
| "F_DCBA":32位浮点数,DCBA型 | |
| "D_ABCDEFGH":64位Double,ABCDEFGH"型 | |
| "D_GHEFCDAB":64位Double,GHEFCDAB型 | |
| "D_BADCFEHG":64位Double,BADCFEHG型 | |
| "D_HGFEDCBA":64位Double,HGFEDCBA型 | |
| "BIT":读线圈或读离散输入量时必须填"BIT" |
| p3 | 整数型 |
|---|---|
| 小数个数 ,注意:该值不能超过6 | |
| 情况1:整数时,有些RS485传感器厂家喜欢用整数表示小数(会指明几个小数),这时可将p3设置为相对应的小数个数 | |
| 情况2:浮点数时,p3可用来指示该浮点数需要保留的小数个数 | |
| 情况3:读线圈或读离散量时,p3可为任意值,一般设置成0 |
| p4 | 字符串型 |
|---|---|
| 要读的数据的Json名称。该字符串请尽量短一些减少通信字节数,最长不能超过32字节 |
应用示例:
--寄存器起始地址0x0002,数据类型"UL_ABCD",0位小数,Json名称"Temperature"
LIB_ModbusToJsonAdd(0x0002,"UL_ABCD",0,"Temperature")
--寄存器起始地址0x0004,数据类型"UL_ABCD",2位小数,Json名称"Humidity"
LIB_ModbusToJsonAdd(0x0004,"UL_ABCD",2,"Humidity")
--完整应用示例请参考LIB_ModbusToJsonSendCheck()函数的介绍
LIB_ModbusToJsonSend(p1~p7)
函数描述: 设置RS485通信参数以及Modbus相关参数
| p1 | 字符串类型,波特率选择 |
|---|---|
| "BAUDRATE_1200" | |
| "BAUDRATE_2400" | |
| "BAUDRATE_4800" | |
| "BAUDRATE_9600" | |
| "BAUDRATE_14400" | |
| "BAUDRATE_19200" | |
| "BAUDRATE_28800" | |
| "BAUDRATE_31250" | |
| "BAUDRATE_38400" | |
| "BAUDRATE_56000" | |
| "BAUDRATE_57600" | |
| "BAUDRATE_76800" | |
| "BAUDRATE_115200" | |
| "BAUDRATE_230400" | |
| "BAUDRATE_250000" | |
| "BAUDRATE_460800" | |
| "BAUDRATE_921600" | |
| "BAUDRATE_1000000" |
| p2 | 字符串类型,校验方式选择 |
|---|---|
| "NoneParity" "EvenParity" OddParity" |
| p3 | 字符串类型,停止位选择 |
|---|---|
| "StopBit_1" "StopBit_1_5" "StopBit_2" |
| p4 | 字符串类型 ,Modbus功能码选择 |
|---|---|
| p4可为如下四个Modbus读取类功能码之一 "01","02","03","04" |
| p5 | 整数型,Modbus从机地址 |
|---|---|
| 0~255 |
| p6 | 整数型,Modbus应答最大等待时间(单位:毫秒) |
|---|---|
| 该时间取决于485传感器的响应时间,不同的传感器可能不同,一般设置100ms既能应对大多数场景,特殊情况请查看相应传感器厂家提供的说明书以适当增加该时间值 |
| p7 | 整数型,Modbus包与包之间最小间隔时间(单位:毫秒) |
|---|---|
| 由于每次最多只能读取100个连续的寄存器,当我们要读取的寄存器地址太过分散导致超过100个时,系统会自动分包读取,所以需要考虑该间隔时间。该间隔时间取决于传感器,一般设置100ms,特殊情况甚至需要达到1~2秒,所以请查看相应传感器厂家提供的说明书以适当增加该时间值 |
应用示例:
--从机参数设置(9600,无校验,1位停止位,功能码"03",从机地址0x01,应答最长等待100ms,包与包最短间隔50ms)
LIB_ModbusToJsonSend("BAUDRATE_9600","NoneParity","StopBit_1","03",0x01,100,50)
--完整应用示例请参考LIB_ModbusToJsonSendCheck()函数的介绍
r1,r2,r3 = LIB_ModbusToJsonFinishCheck()
函数描述: 查询modbus通信是否结束,以及结果(成功或失败),和故障信息
| r1 | 整数型,指示通信是否结束 |
|---|---|
| 0: 未结束 1: 结束 |
| r2 | 字符串,Json结果 |
|---|---|
| 注意:通信失败时将返回null,而不是传感器Json数据字符串 | |
| 正常返回形如: {"temp":26.5, "humi":70} |
| r3 | 字符串,Error错误信息 |
|---|---|
| 注意:通信失败时将返回错误信息,正常时仅返回null | |
| 返回 "Modbus read timeout" 表示RS485通信失败,检查下RS485硬件及线路是否正常 | |
| 返回 "Modbus error: xx"表示Modbus数据格式错误、寄存器地址错误、寄存器数量超出范围等 |
应用示例:
--配置Uart1作为485接口,初始默认波特率19200,并且D8作为自动收发切换引脚
LIB_Uart1Rs485Config("BAUDRATE_19200","D8")
while(GC(1) == true)
do
--当某个条件触发时,读取某个温湿度传感器的温度值和湿度值,并print打印输出Json结果字符串
--Json字符串示例: {"temp":26, "humi":70.00}
if something hanppen then
--配置RS485 Modbus转Json功能,并设置Json字符串最大长度为180字节
--例如mqtt单包传输字符串不能超过180字节,所以这里设置180
LIB_ModbusToJsonConfig(180)
--寄存器地址0x0002,类型"UL_ABCD",0位小数,Json名称"Temperature"
LIB_ModbusToJsonAdd(0x0002,"UL_ABCD",0,"Temperature")
--寄存器地址0x0004,类型"UL_ABCD",2位小数,Json名称"Humidity"
LIB_ModbusToJsonAdd(0x0004,"UL_ABCD",2,"Humidity")
--参数设置(9600,无校验,1位停止位,功能码"03",从机地址0x01,应答最长等待1000ms,包与包最短间隔50ms)
--注意1:应答最长等待时间取决于通信数据量以及传感器,请查阅传感器说明书,通信失败时请尝试增加该值
--注意2:包与包最短间隔时间取决于传感器,请查阅传感器说明书,通信失败时请尝试增加该值
--开始Uart1 RS485通信
LIB_ModbusToJsonSend("BAUDRATE_9600","NoneParity","StopBit_1","03",0x01,1000,50)
--等待RS485通信结束
while true do
Finish,Data,Err = LIB_ModbusToJsonFinishCheck()
if Finish == 1 then
print(Data)
print(Err)
break --跳出while循环
end
end
end
end