指南-luat二次开发教程指南-功能开发教程-Modbus

目录

Modbus

简介

Modbus对设备的控制是通过对一系列寄存器的读写完成的,是一种常用的串行通信协议,现在Modbus协议已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。


API说明

Modbus在luat lib没有对应的API封装,主要应用串口函数,对数据按照一定协议进行打包发送。
相应的串口API如下:

API接口 描述
uart.on() 注册串口的数据接收或发生函数
uart.setup() 配置并且打开串口,可设置使用模块的串口ID号,波特率,数据位,奇偶校验位等
uart.write() 向串口写字符串或者整型数据
uart.read() 从串口读取字符串
uart.close() 关闭uart对应接口

详细的API介绍见uart API章节

实现流程

  • 注册使用对应的串口
  • modbus通信协议封装
  • modbus数据接收处理
  • 启动任务循环发送数据

示例

相关实例程序在脚本库的demo\modbus文件夹下,包含modbus协议通信实例。可以根据实际需要选择demo进行测试研究。

Modbus发送消息

一条modbus报文,通常包含从机地址、功能码、数据地址、数据、CRC校验这几个数据结构,一个报文就是一帧数据,指的是一串完整的指令数据,如

从机地址 功能代码 数据地址 数据 CRC校验
8 位 8 位 Nx8 位 Nx8 位 16 位
01 06 00 01 00 17 98 04

通过pack.pack()对检验数据以十六进制格式进行打包,然后与前面数据结构中的数据进行拼接发送:

local function modbus_send(slaveaddr,Instructions,reg,value)
    local data = (string.format("%02x",slaveaddr)..string.format("%02x",Instructions)..string.format("%04x",reg)..string.format("%04x",value)):fromHex()
    local modbus_crc_data= pack.pack('<h', crypto.crc16("MODBUS",data))
    local data_tx = data..modbus_crc_data
    uart.write(uart_id,data_tx)
end

Modbus接收消息

此处代码演示使用串口1作为modbus协议通信接口,所以使用uart.read(uart_id,1)来读取串口1接收到的数据,并将数据转换为十六进制,对接收到的数据用户可以自己定义解析做功能扩展,在每次打印和处理完之后,通过cacheData = ""清空串口接收数据缓存。

local function modbus_read()
    local cacheData = ""
    while true do
        local s = uart.read(uart_id,1)
        if s == "" then
            if not sys.waitUntil("UART_RECEIVE",35000/uart_baud) then
                -- 3.5个字符的时间间隔,只是用在RTU模式下面,因为RTU模式没有开始符和结束符,
                -- 两个数据包之间只能靠时间间隔来区分,Modbus定义在不同的波特率下,间隔时间是不一样的,
                -- 所以就是3.5个字符的时间,波特率高,这个时间间隔就小,波特率低,这个时间间隔相应就大
                -- 4800  = 7.297ms
                -- 9600  = 3.646ms
                -- 19200  = 1.771ms
                -- 38400  = 0.885ms
                --uart接收数据,如果 35000/uart_baud 毫秒没有收到数据,则打印出来所有已收到的数据,清空数据缓冲区,等待下次数据接收
                --注意:
                --因为在整个GSM模块软件系统中,软件定时器的精确性无法保证,例如本demo配置的是100毫秒,在系统繁忙时,实际延时可能远远超过100毫秒,达到200毫秒、300毫秒、400毫秒等
                --设置的延时时间越短,误差越大
                if cacheData:len()>0 then
                    local a,_ = string.toHex(cacheData)
                    log.info("modbus接收数据:",a)
                    --用户逻辑处理代码
                    --
                    cacheData = ""
                end
            end
        else
            cacheData = cacheData..s
        end
    end
end

Modbus循环消息发送测试

注册一个任务sys.taskInit(),每隔5S钟由modbus_send()函数向串口发送数据

sys.taskInit(function ()
    while true do
        sys.wait(5000)
        modbus_send("0x01","0x01","0x0101","0x04")
    end
end)

常见问题

字符数组的CRC校验值怎么转换成16进制数据的的CRC校验值?

答:https://doc.openluat.com/question_detail/225。

相关资料以及购买链接

相关开发板购买链接
Air724UG开发板
Air724 开发板使用说明

来自转载:https://doc.openluat.com/wiki/21?wiki_page_id=2362

上一篇:UART与SIM卡通信电路设计


下一篇:4.3 串口通信