Skip to content

data — 共享数据对象 ​

模块名:data

创建一个「值容器」(内部类型 lpchar),可以装字符串、数字或布尔值,并支持算术、比较、连接等运算符重载,用起来接近普通变量。

它的主要用途是给串口协议子设备当数据落点:com_modbus / com_fx / com_dlt645 的采集通道可以把值直接写进 data 对象,脚本再从对象里读,避免占用 PLC 寄存器。也可以用来在不同代码块之间共享一份可变数据。

函数总览 ​

库级函数 ​

函数作用
data.creat([value])创建一个数据对象,可带初值

对象方法 ​

方法作用
d:set写入新值
d:get_num按数字读出
d:get_bool按布尔读出
d:get_string按原始字节串读出

get_num / get_bool / get_string 在库表里也注册了,data.get_num(d) 与 d:get_num() 等价。set 只能用冒号写法。

支持的运算符 ​

对象重载了这些元方法,可以直接参与表达式:

运算元方法
+ - * / % ^__add __sub __mul __div __mod __pow
取负 -d__unm
连接 ..__concat
长度 #d__len
比较 == < <=__eq __lt __le
tostring(d) / print(d)__tostring

本模块不注册常量。


data.creat ​

lua
data.creat([value]) --> data

创建一个数据对象。

参数

#参数类型必填默认值说明
1valuestring | number | boolean | nil否—初值。string 按字节串存;number 按浮点存;true→1、false→0;nil 或 table 等其它类型 → 0

返回值

类型说明
userdata数据对象。必须用变量接住,否则可能被 GC 回收

示例

lua
local temp  = data.creat(0)          -- 数值容器
local state = data.creat(0)          -- 通信状态容器
local name  = data.creat("LPPLC")    -- 字符串容器

实用例程 ​

lua
modbus_state=data.creat(0)--连接状态标志对象
dianlu=data.creat(0)--电流对象
--zongliangh=data.creat(0)--总量x100对象
--zongliangl=data.creat(0)--总量x1对象
meter=com_modbus.creat(com_modbus.RTU,3,modbus_state)--建立MODBUS子设备,数字是设备地址
--meter:set_32_abcd(com_modbus.)--32位数编码方式
--meter:set_float_abcd(com_modbus.ABCD)
meter:set_time_recv(2000)--接收时间

meter:add_channel(400001,com_modbus.S16,dianlu,com_modbus.READ)--加入采集通道,数字是寄存器D的地址,400001是要采集的MODBUS设备寄存器
--meter:add_channel(400001,com_modbus.S16,zongliangh,com_modbus.READ)--加入采集通道
--meter:add_channel(400001,com_modbus.FLOAT,zongliangh,com_modbus.READ)--加入采集通道
--meter:add_channel(400004,com_modbus.FLOAT,zongliangl,com_modbus.READ)--加入采集通道
--meter:add_channel(400006,com_modbus.FLOAT,liuliang,com_modbus.READ)--加入采集通道
serial=com.setup(1,9600,com.NONE,8,1)--建立串口父设备,前面 1是串口号
serial:add_device(meter)--加入子设备
serial:set_time_lunxun(2000)--设定轮询时间
serial:set_timeout(2000)--接收超时时间
serial:start()--启动串口数据采集

ds1=timer.start(5000,function()
	print("dianlu:",dianlu)--plc.d(100))		
		plc.d(120,dianlu)
	end
)

把上面的地址、主题、引脚替换成你项目里的即可。

d:set ​

lua
d:set(value)

写入新值。

参数

#参数类型必填默认值说明
1valuedata | string | number | boolean | nil是—传另一个 data 对象则拷贝它的内容;其它类型规则同 data.creat

返回值

无返回值。

示例

lua
temp:set(25.6)
name:set("workshop-A")
temp:set(other_data)     -- 从另一个对象拷贝

说明

  • 传 table 或 lightuserdata 时什么也不做(保持原值),不报错。

d:get_num ​

lua
d:get_num() --> number

按数字读出当前值。

参数

无参数。

返回值

类型说明
number值恰好是整数时返回 integer,否则返回浮点数

示例

lua
print(temp:get_num())

d:get_bool ​

lua
d:get_bool() --> boolean

按布尔读出当前值。

参数

无参数。

返回值

类型说明
boolean内部整数值为 0 时返回 false,否则 true

d:get_string ​

lua
d:get_string() --> string

按原始字节串读出当前值。

参数

无参数。

返回值

类型说明
string内部存储的原始字节,可含 \0

说明

  • 用数字初始化的对象再 get_string 得到的是内部二进制表示,不是可读数字。需要可读文本请用 tostring(d)。

data.start —— 本模块没有这个函数 ​

data 是纯值容器,不需要也没有任何"启动"动作:creat 出来的那一刻就能读写。个别流传的 API 清单会把 start 挂在 data 名下——那是误归属,运行时调用只会报错:

lua
local d = data.creat(0)
data.start()   --> 报错:attempt to call field 'start' (a nil value)

参数

  • start —— data 模块的库表里只有 creat / get_bool / get_num / get_string 四个键,对象元表里只有本页「对象方法」列出的那些,没有 start。真正带 start 的是各通信模块(如 mc_server.start、modbus 的 dev:start),和 data 无关。

返回值

以 data.start() 调用一律报错,没有返回值。

示例

lua
-- 正确:data 对象创建即可用,挂到采集通道上就是它的"生效"方式
v = data.creat(0)
dev:add_channel(400001, com_modbus.FLOAT, v, com_modbus.READ)  -- 之后由 com 轮询写入

常见用法 ​

给 Modbus 采集通道当落点

lua
local state = data.creat(0)          -- 通信状态
local temp  = data.creat(0)          -- 温度值

local dev = com_modbus.creat(com_modbus.RTU, 1, state)
dev:add_channel(400001, com_modbus.FLOAT, temp, com_modbus.READ)

local port = com.setup(1, 9600)
port:add_device(dev)
port:set_time_lunxun(1000)
port:start()

timer.start(2000, function()
    print("温度:", temp:get_num(), "状态:", state:get_num())
end)

直接参与运算

lua
local a = data.creat(10)
local b = data.creat(3)
print(a + b)            -- 13
print(a > b)            -- true
print(tostring(a))      -- 10

注意事项 ​

  • 对象必须用变量长期持有,被 GC 回收后采集通道会写到已释放的对象上。
  • 内部只有一份值,没有类型标签:用数字写进去、用 get_string 读出来得到的是二进制,不是文本。读写用同一族方法。
  • 名字里的「共享」指的是多处代码共享同一份值,不是同步原语,本模块不提供锁。事件回调本身是串行执行的,通常也不需要锁;并发模型见 并发模型概述。
  • 需要掉电保存请用 fdb 或 ini;data 仅保存在内存中。

例程 ​

统一模板「场景 / 完整代码 / 要点 / 验证方法 / 注意事项」。

例程 1:给 Modbus 采集当数据落点(不占 D 区) ​

适用:LP3201 / LP3202 / LP3203 / LP3222 / LP3232 / LP3288 / 软PLC模拟器 / 上位机 | 依赖模块:data com_modbus com | 难度:★☆☆

场景:温控表浮点温度要拿来算 PID,不想占用 PLC D 寄存器,直接落进 data 对象。

完整代码(可直接下载运行):

lua
local state = data.creat(0)          -- 通信状态
local temp  = data.creat(0)          -- 温度值

local dev = com_modbus.creat(com_modbus.RTU, 1, state)
dev:add_channel(400001, com_modbus.FLOAT, temp, com_modbus.READ)

local port = com.setup(1, 9600)
port:add_device(dev)
port:set_time_lunxun(1000)
port:start()

timer.start(2000, function()
    print("温度:", temp:get_num(), "状态:", state:get_num())
end)

要点:data 是纯值容器,creat 出来即用,没有 start;可直接作为采集通道的 target。

验证方法:下载重启,日志每 2 秒打印温度值。

注意事项:对象必须用变量长期持有(被 GC 回收后采集通道写到已释放对象);没有 data.start 之类函数,调用会报错。


例程 2:跨代码块共享 + 直接运算 ​

适用:同上 | 依赖模块:data | 难度:★☆☆

场景:多个定时器/回调共享一个计数,并对其直接做数值运算。

完整代码(可直接下载运行):

lua
local count = data.creat(0)
timer.start(1000, function()
    count:set(count:get_num() + 1)
    print("计数:", count:get_num())
end)

要点:data 重载了 + - * / 等运算符,可直接参与表达式;set 用冒号写法。

验证方法:每秒计数 +1。

注意事项:set 只能用冒号;传 table/lightuserdata 时 set 静默忽略不报错。


例程 3:注意事项——get_string 与 get_num 的区别 ​

适用:同上 | 依赖模块:data | 难度:★☆☆

场景:用数字初始化后想打印可读文本,却拿到乱码。

完整代码(可直接下载运行):

lua
local d = data.creat(25.6)
print(d:get_string())   -- 内部二进制,乱码
print(tostring(d))      -- "25.6" 正确可读

local s = data.creat("LPPLC")
print(s:get_string())   -- "LPPLC"

要点:内部只有一份值、没有类型标签;数字初始化再 get_string 得到二进制。

验证方法:tostring(d) 输出 25.6。

注意事项:需要可读文本用 tostring(d) 而非 get_string()。

LPPLC 工业物联网云平台 · 软硬件与云平台全栈自研