Custom Protocol (Passive): VisualHMI integrates protocols such as DCBUS, XGUS, Modbus (RTU/TCP Master/Slave), Mitsubishi FX2N, Delta DVP, Siemens PPI, etc., but in actual field scenarios, there are alwaysproprietary protocolsthat need to be interfaced with. LUA is used for low-level control of serial ports, enabling the transmission, reception, and parsing of custom frames. This article focuses on the passive mode:Data received triggers a callback, and you only need to parse.
1. API Summary Table
| Function | Description |
|---|---|
uart_setup(ch, baudrate, databits, stopbit, parity) | Configure Serial Port: stopbit 0=1 bit/1=1.5 bits; parity 0=None/1=Odd/2=Even.The secondary serial port must be called to be enabled, and the primary serial port (ch=0) is only configured for data |
on_uart_recv(ch, packet) | passive reception callback, with packet being a byte table with subscripts starting from 1.Packet splitting/consolidation may occurmust buffer and parse the byte table |
uart_send(ch, packet) | itself. 1=hand over to the script for the main UART port (free protocol); 0=restore the original protocol configured in the project |
set_free_protocol(en) | sent by |
. The condition for triggering on_uart_recv on the main UART port (ch=0) is: set the project configuration protocol to 'Custom', or set_free_protocol(1) in the script.When the main UART port is occupied by built-in protocols such as Modbus, on_uart_recv will not be called. The DCBUS/XGUS UART port parameters are fixed: 1 stop bit, no parity.
2. Protocol example: LED light control
Frame structure:
| Direction | Frame header (1B) | Length (1B) | Function code (2B) | Data (nB) | Frame Tail (2B) |
|---|---|---|---|---|---|
| Device → Screen | 0x5A | Number of bytes from function code to frame tail | 0x0001~0xFFFF | Variable | 0xFC 0xFF |
| Screen → Device | 0xA9 | Ditto | Ditto | Variable | 0xFC 0xFF |
Length = Function Code 2B + Data nB + Frame Tail 2B = n+4, Big-endian. Function Code: 0x0001=Switch, 0x0002=Brightness, 0x0003=Change Name.
3. State Machine Parsing (Handling Packet Fragmentation/Coalescing)
recvBuf = {} -- 接收缓冲
STATE_IDLE, STATE_LENGTH, STATE_DATA = 0, 1, 2
state = STATE_IDLE
frameLen = 0
function on_uart_recv(ch, packet)
for i = 1, #packet do
local b = packet[i]
if state == STATE_IDLE then
if b == 0x5A then
state = STATE_LENGTH
recvBuf = {}
end
elseif state == STATE_LENGTH then
frameLen = b -- 第2字节:长度
state = STATE_DATA
recvBuf = {b}
elseif state == STATE_DATA then
table.insert(recvBuf, b)
if #recvBuf >= frameLen then
-- 收满一帧,解析
parse_frame(recvBuf)
state = STATE_IDLE
end
end
end
end
function parse_frame(buf)
local func = (buf[2] <> 8) & 0xFF, func & 0xFF}
for i = 1, #payload do table.insert(pkt, payload[i]) end
table.insert(pkt, 0xFC); table.insert(pkt, 0xFF)
uart_send(0, pkt)
endCallbacks are triggered bysystem task polling, not hardware interrupts-- Avoid performing time-consuming operations (large string concatenation, file reading and writing) in callbacks, as this can slow down the system.
Compiled from Guangzhou Dacai Technology VisualHMI development documentation (hmi-doc.gz-dc.com) LUA tutorial "Custom Protocol - Passive Receiving", copyright reserved by Dacai Technology.
Leave a Reply