跳转至

RS485通信

简单介绍下RS485

物联网(IoT)在工业场景中的应用越来越广泛,而RS485是一种常见的通信协议,广泛应用于工业自动化和物联网系统中。RS485是一种串行通信标准,主要用于长距离、多节点通信。适用于工业环境中的传感器、执行器、控制器等设备之间的数据传输,且支持多点通信,可以连接多个设备,实现分布式控制。因为具有较好的抗干扰能力,也很适用于噪声环境下的通信。RS485支持长距离传输,通常可达1200米,适用于工业现场中的远程监控和控制。

RS485是一种半双工通信协议。半双工通信协议允许数据在两个方向上传输,但同一时间只能在一个方向上传输数据。在RS485通信中,当发送数据时,只能发送数据而不能接收数据;当接收数据时,只能接收数据而不能发送数据。

比如:在RS485通信中,通常使用一个引脚(如A或RX)作为发送引脚,另一个引脚(如B或TX)作为接收引脚。当发送数据时,发送引脚输出高电平或低电平,接收引脚不工作;当接收数据时,接收引脚输出高电平或低电平,发送引脚不工作。有的也有单独一根线专门用于控制收发逻辑,输出高低电平,负责管理RS485的通讯,包括发送、接收、处理错误等数据。

优点

  • 抗干扰能力强:RS485采用差分信号传输,抗干扰能力强,适用于工业环境中的噪声干扰。
  • 传输距离远:RS485支持长距离传输,适用于工业现场中的远程监控和控制。
  • 多节点通信:RS485支持多点通信,可以连接多个设备,实现分布式控制。
  • 兼容性好:RS485是一种标准化的通信协议,具有较好的兼容性,可以与其他设备进行通信。
  • 成本较低:RS485模块和电缆的成本相对较低,适用于工业现场中的成本控制。

缺点

  • 信号衰减:随着距离的增加,信号衰减会加剧,影响通信质量。
  • 速率限制:RS485的传输速率相对较低,通常在9600bps到115200bps之间,适用于低速数据传输。
  • 电气特性要求:RS485对电气特性有较高的要求,需要使用特定的电缆和连接器。
  • 布线复杂:RS485需要使用双绞线进行布线,布线复杂度较高。

一、初始化uart

1.1 适配485串口

local uartid = 1        -- 根据实际设备选取不同的uartid
local uart485Pin = 16   -- 用于控制485接收和发送的使能引脚

--初始化 
uart.setup(
    uartid,     -- 串口id
    9600,       -- 波特率
    8,          -- 数据位
    1,          -- 停止位
    uart.NONE,  -- 校验位
    uart.LSB,   -- 大小端,uart.LSB为小端,uart.MSB为大端
    1024,       -- 缓冲区大小 1024
    uart485Pin, -- 485转换的GPIO
    0,          -- 485模式rx方向的gpio的电平,默认0 低电平
    2000,       -- 485模式下tx向rx转换的延迟时间,单位us
    )

二、注册接收数据的回调函数

-- 收取数据会触发回调, 这里的"receive" 是固定值不要修改。
uart.on(uartid, "receive", function(id, len)
    local s = ""
    repeat
        s = uart.read(id, 128)
        if #s > 0 then -- #s 是取字符串的长度
            -- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
            log.info("uart", "receive", id, #s, s)
            log.info("uart", "receive(hex)", id, #s, s:toHex())   -- 如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到,可以用以hex格式打印
        end
    until s == ""
end)

三、发送数据

发送普通字符串

uart.write(uartid, "\r\nRDY\r\n模块型号:" .. hmeta.model())

发送十六进制的数据串

uart.write(uartid, string.char(0x55,0xAA,0x4B,0x03,0x86))

通过zbuff的方式发送数据

local buff = zbuff.create(1024)
buff:copy(0, "aa:bb:cc:dd, zbuff!")
uart.tx(uartid, buff)

发送json格式的数据

local data =
{
    host = "abcdefg.com",
    port = "1883",
    clientID = "c88885",
    username = "user",
    password = "123456",
    ca_self = {ssl=false},
}

local jsondata = json.encode(data)
uart.write(uartid, jsondata)

四、完整例程

-- Luatools需要PROJECT和VERSION这两个信息
PROJECT = "uart"
VERSION = "1.0.0"

log.info("main", PROJECT, VERSION)

-- 引入必要的库文件(lua编写), 内部库不需要require
sys = require("sys")

if wdt then
    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
    wdt.init(9000)--初始化watchdog设置为9s
    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
end

log.info("main", "uart demo run......")

local uartid = 1        -- 根据实际设备选取不同的uartid
local uart485Pin = 16   -- 用于控制485接收和发送的使能引脚

--初始化
uart.setup(uartid, 9600, 8, 1, uart.NONE, uart.LSB, 1024, uart485Pin, 0, 2000)

-- 收取数据会触发回调, 这里的"receive" 是固定值
uart.on(uartid, "receive", function(id, len)
    local s = ""
    repeat
        s = uart.read(id, 128)
        if #s > 0 then -- #s 是取字符串的长度
            -- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
            log.info("uart", "receive", id, #s, s)
            -- log.info("uart", "receive", id, #s, s:toHex()) --如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到
        end
    until s == ""
end)

sys.taskinit(function()
    -- 循环两秒向串口发一次数据
    while true do
        sys.wait(2000)
        uart.write(uartid, "test data.")
    end
end)

-- 用户代码已结束---------------------------------------------
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!