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

2021/6/27 0:00:39

本文主要是介绍指南-luat二次开发教程指南-功能开发教程-Modbus,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

  • Modbus
    • 简介
    • API说明
    • 实现流程
    • 示例
      • Modbus发送消息
      • Modbus接收消息
      • Modbus循环消息发送测试
    • 常见问题
      • 字符数组的CRC校验值怎么转换成16进制数据的的CRC校验值?
    • 相关资料以及购买链接

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 位
010600 0100 1798 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



这篇关于指南-luat二次开发教程指南-功能开发教程-Modbus的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程