菜单

自由协议串口函数

下载

适用版本:1.0.27 更新日期:2026-10-09

Lua 可用 uart_send 发送原始字节,并在 on_uart_recv 接收业务数据。自定义协议需要由脚本处理帧头、长度、拆包、粘包和校验;发送字符串 "A5 5A" 得到的是这些字符的编码,不是十六进制字节 A5 5A。

1. 工程串口与 uart_setup

先在工程设置中配置通信协议及波特率、数据位、停止位、校验位,并保持主板参数一致。自由协议示例使用工程的自定义协议模式。

lua 复制代码
uart_setup(channel, baudrate, databits, stopbit, parity)

新版运行库已实现参数设置和独立第二串口。请更新屏端固件或模拟器后使用;工程配置决定上电初始参数。接口要求 5 个整数参数,正常成功返回 0,失败返回 -1;参数类型或数量不对会抛 Lua 错误。

参数 说明
channel 0/1 为共享工程通信口;3 为独立第二串口;配置通道 2 不支持
baudrate 波特率,1200~3000000;实际可用范围由设备决定
databits 7 或 8
stopbit Lua 编码:0=1 位,1=2 位;当前屏端不支持 1.5 位
parity 0=无校验,1=奇校验,2=偶校验

uart_setup(0/1, ...) 修改组态协议与 Lua 共用的工程串口,成功后内置协议也使用新参数。工程设置是初始值,脚本生效的设置是当前运行值,不修改工程文件。相同参数重复设置不会重启通信;应在初始化或确需改参时调用。

uart_setup(3, ...) 打开独立 UART3,不改变工程口参数。Lua 通道 0 是工程通信口(UART1),不是硬件 UART0 日志口。独立第二口随脚本关闭释放;串口下载占用期间禁止脚本发包或改参。

lua 复制代码
function on_init()
    local rc = uart_setup(3, 115200, 8, 0, 0) -- 第二口,115200 8N1
    print("UART3 setup", rc)
end

function send_second_port()
    local rc = uart_send(3, {0xA5, 0x5A, 0x00, 0x09})
    print("UART3 send", rc)
end

2. 发送原始数据

lua 复制代码
uart_send(channel, data)
参数或返回值 说明
channel 0/1 为工程口;3 为独立第二口,2 保留第二口发送别名
data 为字符串 发送字符串的原始字节,可包含零字节
data 为表 下标 1 开始的连续整数表,每项 0~255
数据长度 每次 1~255 字节
返回 0 原始字节已成功写入当前串口发送接口
返回 -1 参数不合法、串口不可用、下载占用串口或发送失败

uart_send(0/1, data) 使用工程口;uart_send(2/3, data) 使用已通过 uart_setup(3, ...) 打开的第二口。配置第二口不能用 uart_setup(2, ...)。发送成功只表示串口接口接受了数据,不表示对端已接收、校验通过或执行命令;需要设备协议本身的应答确认。

发送 ASCII 文本:

lua 复制代码
local rc = uart_send(0, "HELLO\r\n")
if rc ~= 0 then
    print("UART send failed")
end

发送十六进制字节表或等价二进制字符串:

lua 复制代码
local rc = uart_send(0, {0xA5, 0x5A, 0x00, 0x09})
if rc ~= 0 then
    print("UART send failed")
end

local packet = string.char(0xA5, 0x5A, 0x00, 0x09)
uart_send(0, packet)

运行库按原样发送,不自动增加帧头、长度、CRC 或结束符。较长消息须按自己的协议拆分,单次调用不能超过 255 字节。

3. 接收回调

在脚本中定义以下函数,运行库收到业务字节后会调用它:

lua 复制代码
function on_uart_recv(channel, packet, length)
    -- packet 是二进制字符串。
end
参数 说明
channel 0 为工程口,3 为独立第二口;发送别名不改变接收通道号
packet 二进制字符串,保留零字节和 0x80~0xFF 字节
length 本次片段的字节数,与 #packet 一致,最多 512 字节

一次回调可能只是部分帧,也可能含多帧,不能直接把一次回调当成一个完整报文。回调返回值不控制内置协议是否继续解析,也不会把串口接收改成独占模式。内置协议同样可监听原始业务片段,但合法下载控制数据不会交给业务脚本;下载占用期间不能发送应用数据。

所有内置协议及自定义协议均支持原始业务接收回调。在模拟器中,主口选择“工程通信”模式才分发工程业务回调;“手动调试”不会向工程脚本分发主口数据。第二口独立收发,两口应各自保存拼帧缓冲。接收回调应简短,及时处理片段,避免阻塞界面。

查看收到的十六进制字节:

lua 复制代码
function on_uart_recv(channel, packet, length)
    local bytes = {}
    for i = 1, length do
        bytes[i] = string.format("%02X", string.byte(packet, i))
    end
    print("RX", channel, table.concat(bytes, " "))
end

4. 拆包、粘包和变量更新示例

下面定义一个简单的自定义协议:固定 4 字节,前两字节为 A5 5A,后两字节为高字节在前的 16 位数值。它仅用于演示接收拼帧,不是内置协议的报文格式。

主板发送 A5 5A 00 09 时,脚本将 LW1014 更新为 9;该变量可绑定温度控件。

lua 复制代码
local LW = 1
local rx = ""

function on_init()
    set_run_cycle(100)
end

function on_uart_recv(channel, packet, length)
    if channel ~= 0 or length == 0 then
        return
    end

    rx = rx .. packet
    while #rx >= 2 do
        local first, second = string.byte(rx, 1, 2)
        if first ~= 0xA5 or second ~= 0x5A then
            rx = string.sub(rx, 2)
        elseif #rx < 4 then
            break
        else
            local high, low = string.byte(rx, 3, 4)
            local value = high * 256 + low
            rx = string.sub(rx, 5)
            set_uint16(LW, 0x1014, value)
        end
    end
end

function on_update(slave, vtype, addr)
    if vtype == LW and addr == 0x1014 then
        print("received value", get_uint16(LW, addr))
    end
end

解析后用寄存器接口写入变量,绑定该变量的控件使用更新后的值。若实际协议还有长度、命令或 CRC 字段,应在全部字段核对通过后再提交变量。

5. 实际可用入口与常见错误

本节公开入口是 uart_setup、uart_send 和脚本回调 on_uart_recv。当前没有注册 uart_recv 同步读取函数,也没有注册 mb_read_coil_01、mb_read_input_02、mb_read_reg_03、mb_read_input_reg_04、mb_write_coil_05、mb_write_reg_06、mb_write_coil_15 或 mb_write_reg_16 自由 Modbus 函数。

  • 表中的每项是字节,不能传 0x1234;需拆成 0x12, 0x34。
  • 用 string.char 或字节表构造二进制报文,不把十六进制显示文本直接当报文发送。
  • packet 可能含零字节,使用 #packet、string.byte 和 string.sub 处理。
  • 不在接收回调中等待下一片数据或执行长循环;保留未完成片段,等待下次回调。
  • 内置 PLC 协议使用自身收发与轮询,自定义报文示例应配合自定义协议工程。

实际项目应按对端协议填写帧结构和串口参数。

6. 模拟器第二口与 Lua 运行日志

主口使用串口副屏选择的 COM。第二口需要在启动模拟器前设置环境变量 STT_SIM_UART3,指定独立 COM,且不能与主口重复。未配置、COM 被占用或硬件不支持时,uart_setup(3, ...) 返回 -1,不会悄悄借用主口。

例如在 Windows 命令提示符中启动(替换为实际模拟器路径;COM13 仅为示例):

bat 复制代码
set STT_SIM_UART3=COM13
"C:\your-path\TaiSimulator.exe"

Lua print()、脚本加载/执行错误和未被脚本自行处理的回调异常,显示在串口副屏的“运行日志”。筛选选择“运行日志”或“全部日志”,无需连接 COM;日志可复制或导出,不作为串口 TX 发送,也不计入 RX/TX 统计。使用 pcall 捕获的错误,需要脚本自行 print 才会显示。

lua 复制代码
print("Lua debug", get_uint16(1, 0x1014))
local ok, err = pcall(set_uint16, 1, -1, 7)
if not ok then
    print("write failed", err)
end

第二口与工程口的业务回调均在原界面主循环中执行;不要在回调中忙等或阻塞。停止定时脚本见定时器函数;限制本地演示数据自动上传见寄存器操作函数中的 set_notify。

上一个
寄存器操作函数
下一个
定时器函数
最近修改: 2026-10-09Powered by