当前位置:首页 >> 信息与通信 >>

EB8000宏指令使用说明


第十八章

宏 指 令 (macro)使 用 说 明

此章节将说明宏指令的语法与编写的方式,包含以下几个部分:

宏语言说明 宏语言使用说明 数值运算与数据转换函数 如何利用宏指令直接控制外接装置 与 PLC 的 通 信 (包 括 本 地 地 址 Local Bit、 Local Word) 宏指令操作说明 有关宏指令

的一些限制 编译错误提示 范例程序

3 65

一. 宏语言说明

1. 常 数 与 变 量 a. 常 数 (1) 十 进 制 常 数 (2) 十 六 进 常 数 (3) 单 引 号 内 的 ASCII 常 数 (字 符 常 数 ), 例 如 ’a’ (4) 逻 辑 常 数 : true (非 零 ), false(零 )

b. 变 量 (1) 变 量 命 名 必 须 以 英 文 字 母 为 开 头 , 不 得 超 过 32 个 字 符 的 长 度 (2) 数 据 类 型 char. bool short int float 字符类型 逻辑类型 短整数类型 整数类型 浮点数类型

c. 运 算 符 (1) 赋 值 运 算 赋值运算 : = (2) 算 术 运 算 加 减 乘 除 余 (3) 关 系 运 算 小于 : <
3 66

: + : : * : / : %

小 于 等 于 : <= 大于 : >

大 于 等 于 : >= 等于 不等于 (4) 逻 辑 运 算 逻辑于 逻辑或 逻辑 逻辑非 (5) 位 运 算 (a) 移 位 运 算 左 移 : << 右 移 : >> (b) 逻 辑 位 运 算 位与运算 位或运算 : & : | : and : or : xor : not : == : <>

位异或运算 : ^ 位取反运算 : ~ 注 意 :如 果 想 要 运 算 出 逻 辑 运 算 的 值 请 使 用 位 运 算 的 命 令 .

2. 运 算 符 号 的 优 先 级 表 达 式 中 执 行 多 个 运 算 符 号 的 操 作 时 ,需 按 照 规 定 的 顺 序 作 计 算 ,这 种 运算符号间的计算顺序,叫运算符的优先级。

a. 同 一 种 类 运 算 符 号 的 优 先 级 (按 左 到 右 , 依 次 从 高 到 低 ) 算术运算符号 : ^ ( * , / ) % ( + , - )

移位运算符号 : 依照在表达式中出现的次序从左到右进行处理 关系运算符号 : 依照在表达式中出现的次序从左到右进行处理 逻辑运算符号 : not and
3 67

or

xor

b. 算术运算 位运算 逻辑运算 优先于 位运算 优先于 关系运算 优先于 赋值运算

3. 数 组 只支持静态一维数组,形式为:

数 组 名 [数 组 的 大 小 ], 如 array[10]

数 组 的 下 标 大 小 为 整 数 , 其 可 取 值 区 间 为 0 --- 4294967295, 下 标 的 最 小 值 为 0, 下 标 的 最 大 值 为 (数 组 的 大 小 – 1), 例 如

int array[MAX]

MAX = 100

下 标 最 小 值 : 0, 例 如 array[10] 下 标 最 大 值 : 99 ( 由 (100 – 1)获 得 ) , 例 如 array[99]

4. 表 达 式 a. 运 算 对 象 (1) 常 数 (2) 变 量 (3) 数 组 元 素 (4) 函 数 呼 叫 b. 表 达 式 组 成 表达式由操作数件和运算符号按一定规则组合而成

5. 语 句 a. 宣 告 语 句 (1) type name: 宣 告 type 类 型 的 变 量 例如 (2) int a, 宣 告 变 量 a 为 整 数

type name[constant]: 宣 告 type 类 型 的 一 维 数 组
3 68

例如 赋值语句

int array[10], 宣 告 变 量 a 为 整 数 类 型 的 一 维 数 组

形式为 : 变量 = 表达式 例如 a = 2

b. 逻 辑 判 断 与 分 支 赋 值 语 句 (1) 单 行 形 式 if Condition then [Statements] end if 例如

if a == 2 then b = 1 else b = 2 end if

(2) 区 块 形 式 if Condition then [Statements] [else [if Condition – n then [Else_If_Statements] …. [else [Else_Statements]] ] ] end if 例如

if a == 2 then
3 69

b = 1 else if a == 3 b = 2 else b = 3 end if

语法说明 Condition 必要,为一条件表达式,条件表达式值为零, 则 视 为 伪 (false), 条 件 表 达 式 值 为 非 零 , 则 视 为 真 (true)。 Statements 在区块形式中是可选择的参数, 单行形式中, 在 且 没 有 else 子 句 时 , 为 必 要 参 数 , 该 语 句 在 Condition 为 真 时 执 行 。 Condition – n 可 选 , 解 释 同 Condition

Else_If_Statements 可 选 ,一 条 或 多 条 语 句 ,在 相 对 应 的 Condition – n 为 true 时 执 行 。 Else_Statements 可 选 , 在 上 述 Condition 和 Condition – n 都 不 为 true 时 执 行 。

c. 循 环 控 制 (1) for–next 语 句 常 用 于 次 数 已 确 定 的 情 况 , 当 为 ’to’时 , 此 时 按 步 长 递 增 , 当 为 ’down’时 , 此 时 按 步 长 (step)递 减 。 for Counter = Start to end [step Step] [Statements] next [Counter]

3 70

for Counter = Start down end [step Step] [Statements] next [Counter] 例如

for a = 0 to 10 step 2 b = a next a 语法说明 Counter 必 要 ,循 环 计 数 器 的 数 值 变 量 ,该 变 量 只 能 是 整 数 或 字符型态的变量。 Start End Step 必 要 , Counter 的 初 值 。 必 要 , Counter 的 终 值 。 可 选 ,Counter 的 步 长 ,只 能 是 数 值 ,如 果 没 有 指 定 , 则 预 设 为 1。 Statements 可 选 , for 和 next 之 间 的 语 句 区 块 , 该 语 句 区 块 将 执 行所指定的次数。

(2) while – wend 语 句 包 含 条 件 控 制 的 循 环 ,条 件 放 置 于 循 环 顶 部 ,当 条 件 的 逻 辑 表 达 式 值 为 TRUE 时 , 执 行 循 环 体 中 的 语 句 区 块 。 while Condition [statements] wend 例如 while a == 2 b = b + 1 GetData(a, “Local HMI”, LB, 5, 1)
3 71

wend 语法说明 Condition 必 要 , 逻 辑 表 达 式 , 其 计 算 结 果 为 true 或 false, Condition 为 true 时 执 行 循 环 体 。 Statements 可 选 , 为 一 语 句 区 块 , 当 Condition 的 值 为 true 时 , 执行语句区块。

(3) break 使 用 在 循 环 和 条 件 选 择 语 句 中 ,执 行 到 此 语 句 时 ,退 出 循 环 或 条 件 语句。

(4) continue 使 用 在 循 环 语 句 中 ,执 行 到 continue 时 ,立 即 中 断 这 一 次 循 环 的 执 行,直接执行下一次循环。

(5) return 函数返回语句

6. 关 键 词 集 在 宏 语 言 中 规 定 ,用 作 特 定 用 途 的 关 键 词 ,不 能 作 为 函 数 名 称 、数 组 名 、 变 量 名 称 等 。 这 些 关 键 词 包 含 +, -, *, /, ^, %, >=, >, <, <=, <>, ==, and, or, xor, not, <<, >>, =, &, |, ^, ~, if, then, else, end if, for, to, down, step, next, while, wend, break, continue, return 等 。

3 72

二. 宏语言使用说明

1. 区 域 变 量 及 全 域 变 量 a. 区 域 变 量 : 仅 在 一 个 函 数 范 围 内 有 效 b. 全 域 变 量 : 从 定 义 或 宣 告 的 地 方 开 始 , 到 宏 程 序 结 束 为 止 皆 有 效 。

在一个函数内当有相同名称的全域变量与区域变量时, 区域变量为准。 以

2. 变 量 赋 于 初 值 及 常 数 种 类 a. 变 量 赋 于 初 值 (1) 在 宣 告 语 句 中 直 接 赋 于 变 量 初 值 , 例 如 int temp = 9 (2) 在 宣 告 或 定 义 后 , 用 赋 值 语 句 赋 于 变 量 初 值 , 例 如 temp = 9 (3) 赋 于 数 组 变 量 初 值 形 式 如 : int g[10] = { 1, 2, 3, , 10 } 初 值 包 含 在 括 号 中 ,各 数 组 分 量 用 逗 号 隔 开 ,从 左 到 右 按 数 组 下 标 从零开始的顺序,赋于初值给各数组分量。

b. 常 数 宏语言支持 (1) 十 进 制 整 数 形 态 常 数 (2) 十 六 进 制 整 数 形 态 常 数 , 以 0x 开 头 (3) 字 符 形 态 常 数 (4) 逻 辑 常 数 , true 代 表 真 , false 代 表 伪

3. 逻 辑 变 量 及 表 达 式 a. 逻 辑 变 量 它 有 真 (true), 伪 (false)两 种 取 值 的 情 况 , 所 有 非 零 的 值 认 为 是 真 (true), 零 值 认 为 是 伪 (false)。 b. 表 达 式 条 件 表 达 式 的 值 为 零 值 即 为 伪 ,代 表 条 件 不 成 立 ;条 件 表 达 式 的 值 为 非零值即为真,代表条件成立。
3 73

4. 宣 告 语 句 a. 宣 告 语 句 在 函 数 外 宣 告 或 定 义 全 域 变 量 b. 宣 告 语 句 在 函 数 内 宣 告 或 定 义 区 域 变 量 ,同 时 区 域 变 量 的 宣 告 语 句 在 函 数 内 的 最 前 面 ,其 间 不 能 有 其 它 的 语 句 ,否 则 编 译 时 会 出 现 错 误 讯 息。

范例:

macro_command main( ) char i 在宣告语句间的非宣告语句,编译将出现错误讯息

i = 9// int g[10]

for g[2] = 0 to 2 g[3] = 4 next g[2] end macro_command 5. 函 数 呼 叫 及 参 数 传 递 方 式 a. 函 数 定 义 函数的定义必须遵照下列的格式

sub Type FunName(Type1 var1, Type2 var2, …, TypeN varN) …….. return ret end sub 其 中 Type1 为 回 传 值 的 变 量 型 态 , FunName 为 函 数 的 名 称 Type1~TypeN 为 传 入 参 数 的 变 量 型 态 , var1~ varN 为 传 入 的 参 数 , ret 为 回 传 值 。

3 74

范例:

sub int func(int i) int h

h = i + 10 ….. return h end sub b. 函 数 呼 叫 被呼叫的函数需在函数被呼叫前定义,否则编译会出现错误讯息。

范例:

macro_command main() int i 编 译 时 将 出 现 函 数 Func 没 有 被 定 义 的 提 示

i = Func(i)//

end macro_command c. 参 数 传 递 方 式 (1) 通 过 区 域 变 量 传 值 的 方 式 传 递 参 数 (2) 通 过 函 数 间 共 享 全 域 变 量 的 方 式 传 递 参 数

6. 主 函 数 宏指令程序有且只能有一个主函数,它是宏指令程序开始执行的入口, 其形式为: macro_command 函 数 名 ()

end macro_command

3 75

三. 数值运算与数据转换函数

(1) 数 值 运 算


SQRT 开根号运算 语法 SQRT(source, result) SQRT 将 source 的 开 根 号 结 果 储 存 在 result 中 , source 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() float source, result SQRT(15, result) GetData(source, "Local HMI", LW, 0, 1)// SQRT(source, result)// result == 3.0 source == 9.0

SetData(result, "Local HMI", LW, 0, 1) end macro_command


SIN 正弦运算 语法 SIN(source, result) SIN 将 source 的 正 弦 运 算 结 果 储 存 在 result 中 , source 为 角 度 值 , 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() float source, result SIN(90, result)// result == 1

GetData(source, "Local HMI", LW, 0, 1) SIN(source, result) // source == 30 => result == 0.5
3 76

SetData(result, "Local HMI", LW, 0, 1) end macro_command



COS 余弦运算 语法 COS(source, result) COS 将 source 的 余 弦 运 算 结 果 储 存 在 result 中 , source 为 角 度 值 , 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() float source, result COS(90, result)// result == 0

GetData(source, "Local HMI", LW, 0, 1) COS(source, result) // source == 60 => result == 0.5 SetData(result, "Local HMI", LW, 0, 1) end macro_command ■ TAN 正切运算 语法 TAN(source, result) TAN 将 source 的 正 切 运 算 结 果 储 存 在 result 中 , source 为 角 度 值 , 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() float source, result TAN(45, result)// result == 1

GetData(source, "Local HMI", LW, 0, 1)

3 77

TAN(source, result) // source == 60 => result == 1.732 SetData(result, "Local HMI", LW, 0, 1) end macro_command ■ COT 余切运算 语法 COT(source, result) COT 将 source 的 余 切 运 算 结 果 储 存 在 result 中 , source 为 角 度 值 , 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() float source, result COT(45, result)// result == 1

GetData(source, "Local HMI", LW, 0, 1) COT(source, result) // source == 60 => result == 0.5774 SetData(result, "Local HMI", LW, 0, 1) end macro_command ■ SEC 正割运算 语法 SEC(source, result) SEC 将 source 的 正 割 运 算 结 果 储 存 在 result 中 , source 为 角 度 值 , 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() float source, result SEC(45, result)// result == 1.414

3 78

GetData(source, "Local HMI", LW, 0, 1) SEC(source, result) // source == 60 => result == 2 SetData(result, "Local HMI", LW, 0, 1) end macro_command ■ CSC 余割运算 语法 SEC(source, result) CSC 将 source 的 余 割 运 算 结 果 储 存 在 result 中 , source 为 角 度 值 , 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() float source, result CSC(45, result)// result == 1.414

GetData(source, "Local HMI", LW, 0, 1) CSC(source, result) // source == 30 => result == 2 SetData(result, "Local HMI", LW, 0, 1) end macro_command



ASIN 正弦函数的反函数运算 语法 ASIN(source, result) ASIN 将 source 的 正 弦 反 函 数 运 算 结 果 储 存 在 result 中 , source 可 以 是 常 数 或 变 量 , result 为 角 度 值 , 必 须 为 变 量 。 范例 macro_command main() float source, result
3 79

ASIN(0.8660, result)//

result == 60

GetData(source, "Local HMI", LW, 0, 1) ASIN(source, result) // source == 0.5 => result == 30 SetData(result, "Local HMI", LW, 0, 1) end macro_command ■ ACOS 余弦函数的反函数运算 语法 ACOS(source, result) ACOS 将 source 的 余 弦 反 函 数 运 算 结 果 储 存 在 result 中 , source 可 以 是 常 数 或 变 量 , result 为 角 度 值 , 必 须 为 变 量 。 范例 macro_command main() float source, result ACOS(0.8660, result)// result == 30

GetData(source, "Local HMI", LW, 0, 1) ACOS(source, result) // source == 0.5 => result == 60 SetData(result, "Local HMI", LW, 0, 1) end macro_command



ATAN 正切函数的反函数运算 语法 ATAN(source, result) ATAN 将 source 的 正 切 反 函 数 运 算 结 果 储 存 在 result 中 , source 可 以 是 常 数 或 变 量 , result 为 角 度 值 , 必 须 为 变 量 。 范例
3 80

macro_command main() float source, result ATAN(1, result)// result == 45

GetData(source, "Local HMI", LW, 0, 1) ATAN(source, result) // source == 1.732 => result == 60 SetData(result, "Local HMI", LW, 0, 1) end macro_command



RAND 产生随机数值 语法 RAND(result) 每 次 呼 叫 RAND(), RAND 将 随 机 产 生 一 个 数 值 , 并 将 此 数 值 储 存 在 result 中 , result 必 须 为 变 量 。 Result 的 范 围 介 于 0~0x7fff。 范例 macro_command main() short random RAND(random) SetData(random, "Local HMI", LW, 120, 1) end macro_command

(2) 数 值 转 换 ■ BIN2BCD 将 十 进 制 的 数 值 转 换 为 BCD 格 式 的 数 值 语法 BIN2BCD(source, result) BIN2BCD 将 source(十 进 制 数 值 )转 换 为 BCD 格 式 的 数 值 , 并 将 结 果 储 存 在 result 中 , source 可 以 是 常 数 或 变 量 , result 必 须 为 变
3 81

量。 范例 macro_command main() short source, result BIN2BCD(1234, result)// result == 0x1234

GetData(source, "Local HMI", LW, 4, 1) BIN2BCD(source, result) // source == 5678 => result == 0x5678 SetData(result, "Local HMI", LW, 6, 1) end macro_command



BCD2BIN 将 BCD 格 式 的 数 值 转 换 为 十 进 制 的 数 值 语法 BCD2BIN(source, result) BCD2BIN 将 source(BCD 格 式 的 数 值 )转 换 为 十 进 制 的 数 值 , 并 将 结 果 储 存 在 result 中 , source 可 以 是 常 数 或 变 量 , result 必 须 为 变量。 范例 macro_command main() short source, result BCD2BIN(0x1234, result)// result == 1234

GetData(source, "Local HMI", LW, 4, 1) BCD2BIN(source, result) // source == 0x5678 => result == 5678 SetData(result, "Local HMI", LW, 6, 1) end macro_command



DEC2ASCII
3 82

将 十 进 制 的 数 值 转 换 为 ASCII 字 符 语法 DEC2ASCII(source, result[start], no) DEC2ASCII 将 source(十 进 制 数 值 )转 换 为 ASCII 字 符 , 并 将 结 果 依 序 储 存 在 result[]中 , no 为 需 转 换 的 字 符 个 数 。 第 一 个 字 符 储 存 在 result[start], 第 二 个 字 符 储 存 在 result[start + 1], 后 一 最 个 字 符 储 存 在 result[start + (no – 1)]。 source, no 可 以 是 常 数 或 变 量 , result 必 须 为 矩 阵 形 态 的 变 量 。 范例 macro_command main() short source char result[4] GetData(source, "Local HMI", LW, 30, 1) DEC2ASCII(source, result[0], 4)// no. of ASCII == 4 // source == 5678 => // result[0] == '5', result[1] == '6', result[2] == '7', result[3] == '8' SetData(result[0], "Local HMI", LW, 40, 4)// end macro_command 因 为 result的 变 量 型 态 为 char (size为 byte), 执 行 上 面 的 范 例 后 , LW的 储 存 内 容 如 下 : 写入 4 个bytes == 2 words

[LW40] == 0x3635 [LW41] == 0x3837 若 将 result的 变 量 型 态 改 为 short (size为 word)

macro_command main() short source short result[4] GetData(source, "Local HMI", LW, 30, 1) DEC2ASCII(source, result[0], 4)//
3 83

no. of ASCII == 4

// //

source == 5678 => result[0] == '5', result[1] == '6', result[2] == '7', result[3] == '8' 写入 4 个words

SetData(result[0], "Local HMI", LW, 40, 4) // end macro_command

执 行 上 面 的 范 例 后 , LW的 储 存 内 容 变 为 :

[LW40] == 0x0035 [LW41] == 0x0036 [LW42] == 0x0037 [LW43] == 0x0038

(==‘5’) (==‘6’) (==‘7’) (==‘8’)

若 将 result的 变 量 型 态 改 为 int (size为 double words)

macro_command main() short source int result[4] GetData(source, "Local HMI", LW, 30, 1) DEC2ASCII(source, result[0], 4)// no. of ASCII == 4 // source == 5678 => // result[0] == '5', result[1] == '6', result[2] == '7', result[3] == '8' SetData(result[0], "Local HMI", LW, 40, 4) // end macro_command 执 行 上 面 的 范 例 后 , LW的 储 存 内 容 变 为 : 写入 4 个 double words

[LW40] == 0x0035 [LW41] == 0x0000 [LW42] == 0x0036 [LW43] == 0x0000 [LW44] == 0x0037 [LW45] == 0x0000 [LW46] == 0x0038

(==‘5’)

(==‘6’)

(==‘7’)

(==‘8’)
3 84

[LW47] == 0x0000



HEX2ASCII 将 16 进 制 的 数 值 转 换 为 ASCII 字 符 语法 HEX2ASCII(source, result[start], no) HEX2ASCII 将 source(16 进 制 数 值 )转 换 为 ASCII 字 符 , 并 将 结 果 依 序 储 存 在 result[]中 , no 为 需 转 换 的 字 符 个 数 。 第 一 个 字 符 储 存 在 result[start], 第 二 个 字 符 储 存 在 result[start + 1], 后 一 最 个 字 符 储 存 在 result[start + (no – 1)]。 source, no 可 以 是 常 数 或 变 量 , result 必 须 为 矩 阵 形 态 的 变 量 。 范例 macro_command main() short source char result[4] GetData(source, "Local HMI", LW, 30, 1) HEX2ASCII(source, result[0], 4)// no. of ASCII == 4 // source == 0x5678 // result[0] == '5', result[1] == '6', result[2] == '7', result[3] == '8' SetData(result[0], "Local HMI", LW, 40, 4)// end macro_command 因 为 result的 变 量 型 态 为 char (size为 byte), 执 行 上 面 的 范 例 后 , LW的 储 存 内 容 如 下 : 写入 4 个bytes == 2 words

[LW40] == 0x3635 [LW41] == 0x3837



ASCII2DEC 将 ASCII 字 符 转 换 为 十 进 制 的 数 值
3 85

语法

ASCII2DEC(source[start], result, no) ASCII2DEC 将 储 存 在 source[]中 的 ASCII 字 符 转 换 为 十 进 制 数 值 , 第 一 个 字 符 储 存 在 source [start], 第 二 个 字 符 储 存 在 source [start + 1],最 后 一 个 字 符 储 存 在 source [start + (no – 1)],no 为 需 转 换 的 字 符 个 数 。 转 换 后 结 果 将 储 存 在 result 中 。 source 必 须 为 矩 阵 形 态 的 变 量 , result 必 须 为 变 量 , no 可 以 是 常 数或变量。

范例 macro_command main() char source[4] short result GetData(source[0], "Local HMI", LW, 80, 4) ASCII2DEC(source[0], result, 4) // source[0] = '5', source[1] = '6', source[2] = '7', source[3] = '8' => // result == 5678 SetData(result, "Local HMI", LW, 90, 1) end macro_command 下 面 范 例 的 执 行 结 果 , result 同 样 等 于 5678

macro_command main() char source[4] short result source[0] = '5' source[1] = '6' source[2] = '7' source[3] = '8' ASCII2DEC(source[0], result, 4) // result == 5678

SetData(result, "Local HMI", LW, 90, 1) end macro_command

3 86



ASCII2HEX 将 ASCII 字 符 转 换 为 16 进 制 的 数 值 语法 ASCII2HEX(source[start], result, no) ASCII2HEX 将 储 存 在 source[]中 的 ASCII 字 符 转 换 为 16 进 制 数 值 , 第 一 个 字 符 储 存 在 source [start], 第 二 个 字 符 储 存 在 source [start + 1],最 后 一 个 字 符 储 存 在 source [start + (no – 1)],no 为 需 转 换 的 字 符 个 数 。 转 换 后 结 果 将 储 存 在 result 中 。 source 必 须 为 矩 阵 形 态 的 变 量 , result 必 须 为 变 量 , no 可 以 是 常 数或变量。 范例 macro_command main() char source[4] short result GetData(source[0], "Local HMI", LW, 80, 4) ASCII2HEX(source[0], result, 4) // source[0] = '5', source[1] = '6', source[2] = '7', source[3] = '8' => // result == 0x5678 SetData(result, "Local HMI", LW, 90, 1) end macro_command

(3) 数 值 操 作 ■ FILL 将变量填入指定的数值 语法 FILL(source[start], sign, no) FILL 将 source[start]到 source[start + (no – 1)]的 变 量 依 序 设 定 为 sign。source 需 为 变 量 , sign 可 以 是 常 数 或 变 量 。no 为 需 设 定 的变量个数, 可以是常数或变量。 范例 macro_command main() char result[4]
3 87

char sign GetData(sign, "Local HMI", LW, 110, 1) FILL(result[0], 0x31, 2) // result[0] == 0x31, result[1] == 0x31 FILL(result[0], sign, 4) // result[0] == result[1] == result[2] == result[3] == sign SetData(result[0], "Local HMI", LW, 115, 4)// end macro_command 在 上 面 的 例 子 中 , result 的变量型态为 char (size 等 于 byte), 假 设 sign 等 于 0x35, 则 此 MACRO 执 行 后 , LW 的 储 存 内 容 如 下 : 写入 4 bytes == 2 words

[LW115] == 0x3535 [LW116] == 0x3535 若 将 result 的变量型态改为 short (size 等 于 word):

macro_command main() short result[4] char sign GetData(sign, "Local HMI", LW, 110, 1)

FILL(result[0], sign, 4) // result[0] == result[1] == result[2] == result[3] == sign SetData(result[0], "Local HMI", LW, 115, 4)// end macro_command 则 MACRO 执 行 后 (假 设 此 时 sign 等 于 0x35), LW 的 储 存 内 容 如下: 写入 4 words

[LW115] == 0x0035 [LW116] == 0x0035
3 88

[LW117] == 0x0035 [LW118] == 0x0035



SWAPB 将 数 值 的 high bye 与 low byte 数 据 对 调 语法 SWAPB(source, result) SWAPB 将 source 的 high byte 与 low byte 数 据 对 调 , 并 将 结 果 储 存 在 result 中 。source 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() short source, result SWAPB(0x5678, result)// result == 0x7856

GetData(source, "Local HMI", LW, 125, 1) SWAPB(source, result) // source == 0x1234 => result == 0x3412 SetData(source, "Local HMI", LW, 125, 1) end macro_command



SWAPW 将 数 值 的 high word 与 low word 数 据 对 调 语法 SWAPW(source, result) SWAPW 将 source 的 high word 与 low word 数 据 对 调 , 并 将 结 果 储 存 在 result 中 。source 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() int source, result GetData(source, "Local HMI", LW, 130, 1) SWAPW(source, result)
3 89

//

source == 0x12345678 => result == 0x56781234

SetData(result, "Local HMI", LW, 130, 1) end macro_command



LOBYTE 读 取 数 值 的 low byte 语法 LOBYTE(source, result) LOBYTE 将 读 取 source 的 low byte 数 据 , 并 将 结 果 储 存 在 result 中 。 source 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() short source, result LOBYTE(0x1234, result)// result == 0x34

GetData(source, "Local HMI", LW, 140, 1) LOBYTE(source, result) // source == 0x1234 => result == 0x34 SetData(result, "Local HMI", LW, 140, 1)

end macro_command



HIBYTE 读 取 数 值 的 high byte 语法 HIBYTE(source, result) HIBYTE 将 读 取 source 的 high byte 数 据 , 并 将 结 果 储 存 在 result 中 。 source 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() short source, result
3 90

HIBYTE(0x1234, result)//

result == 0x12

GetData(source, "Local HMI", LW, 140, 1) HIBYTE(source, result) // source == 0x1234 => result == 0x12 SetData(result, "Local HMI", LW, 140, 1) end macro_command



LOWORD 读 取 数 值 的 low word 语法 LOWORD(source, result) LOWORD 将 读 取 source 的 low word 数 据 , 并 将 结 果 储 存 在 result 中 。 source 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() int source, result LOWORD(0x12345678, result)// result == 0x5678

GetData(source, "Local HMI", LW, 140, 1) LOWORD (source, result) // source == 0x12345678 => result == 0x5678 SetData(result, "Local HMI", LW, 140, 1) end macro_command



HIWORD 读 取 数 值 的 high word 语法 HIWORD(source, result) HIWORD 将 读 取 source 的 high word 数 据 , 并 将 结 果 储 存 在 result 中 。 source 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例
3 91

macro_command main() int source, result HIWORD(0x12345678, result)// result == 0x1234

GetData(source, "Local HMI", LW, 140, 1) HIWORD (source, result) // source == 0x12345678 => result == 0x1234 SetData(result, "Local HMI", LW, 140, 1) end macro_command

(4) 位 操 作 ■ GETBIT 读 取 数 值 指 定 bit 位 置 的 状 态 语法 GETBIT(source, result, bit_pos) GETBIT 将 读 取 source 由 bit_pos 所 指 定 bit 位 置 的 状 态 , 并 将 结 果 储 存 在 result 中 ,result 的 值 为 0 或 1。source, bit_pos 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() int source, result short bit_pos GetData(source, "Local HMI", LW, 180, 1) GetData(bit_pos, "Local HMI", LW, 182, 1)

GETBIT(source, result, bit_pos) // source == 4, bit_pos == 0 => result = 0 // source == 4, bit_pos == 1 => result = 0 // source == 4, bit_pos == 2 => result = 1

SetData(result, "Local HMI", LW, 183, 1) end macro_command

3 92



SETBITON 将 数 值 所 指 定 bit 位 置 的 状 态 设 定 为 1 语法 SETBITON(source, result, bit_pos) SETBITON 会 将 source 由 bit_pos 所 指 定 bit 位 置 的 状 态 设 定 为 1, 并 将 结 果 储 存 在 result 中 。 source, bit_pos 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() int source, result short bit_pos GetData(source, "Local HMI", LW, 180, 1) GetData(bit_pos, "Local HMI", LW, 182, 1) SETBITON(source, result, bit_pos) // source == 4, bit_pos = 1 => result == 6

SetData(result, "Local HMI", LW, 180, 1) end macro_command



SETBITOFF 将 数 值 所 指 定 bit 位 置 的 状 态 设 定 为 0 语法 SETBITOFF(source, result, bit_pos) SETBITOFF 会 将 source 由 bit_pos 所 指 定 bit 位 置 的 状 态 设 定 为 0, 并 将 结 果 储 存 在 result 中 。 source, bit_pos 可 以 是 常 数 或 变 量 , result 必 须 为 变 量 。 范例 macro_command main() int source, result short bit_pos GetData(source, "Local HMI", LW, 180, 1) GetData(bit_pos, "Local HMI", LW, 182, 1)
3 93

SETBITOFF(source, result, bit_pos) // source == 6, bit_pos = 1 => result == 4

SetData(result, "Local HMI", LW, 180, 1) end macro_command



INVBIT 将 数 值 所 指 定 bit 位 置 的 状 态 反 相 语法 INVBIT(source, result, bit_pos) INVBIT 会 将 source 由 bit_pos 所 指 定 bit 位 置 的 状 态 反 相 , 并 将 结 果 储 存 在 result 中 。 source, bit_pos 可 以 是 常 数 或 变 量 , result 必须为变量。 范例 macro_command main() int source, result short bit_pos GetData(source, "Local HMI", LW, 180, 1) GetData(bit_pos, "Local HMI", LW, 182, 1) INVBIT(source, result, bit_pos) // source == 6, bit_pos = 1 => result == 4 // source == 4, bit_pos = 1 => result == 6 SetData(result, "Local HMI", LW, 180, 1) end macro_command

(5) 通 讯 ■ DELAY 延迟设定的时间后, 再继续执行后续的命令 语法 DELAY(time) 使 用 DELAY 函 数 时 , HMI 将 延 迟 time 时 间 后 , 再 继 续 执 行 后 续
3 94

的 MACRO 命 令 , time 单 位 为 ms, 可 以 是 常 数 或 变 量 。

范例

macro_command main() char s[100] int a = 5000// s[0] = 'a' s[1] = 'b' s[2] = 'c' s[2] = 'd'

ms

DELAY(a) DELAY(4000)//

delay 4000ms

SetData(s[0], "Local HMI", LW, 0, 3) end macro_command



ADDSUM 利 用 加 法 计 算 出 checksum 语法 ADDSUM(source[start], result, no) ADDSUM 将 source[start]到 source[start + (no – 1)]的 变 量 累 加 后 , 将 结 果 存 入 result。 source 与 result 需 为 变 量 , no 为 变 量 的 个数, 可以是常数或变量。

范例 macro_command main() char data[5] short checksum data[0] = 0x1 data[1] = 0x2 data[2] = 0x3 data[3] = 0x4 data[4] = 0x5 ADDSUM(data[0], checksum, 5) end macro_command
3 95



XORSUM 利 用 XOR 计 算 出 checksum 语法 XORSUM(source[start], result, data_count) XORSUM 将 source[start]到 source[start + (data_count – 1)]的 数 值 , 利 用 XOR 的 方 式 计 算 出 checksum, 并 将 结 果 存 入 result。 source 与 result 需 为 变 量 , data_count 为 变 量 的 个 数 , 可 以 是 常 数或变量。

范例 macro_command main() char data[5] short checksum data[0] = 0x1 data[1] = 0x2 data[2] = 0x3 data[3] = 0x4 data[4] = 0x5 XORSUM(data[0], checksum, 5) end macro_command



CRC 计 算 16 bit CRC 语法 CRC(source[start], result, data_count) CRC 将 利 用 source[start]到 source[start + (data_count – 1)]的 数 值 计 算 出 16 bit CRC, 并 将 结 果 存 入 result。 source 与 result 需 为 变 量 , data_count 为 计 算 的 个 数 , 可 以 是 常 数 或 变 量 。

范例 macro_command main() char data[5] short 16bit_CRC

3 96

data[0] = 0x1 data[1] = 0x2 data[2] = 0x3 data[3] = 0x4 data[4] = 0x5 CRC(data[0], 16bit_CRC, 5) end macro_command



OUTPORT 从 通 讯 端 口 (COM 串 口 或 ethernet)输 出 数 据 语法 OUTPORT(command[start], device_name, cmd_count) device_name 为 装 置 名 称 , OUTPORT 将 利 用 device_name 所 定 义 的 通 讯 端 口 , 将 command[start]到 command[start + (cmd_count – 1)]的 数 值 依 序 送 出 , command 需 为 变 量 , cmd_count 需 为 常 数 。 device_name 必 须 是 属 于 Free Protocol 类 型 的 装 置 , 参 考 下 图 。

3 97

范例 假 使 ”MODBUS RTU Device”已 定 义 在 device table 中 , 且 使 用 COM 1 作 为 通 讯 端 口 , 下 面 范 例 说 明 如 何 利 用 OUTPORT 函 数 , 设 定 MODBUS RTU 装 置 的 状 态 。

// Write Single Coil (ON) macro_command main() char command[32], response[32] short address, checksum short i, return_value FILL(command[0], 0, 32)// FILL(response[0], 0, 32) command[0] = 0x1// command[1] = 0x5// init

station no write signle coil

address = 0 HIBYTE(address, command[2]) LOBYTE(address, command[3]) command[4] = 0xff// command[5] = 0 force 0x_1 on

CRC(command[0], checksum, 6) LOBYTE(checksum, command[6]) HIBYTE(checksum, command[7]) // send command OUTPORT(command[0], "MODBUS RTU Device", 8) // read response INPORT(response[0], "MODBUS RTU Device", 8, return_value) // return_value == 0 -> error SetData(return_value, "Local HMI", LW, 0, 1) SetData(response[0], "Local HMI", LW, 10, 8)// end macro_command

send response to LW



INPORT
3 98

从 通 讯 端 口 (COM 串 口 或 ethernet)读 取 数 据 语法 INPORT(response[start], device_name, read_count, return_value) device_name 为 装 置 名 称 , INPORT 将 从 device_name 所 定 义 的 通 讯 端 口 中 读 取 数 据 , 并 将 结 果 存 到 response[]。 INPORT 要 求 的 数 据 读 取 量 与 source 的 变 量 型 态 与 read_count 两者有关, 举例来说

char response[10] INPORT(response[0], “device”, 10, return_value) 此 时 因 为 response 为 char 型 态 的 变 量 , char 的 长 度 为 1 byte, 所 以 INPORT()将 读 取 10 * 1= 10 个 byte 的 数 据 。

若 response 宣 告 为 short 型 态 的 变 量 , 如 下 :

short response[10] INPORT(response[0], “device”, 10, return_value) 因 为 short 的 长 度 为 2 bytes, 此 时 INPORT()将 读 取 10 * 2= 30 个 byte 的 数 据 。

device_name 必 须 是 属 于 Free Protocol 类 型 的 装 置 。 执 行 完 成 INPORT() 函 数 后 , 实 际 读 取 的 数 据 量 纪 录 在 return_value 中 , 单 位 为 byte。

[函 数 执 行 失 败 ] 若 return_value 等 于 0, 表 示 HMI 在 等 待 timeout 时 间 后 , 仍 无 法 读 取 到 read_count 所 定 义 数 目 的 数 据 。

INPORT()函 数 所 使 用 的 timeout 时 间 需 在 装 置 列 表 (devicelist) 中定义, 参考下图。
3 99

范例 假 使 ”MODBUS RTU Device”已 定 义 在 device table 中 , 且 使 用 COM 1 作 为 通 讯 端 口 , 下 面 范 例 说 明 如 何 利 用 OUTPORT 函 数 , 读 取 MODBUS RTU 装 置 的 状 态 。 // Read Holding Registers macro_command main() char command[32], response[32] short address, checksum short read_no, return_value, read_data[2], i FILL(command[0], 0, 32)// FILL(response[0], 0, 32) command[0] = 0x1// command[1] = 0x3// init

station no read holding registers

address = 0 HIBYTE(address, command[2]) LOBYTE(address, command[3]) read_no = 2// read 4x_1, 4x_2 HIBYTE(read_no, command[4]) LOBYTE(read_no, command[5]) CRC(command[0], checksum, 6) LOBYTE(checksum, command[6])
4 00

HIBYTE(checksum, command[7]) // send command OUTPORT(command[0], "MODBUS RTU Device", 8) // read response INPORT(response[0], "MODBUS RTU Device", 9, return_value) // return_value == 0 -> error SetData(return_value, "Local HMI", LW, 0, 1) SetData(response[0], "Local HMI", LW, 10, 9)//

send response to LW

if return_value > 0 then read_data[0] = response[4] + (response[3] << 8)// read_data[1] = response[6] + (response[5] << 8)// SetData(read_data[0], "Local HMI", LW, 100, 2) end if end macro_command

4x_1 4x_2

4 01

四. 如何利用宏指令直接控制外接装置

当 HMI 不 支 持 用 户 所 使 用 的 装 置 时 , 用 户 仍 可 以 利 用 宏 指 令 的 OUTPORT 与 INPORT 命 令 直 接 控 制 这 些 装 置 。 下 面 的 范 例 说 明 用 户 如 何 透 过 宏 指 令 , 读 写 使 用 MODBUS RTU 协 议 的 外 接 装 置 。 首 先 用 户 需 先 在 装 置 列 表 (device list) 中 建 立 一 个 型 态 为 ”Free Protocol” 的 装 置 , 此 装 置 使 用 COM 1, 通 讯 参 数 为 19200, E, 8, 1 。 此 装 置 被 命 名 为 ”MODBUS RTU Device”, 请 参 考 下 图 。

装 置 也 可 以 是 使 用 ethernet 接 口 , 例 如 使 用 MODBUS TCP/IP 协 议 的 装 置 , 此 时 只 需 将 通 讯 接 口 设 定 为 ”Ethernet”, 并 设 定 好 IP 与 通 讯 端 口 (port no.) 即可, 请参考下图。

4 02

假 设 目 前 需 读 取 此 外 接 装 置 4x_1, 4x_2 地 址 中 的 数 据 , 首 先 需 先 利 用 OUTPORT 函 数 对 此 装 置 发 出 读 取 要 求 , OUTPORT 函 数 的 语 法 如 下 :

OUTPORT(command[start], device_name, cmd_count) 因 此 装 置 使 用 MODBUS RTU 协 议 , 此 时 需 参 照 MODBUS RTU 协 议 的 内 容 , 决 定 command []内 容 。 我 们 使 用 MODBUS RTU 协 议 中 的 ”Reading Holding Registers (0x03)”命 令 , 来 读 取 4x_1, 4x_2 地 址 中 的 数 据 , 下 图 为 协 议 的 部 分 内 容 (未 写 出 站 号 (第 0 个 byte)与 最 后 的 两 个 byte(CRC))。

依 照 协 议 的 要 求 , command 的 内 容 如 下 , 共 计 8 bytes:

command[0] : 站号 command[1] : 命令 command[2] : 地址高位(high byte) command[3] : 地址低位(low byte) command[4] : 读取数目高位(high byte)

(BYTE 0) (BYTE 1) (BYTE 2) (BYTE 3) (BYTE 4)
4 03

command[5] : 读取数目低位(low byte)

(BYTE 5)

command[6] : 16-bit CRC高位(high byte) (BYTE 6) command[7] : 16-bit CRC低位(low byte) (BYTE 7)

因此宏指令的实际内容设计如下

char command[32] short address, checksum 先将command[0]~command[31]设为0

FILL(command[0], 0, 32)//

command[0] = 0x1// command[1] = 0x3//

station no read holding registers

address = 0//

读取4x_1开始连续两个words, 4x_1的起始地址为0

HIBYTE(address, command[2]) LOBYTE(address, command[3]) 读取 4x_1, 4x_2共计2 words

read_no = 2//

HIBYTE(read_no, command[4]) LOBYTE(read_no, command[5]) 计算16-bit CRC

CRC(command[0], checksum, 6)//

LOBYTE(checksum, command[6]) HIBYTE(checksum, command[7]) 最后使用OUPORT函数将命令送出

OUTPORT(command[0], "MODBUS RTU Device", 8)//

send command

4 04

在送出读取命令后, 可以利用INPORT函数读取外接装置的回复。 依照协议的内容, 回复 的内容如下, 共计9个byte。

command[0] : 站号 command[1] : 命令 command[2] : 读取数据的byte个数 command[3] : 4x_1高位 command[4] : 4x_1低位 command[5] : 4x_2高位 command[6] : 4x_2低位

(BYTE 0) (BYTE 1) (BYTE 2) (BYTE 3) (BYTE 4) (BYTE 5) (BYTE 6)

command[7] : 16-bit CRC高位(high byte) (BYTE 7) command[8] : 16-bit CRC低位(low byte) (BYTE 8)

因此INPORT函数的内容设定如下

INPORT(response[0], "MODBUS RTU Device", 9, return_value)//

read response

其中return_value用来纪录INPORT的实际读取值byte数, 若等于0, 表示读取失败。依照 协议的内容, response[1]需等于0x3, 表示装置的回复正确。 若回复正确, 在计算获得4x_1 与4x_2的数据后, 将结果设置到LW100与LW101, 即可显示读取的数据。

if (return_value >0 and response[1] == 0x3) then read_data[0] = response[4] + (response[3] << 8)// read_data[1] = response[6] + (response[5] << 8)// 4x_1 4x_2

SetData(read_data[0], "Local HMI", LW, 100, 2) end if 完整的程序如下:

// Read Holding Registers macro_command main()
4 05

char command[32], response[32] short address, checksum short read_no, return_value, read_data[2], i FILL(command[0], 0, 32)// FILL(response[0], 0, 32) command[0] = 0x1// command[1] = 0x3// init

station no read holding registers

address = 0 HIBYTE(address, command[2]) LOBYTE(address, command[3]) read_no = 2// read 4x_1, 4x_2 HIBYTE(read_no, command[4]) LOBYTE(read_no, command[5]) CRC(command[0], checksum, 6) LOBYTE(checksum, command[6]) HIBYTE(checksum, command[7]) OUTPORT(command[0], "MODBUS RTU Device", 8)// send command INPORT(response[0], "MODBUS RTU Device", 9, return_value)// read response SetData(return_value, "Local HMI", LW, 0, 1)// return_value == 0 -> error SetData(response[0], "Local HMI", LW, 10, 9)// send response to LW if (return_value > 0 and response[1] == 0x3) then read_data[0] = response[4] + (response[3] << 8)// read_data[1] = response[6] + (response[5] << 8)// SetData(read_data[0], "Local HMI", LW, 100, 2) end if end macro_command

4x_1 4x_2

下 面 范 例 则 用 来 说 明 如 何 将 0x_1 的 装 态 设 定 为 ON 或 OFF, 下 图 为 协 议 的 部 分 内 容 ( 未 写 出 站 号 ( 第 0 个 byte) 与 最 后 的 两 个 byte(CRC)), 此 时 是 使 用 ”Write Single Coil(0x5)”命 令 格 式 :

4 06

首 先 需 先 利 用 OUTPORT 函 数 对 此 装 置 发 出 设 定 要 求 , 依 照 协 议 的 要 求 , command[]的 内 容 设 定 如 下 。

char command[32] FILL(command[0], 0, 32)// command[0] = 0x1// command[1] = 0x5// init

station no write signle coil

address = 0// 设定地址0的第0个bit, 也就是0x_1 HIBYTE(address, command[2]) LOBYTE(address, command[3]) command[4] = 0xff// command[5] = 0 force 0x_1 on

CRC(command[0], checksum, 6) LOBYTE(checksum, command[6]) HIBYTE(checksum, command[7]) OUTPORT(command[0], "MODBUS RTU Device", 8)// send command

在 送 出 命 令 后 , 可 以 使 用 INPORT 读 取 设 定 结 果 , 依 照 协 议 的 内 容 , 共 需 读 取 8 个 byte。

4 07

INPORT(response[0], "MODBUS RTU Device", 8, return_value)// 完整的程序如下

read response

// Write Single Coil (ON) macro_command main() char command[32], response[32] short address, checksum short i, return_value FILL(command[0], 0, 32)// FILL(response[0], 0, 32) command[0] = 0x1// command[1] = 0x5// init

station no write single coil

address = 0 HIBYTE(address, command[2]) LOBYTE(address, command[3]) command[4] = 0xff// command[5] = 0 force 0x_1 on

CRC(command[0], checksum, 6) LOBYTE(checksum, command[6]) HIBYTE(checksum, command[7]) OUTPORT(command[0], "MODBUS RTU Device", 8)// send command INPORT(response[0], "MODBUS RTU Device", 8, return_value)// read response SetData(return_value, "Local HMI", LW, 0, 1)// return_value == 0 -> error SetData(response[0], "Local HMI", LW, 10, 8)// send response to LW end macro_command

4 08

五 . 与 PLC 的 通 信 (包 括 与 本 地 地 址 Local Bit(LB),Local Word(LW)间 的 通

讯)

功 能 : 使 用 通 讯 函 数 实 现 与 PLC 的 沟 通 在 宏 指 令 程 序 中 , 可 以 使 用 通 讯 函 数 GetData(…)从 HMI 连 接 的 PLC 中 取 得 资 料 ; 也 可 以 使 用 通 讯 函 数 SetData(…)把 资 料 送 到 HMI 连 接 的 PLC 中 , 也 就 是 把 处 理 PLC 信 息 的 繁 杂 工 作 交 给 了 GetData(…)与 SetData(…)等 操 作 函数。

1. GetData(

各 种 支 持 的 数 据 类 型 DestData, char* char* int int szPLCName, szDeviceType, nAddress, nDataCount)

说明 从 PLC 中 读 取 资 料 参数说明: DestData szPLCName szDeviceType nAddress nDataCount 返回值 没有 用来储存所撷取数据的地址 PLC 名 称 PLC 地 址 类 型 和 编 码 方 式 PLC 地 址 数据项数

szPLCName 设 定 要 操 作 的 PLC 对 象 , 使 用 包 含 前 后 双 引 号 (“)的 字 符 串 来 标 示 PLC 名 称 , 这 些 名 称 应 该 已 经 定 义 在 系 统 参 数 的 设 备 清 单 中 , 例 如 ”FATEK FB Series”, 参 考 下 图 。 若 使 用 未 定 义 在 设 备 清 单 中 的 名 称 , 编 译 时 将 产 生 错 误。
4 09

strDeviceType 的 格 式 为 AAA_BBB AAA 表 示 PLC 地 址 类 型 , 例 如 LB 或 LW 等 。 BBB 表 示 选 择 资 料 格 式 为 BIN 或 BCD。

举 例 来 说 , 如 果 strDeviceType 等 于 LB_BIN, 表 示 使 用 BIN 格 式 , 对 PLC 的 LB 地 址 进 行 操 作 。 若 选 择 使 用 BIN 格 式 , strDeviceType 可 以 省 略 ”_BIN”, 如 LW_BIN 与 例 LW 同 义 , 都 是 选 择 使 用 BIN 格 式 , 对 LW 地 址 进 行 操 作 。

nAddress 的 格 式 为 N#AAAAA N 表 示 PLC 的 站 号 , 围 从 0 到 255。 果 使 用 系 统 参 数 中 的 默 认 站 号 , 范 如 ’N#’ 可 省 略 ; AAAAA 则 为 PLC 的 地 址 。

举 例 来 说 ,strAddress 如 果 等 于 2#10,表 示 PLC 站 号 为 2,PLC 的 地 址 为 10。 因 此 对 GetData(a, “DELTA DVP”, M, 2#10, 1)此 句 函 数 的 内 容 可 解
4 10

读 为 : 从 站 号 为 2 的 PLC 中 , 读 取 M10 地 址 的 数 据 。 strAddress 如 果 等 于 123, 省 略 ’N#’, 此 时 将 使 用 系 统 参 数 中 的 默 认 站 号 , 以 下 图 来 说 , 此 时 的 默 认 站 号 为 2。

下面为一些简单的例子:

bool a bool b[30] short c short d[50] int e int f[10] double g[10] 读 取 LB2 地 址 的 状 态 , 并 存 入 变 量 a 中

//

GetData(a, “Local HMI”, LB, 2, 1) 读 取 LB0~LB29 共 30 个 地 址 的 状 态 , 并 存 入 变 量 b[0]~b[29]中

//

GetData(b[0], “Local HMI”, LB, 0, 30) 从 LW2 地 址 读 取 1 个 word 数 据 , 并 存 入 变 量 c 中

//

GetData(c, “Local HMI”, LW, 2, 1) 读 取 LW0~LW49 共 50 个 word 的 资 料 , 并 存 入 d[0]~d[49]中

//

GetData(d[0], “Local HMI”, LW, 0, 50)

411

// //

从 LW6 地 址 读 取 1 个 double word 的 数 据 并 存 入 e 中 注 意 : 此 时 e 的 type 为 int

GetData(e, “Local HMI”, LW, 6, 1) 读 取 LW0~LW19 共 20 个 word 的 资 料 , 并 存 入 f[0]~f[9]中 注 意 : 此 时 f[10]的 type 为 int, 其 中 f[0]存 放 LW0~LW1 的 资 料 , f[1]存 放 LW2~LW3 的 资 料 , 依 此 类 推

// // //

GetData(f[0], “Local HMI”, LW, 0, 10) 从 LW3 地 址 读 取 1 个 float 数 据 , 大 小 为 2 个 word, 并 存 入 变 量 f 中

//

GetData(f, “Local HMI”, LW, 2, 1)

PLC 的 地 址 也 可 以 使 用 变 量 来 表 示 , 参 考 下 面 的 使 用 方 式 :

int i i = 10 GetData(b[0], “Local HMI”, LB, i, 30)

example 1: short a, b a = 123 b=2 // 此时将 b 当成是地址变量, LW2 将被设定为 123 SetData(a, "Local HMI", LW, b, 1)

example 2: short a a = 123 // 此时将 b 当成是地址变量, 但因为 b 未宣告, 因此编译时将产生错误 SetData(a, "Local HMI", LW, b, 1) example 3: short a, b a=1
4 12

b=2 // 此时将 b 当成是地址变量 SetData(a, "PLC", Q, b, 1) example 4: short a, b a=1 b=2 // 此时将 b 当成是地址变量, 编译时将产生错误, 因 b 未宣告 SetData(a, "PLC", Q, b, 1) 因为某些装置型态需要使用 a~f 指示 bit 位置, 所以 MACRO 使用上有些规则必须遵守。 此时先假设有一个装置类型 Q, 他的地址型态为 AAAB, AAA 指示地址, B 为 bit offset(16 进制), 也就是 123b 表示地址为 123 的第 11 个 bit

范例: short a, b a=1 b=2 SetData(a, "Local HMI", Q, 0b, 1)// 此时 0b 表示地址 0 的第 11 个 bit

即使是地址 0 的第 11 个 bit, 也不能就写为 b, 一定要写成 0b, 单独一个 a~f 字母的变量 一定会被当成是变量。

4 13

2. SetData(

各 种 支 持 的 数 据 类 型 DestData, char* char* int int szPLCName, szDeviceType, nAddress, nDataCount)

说明 送 出 资 料 到 PLC 中 , 可 通 过 对 话 窗 填 表 的 形 式 输 入 。 参数说明: DestData szPLCName szDeviceType nAddress nDataCount 返回值 没有 欲送出数据的地址 PLC 名 称 PLC 地 址 类 型 和 编 码 方 式 PLC 地 址 数据项数

说 明 请 参 考 GetData(…)

范例 :

int i bool a = True bool b[30] short c = False short d[50] int e = 5 int f[10]

for i = 0 to 29 b[i] = true
4 14

next i

for i = 0 to 49 d[i] = i * 2 next i

for i = 0 to 9 f[i] = i * 3 next i 设 定 LB2 地 址 的 状 态

//

SetData(a, “Local HMI”, LB, 2, 1) 设 定 LB0~ LB29 地 址 的 状 态

//

SetData(b[0], “Local HMI”, LB, 0, 30) 设 定 LW2 地 址 中 的 数 据

//

SetData(c, “Local HMI”, LW, 2, 1) 设 定 LW0~LW49 地 址 中 的 数 据

//

SetData(d[0], “Local HMI”, LW, 0, 50) 设 定 LW6~LW7 地 址 中 的 数 据 注 意 : e 的 type 为 int

// //

SetData(e, “Local HMI”, LW, 6, 1) 设 定 LW0~LW19 地 址 中 的 数 据

//

SetData(f[0], “Local HMI”, LW, 0, 10)

4 15

. 宏指令操作说明

1. 宏 指 令 程 序 的 编 写 包 含 下 列 步 骤 步骤一 在 EasyBuilder 8000 中 开 启 ”宏 指 令 ”

步骤二 在 ”宏 指 令 ”对 话 窗 中 进 行 宏 指 令 的 新 增 、 删 除 、 编 辑 、 复 制 。

步骤三 编辑宏指令程序,需先确定宏程序的名称,编号,然后进行编译,并排 除编译错误。

4 16

2. 在 宏 指 令 程 序 中 增 加 通 讯 函 数 的 方 法 a. 输 入 在 宏 指 令 程 序 要 增 加 通 讯 函 数 的 地 方 , 入 关 键 词 ”insert”或 者 把 光 标 输 置 于 要 增 加 通 讯 函 数 的 地 方 , 然 后 按 下 [函 数 ]按 钮 , 此 时 皆 会 出 现 如 下图所示的对话窗。

4 17

此 时 正 确 设 置 各 项 参 数 后 按 下 [确 定 ]按 钮 , 即 可 完 成 增 加 一 个 通 讯 函 数。

b. 修 改 将光标置于要修改的通讯函数上对其进行修改即可。

4 18

3. 宏 指 令 的 触 发 条 件 在 ”位 状 态 设 置 ”、 ”位 状 态 切 换 ”、 ”功 能 键 ”与 ”PLC 控 制 ”组 件 中 皆 可 以 使 用 宏 指 令 , 下 文 说 明 如 何 利 用 ”PLC 控 制 ”组 件 使 用 宏 指 令 。

第一步 在 ”PLC 控 制 组 件 属 性 对 话 窗 ”中 选 择 控 制 类 型 为 执 行 宏 指 令 。

第二步 在 ”PLC 控 制 ”组 件 属 性 对 话 窗 中 选 择 控 制 类 型 为 ”执 行 宏 指 令 ”,并 在 [宏 指 令 名 称 ]的 选 项 中 选 择 要 执 行 的 宏 指 令 。 最 后 并 确 定 一 个 触 发 位 置 (此 范 例 为 LB1)与 触 发 条 件 。

以 上 图 为 例 ,当 LB1 的 状 态 由 OFF 变 为 ON 时 ,宏 指 令 ”test”将 被 执 行 , 更 详 细 的 内 容 请 参 考 ”PLC 控 制 ”组 件 的 说 明 。

4 19

七. 有关宏指令的一些限制

1. 宏 指 令 程 序 存 储 空 间 的 限 制 一 个 宏 指 令 程 序 中 的 区 域 变 量 储 存 空 间 最 大 为 4k,因 此 各 项 区 域 变 量 最 大的宣告维度如下:

char a[4096] bool b[4096] short c[2048] int d[1024]

float e[1024]

2. 最 多 可 能 执 行 的 宏 指 令 个 数 的 限 制 一 个 eob 檔 中 最 多 可 以 使 用 255 条 宏 指 令 程 序

3. 宏 指 令 可 能 出 现 的 死 机 情 况 宏指令程序中使用数组资料,但储存空间不足时。

4. 宏 指 令 程 序 的 通 讯 速 度 宏指令程序若因通信或执行计算动作占用太多的时间,将降低系统 的运作效率。应尽量避免一个宏指令执行过多的复杂动作。

4 20

八. 编译错误提示

1. 错 误 提 示 格 式

error C# : 错 误 提 示

其 中 #为 编 译 错 误 编 号

例如: error C37 : undeclared identifier : i 当编译没有通过时,可以通过编译错误编号,寻找此项错误的说明

2. 错 误 提 示 (C1) syntax error: ’identifier ’ 出现此项错误提示时,一般都是多了或少了一个不合理的符号。

例如: macro_command main() char i, 程 //这 是 一 个 不 支 持 的 记 号 //错 误 提 示 为 : “syntax error: 程 ” end macro_command (C2) ‘identifier ’ used without having been initialized 宏指令程序只支持静态数组,在定义数组变量时,必须指定数组的 大小。

例如: macro_command main() char i int g[i]// i 是一个变量,不可以用来指定数组的大小

end macro_command
4 21

(C3) redefinition error : ‘identifier ’ 函数、变量名称在其有效区域内必须是唯一的

例如: macro_command main() int g[10], g// ‘g’重 复 使 用

end macro_command (C4) function name error : ‘identifier ’ 关键词、常数等不能作为函数名称

例如: sub int if()// if 为 关 键 词

(C5) parentheses have not come in pairs 左括号、右括号不成对出现

例如: macro_command main )// 缺少左括号

(C6) illegal expression without matching ‘if’ ‘if ’后 没 有 表 达 式 (C7) illegal expression (no ‘then’) without matching ‘if ’ ‘if ’语 句 没 有 配 对 的 ’then’ (C8) illegal expression (no ‘end if ’) 没 有 ’end if ’语 句 (C9) illegal ‘end if ’ without matching ‘if ’ ‘end if ’前 面 没 有 配 对 的 ’if ’

4 22

(C10) illegal ‘else’ if 语 法 结 构 为 : if 条 件 表 达 式 then ……. [else [if 条 件 表 达 式 then ]] ……. end if 不 符 合 这 种 表 达 形 式 的 if 选 择 语 句 都 是 不 合 法 的 , 编 译 时 将 出 现 此 项 错 误 讯息。

(C11) ‘case’ expression not constant ‘case’后 面 应 为 常 数 (C12) ‘select’ statement contains no ‘case’ ‘select’后 面 缺 少 ’case’关 键 词 (C13) illegal expression without matching ‘select case’ ‘select case’后 面 缺 少 表 达 式 (C14) ‘select’ statement contains no ‘end select’ 缺 少 ’end select’关 键 词 (C15) illegal ‘case’ 非 法 的 ’case’语 句 (C16) illegal expression (no 'select') without matching ‘end select’ ‘end select’前 面 没 有 出 现 配 对 的 ’select’

select case 语 法 结 构 为 :

select case 表 达 式
4 23

case 数 值 常 数 break case 数 值 常 数 break case 数 值 常 数 break case else

end select 不 符 合 这 种 表 达 形 式 的 select case 选 择 语 句 都 是 不 合 法 的 , 编 译 时 将 出 现 此项错误讯息。

(C17) illegal expression (no 'for') without matching ‘next’ ‘for ’循 环 不 配 对 , ’next’前 面 应 有 ’for ’关 键 词 。 (C18) illegal variable type (not interger or char) 此处应为整数型态或字符型态变量

(C19) variable type error 此 处 应 为 赋 值 符 号 (可 能 缺 少 符 号 ‘=’) (C20) must be key word ‘to’ or ‘down’ 此 处 应 为 关 键 词 ’to’或 ’down’ (C21) illegal expression (no 'next') 缺 少 ‘next’关 键 词

for 循 环 语 法 结 构 为 :

for 变 量 = 初 值 to 终 值 [step 步 长 ]
4 24

next [变 量 ]

不 符 合 这 种 表 达 形 式 的 for 循 环 语 句 都 是 不 合 法 的 , 译 时 将 出 现 此 项 错 误 编 讯息。

(C22) ‘wend’ statement contains no ‘while’ ‘while’循 环 不 配 对 , ’wend’前 面 应 有 ’while’关 键 词 (C23) illegal expression without matching ‘wend’ 缺 少 ‘wend’关 键 词

while 循 环 语 法 结 构 为 :

while 条 件 表 达 式 ……. wend 不 符 合 这 种 表 达 形 式 的 while 循 环 语 句 都 是 不 合 法 的 , 译 时 将 出 现 此 项 错 编 误错误讯息。

(C24) syntax error : ‘break’ 不 合 法 的 ‘break’语 句 。 break 语 句 只 能 在 for 循 环 、 while 循 环 、 select case 选 择 结 构 中 使 用 , 且 break 单 独 成 一 行 。 (C25) syntax error : ‘continue’ 合 法 的 ‘continue’语 句 。 continue 语 句 只 能 在 for 循 环 、 while 循 环 中 使 用 , 且 continue 单 独 成 一 行 。 (C26) syntax error 表达式不正确

4 25

(C27) syntax error 合法的操作数件。在表达式中出现与运算符号不匹配的操作数件时,编译 时将出现此项错误讯息。

例如: macro_command main( ) int a, b

for a = 0 to 2 b = 4 + 程 next a end macro_command (C28) must be ‘macro_command’ 此 处 应 为 ’macro_command’ (C29) must be key word ‘Sub’ 此 处 应 为 ’sub’

函数的定义形式为:

sub 数 据 类 型 函 数 名 (…) ……….. end sub 例如: sub int pow(int exp) ……. end sub 不符合这种形式的函数定义,编译时将出现此项错误讯息。

4 26

(C30) number of parameters is incorrect 参数个数不对

(C31) parameter type is incorrect 参数数据类型不匹配。呼叫函数时,参数必须在数据类型、个数上一一对 应才能通过编译,否则编译时将出现此项错误讯息。

(C32) variable is incorrect 变量型态不正确

(C33) function name : undeclared function 没有定义的函数

(C34) expected constant expression 不合法的数组下标表达形式

(C35) invalid array declaration 不合法的数组宣告

(C36) array index error 不合法的数组下标

(C37) undeclared identifier : i ‘identifier ’ 使用没有定义或宣告的变量。只能使用已经定义或宣告的变量和函数,否 则编译时将出现此项错误讯息。

(C38) PLC encoding method is not supported 通 讯 函 数 GetData( … )、 SetData( … )的 参 数 中 有 包 含 PLC 地 址 类 型 信 息 , 当 PLC 地 址 类 型 不 是 此 种 PLC 支 持 的 地 址 类 型 时 ,编 译 时 将 出 现 此 项 错 误 讯息。

(C39) ‘idenifier ’ must be integer, char or constant
4 27

数 组 [a], a 应 为 整 数 、 字 符 变 量 或 常 数 数组的表达形式为:

宣 告 时 : 数 组 名 [常 数 ] (常 数 描 述 数 组 的 大 小 ) 使 用 时 : 数 组 名 [整 形 , 字 符 形 变 量 或 常 数 ]

不符合这种表达形式,编译时将出现此项错误讯息。

(C40) execution syntax should not exist before variable declaration or constant definition 变量定义或宣告语句的前面不能有执行语句

例如: macro_command main( ) int a, b for a = 0 to 2 b = 4 + a

int h, k // 宣 告 语 句 在 此 处 是 错 误 的 , 在 一 个 函 数 内 宣 告 语 句 的 前 面 不 能 有 // 执 行 语 句 , 例 如 b = 4 + a

next a end macro_command (C41) float variables cannot be contained in shift calculation 移位运算中,操作数不能为浮点数。

(C42) function must return a value 函数应有返回值

(C43) function should not return a value
4 28

函数不应有返回值

(C44) float variables cannot be contained in calculation 运 算 中 不 能 有 float 型 资 料 (C45) PLC address error PLC 地 址 错 误 (C46) array size overflow (max. 4k) 矩 阵 的 大 小 超 过 4k (C47) macro command entry function is not only one 宏指令程序入口只能有一个

(C48) macro command entry function must be only one 宏指令入口函数不唯一。宏指令的入口函数只能有一个,形式为:

macro_command 函 数 名 ( ) ……….. end macro_command (C49) a extended address's station no. must be between 0 and 255 在 宏 指 令 中 , 扩 展 地 址 内 的 站 号 大 小 只 能 从 0 到 255

例如: SetData(bits[0] , “PLC 1”, LB , 300#123, 100) 300#123 中 的 300 表 示 站 号 为 300, 站 号 最 大 值 只 能 设 定 为 255。 (C50) a invalid PLC name 在 宏 指 令 中 , PLC 的 名 称 并 未 定 义 在 系 统 参 数 的 设 备 清 单 中

4 29

例如: SetData(bits[0] , “PLC 1”, LB , 200#123, 100) 此时并未在设 备 清 单 中 发 现 “PLC 1“ (C51) macro command do not control a remote device 宏指令只能控制本机的装置

例如: SetData(bits[0] , “PLC 1”, LB , 300#123, 100) 此 时 “PLC 1“为连接在其它 HMI 上的远程装置 (C51) macro command do not control a remote device 宏指令只能控制本机的装置

例如: SetData(bits[0] , “PLC 1”, LB , 300#123, 100) 此 时 “PLC 1“为连接在其它 HMI 上的远程装置 (C51) macro command do not control a remote device 宏指令只能控制本机的装置

例如: SetData(bits[0] , “PLC 1”, LB , 300#123, 100) 此 时 “PLC 1“为连接在其它 HMI 上的远程装置 (C52) GetData() cannot used a broadcast station no !! GetData 函 式 不 允 许 使 用 广 播 站 号

4 30

例如: GetData(data[0] , “PLC 1”, MX , 300#123, 100) 此时 300 为广播站号 (C53) INPORT() must use a "Free Protocol" device !! INPORT()函 数 只 能 使 用 类 型 为 ”Free Protocol”的 装 置

例如: INPORT(data[0] , “PLC 1”, 10, return_value) 此 时 “PLC 1“的 PLC 类型必须是”Free Protocol”, 请 参 考 ” 如 何 利 用 宏 指 令 直 接 控 制 外 接 装 置 ”此 章 节 。 (C54) OUTPORT() must use a "Free Protocol" device !! INPORT()函 数 只 能 使 用 类 型 为 ”Free Protocol”的 装 置

例如: INPORT(data[0] , “PLC 1”, 10, return_value) 此 时 “PLC 1“的 PLC 类型必须是”Free Protocol”, 请 参 考 ” 如 何 利 用 宏 指 令 直 接 控 制 外 接 装 置 ”此 章 节 。

4 31

九. 宏指令范例程序

1. for 循 环 , 各 种 表 达 式 (算 术 , 移 位 元 , 逻 辑 , 关 系 表 达 式 ) macro_command main() int a[10], b[10], i

b[0]= (400 + 400 << 2) / 401 b[1]= 22 *2 - 30 % 7 b[2]= 111 >> 2 b[3]= 403 > 9 + 3 >= 9 + 3 < 4 + 3 <= 8 + 8 == 8 b[4]= not 8 + 1 and 2 + 1 or 0 + 1 xor 2 b[5]= 405 and 3 and not 0 b[6]= 8 & 4 + 4 & 4 + 8 | 4 + 8 ^ 4 b[7]= 6 – (~4) b[8]= 0x11 b[9]= 409

for i = 0 to 4 step 1 if (a[0] == 400) then GetData(a[0],”Device 1”, 3x, 0,9) GetData(b[0],”Device 1”, 3x, 11,10) end If next i end macro_command 2. while, if, break macro_command main() int b[10], i i = 5 while i == 5 - 20 % 3
4 32

GetData(b[1], ”Device 1”, 3x, 11, 1) if b[1] == 100 then break end if wend end macro_command 3. 全 域 变 量 , 函 数 调 用

char g sub int fun(int j, int k) int y

SetData(j, “Local HMI”, LB, 14, 1) GetData(y, “Local HMI”, LB, 15, 1) g = y

return y end Sub macro_command main() int a, b, i

a = 2 b = 3 i = fun(a, b) SetData(i, “Local HMI”, LB, 16, 1) end macro_command

4 33

4. if 结 构 macro_command main() int k[10], j

for j = 0 to 10 k[j] = j next j

if k[0] == 0 then SetData(k[1], “Device 1”, 3x, 0, 1) end if

if k[0] == 0 then SetData(k[1], “Device 1”, 3x, 0, 1) else SetData(k[2], “Device 1”, 3x, 0, 1) end if

if k[0] == 0 then SetData(k[1], “Device 1”, 3x, 1, 1) else if k[2] == 1 then SetData(k[3], “Device 1”, 3x, 2, 1) end If

if k[0] == 0 then SetData(k[1], “Device 1”, 3x, 3, 1) else if k[2] == 2 then SetData(k[3], “Device 1”, 3x, 4, 1) else SetData(k[4], 3x_BIN, 5, 1) end If end macro_command
4 34

5. while 结 构 macro_command main() char i = 0 int a[13], b[14], c = 4848

b[0] = 13

while b[0] a[i] = 20 + i * 10

if a[i] == 120 then c =200 break end if

i = i + 1 wend

SetData(c, “Device 1”, 3x, 2, 1) end macro_command 6. break、 continue 结 构 macro_command main() char i = 0 int a[13], b[14], c = 4848

b[0] = 13

while b[0] a[i] = 20 + i * 10

4 35

if a[i] == 120 then c =200 i = i + 1 continue end if

i = i + 1

if c == 200 then SetData(c, “Device 1”, 3x, 2, 1) break end if wend end macro_command 7. 数 组 结 构 macro_command main() int a[25], b[25], i

b[0] = 13

for i = 0 to b[0] step 1 a[i] = 20 + i * 10 next i

SetData(a[0], “Device 1”, 3x, 0, 13) end macro_command

4 36


相关文章:
EB8000使用说明书
EB8000使用说明书_计算机软件及应用_IT/计算机_专业资料。目录第一章 WEINVIEW ...强大的宏指令功能,除了常用的四则运算、逻辑判断等功能外,还可以进行 三角函数...
加载宏使用说明
加载宏使用说明_其它技巧_PPT制作技巧_PPT专区。配色如需使用该加载宏,需要对本...宏程序编制说明 31页 1下载券 EB8000宏指令使用说明 72页 1下载券喜欢...
第六节 宏 指 令
EB8000宏指令使用说明 72页 1财富值 数控车床宏指令 19页 2财富值 宏指令的应用 57页 2财富值 威纶触摸屏编程 68页 免费如要投诉违规内容,请到百度文库投诉中...
维纶宏指令
范例操作概述 2. 规划说明 3. 物件列表 1 v1.00 1. 范例操作概述 EB8000宏指令提供函数做为数学运算,使用者利用宏语法可建立指令来运算缓...
EB8000多国语言的使用
EB8000多国语言的使用_IT/计算机_专业资料。EB8000 多国语言的使用 EB8000 同时...EB8000 使用说明 9页 1下载券 EB8000宏指令使用说明 72页 1下载券喜欢...
EB8000触摸屏总结
5、EB8000 用户密码设置方法: (1)放置一个位状态设置元件---写入地址(例如:LB100) --- 属 性定义为:窗口打开时设为 ON---编写宏指令。 此段的作用为...
步科触摸屏使用说明
步科组态使用说明 一、创建一个简单的工程 二、软件说明 的简单介绍, 使用手册...触摸屏使用方法 8页 免费 触摸屏使用说明 6页 免费 威纶触摸屏宏指令使用说....
土木工程学院
EB8000宏指令使用说明 72页 1下载券土​木​工​程​学​院 ...同等学力加 试:①弹性力 学;②结构分 析中的有限 元方法 1.复试科目: ①...
EB8000触摸屏设计
EB8000 设计过程作者自述:刚开始设计先设置触摸屏的参数,按照说明书的来,密码 ...“进入”功能键,位状态元件,LB0 使用宏指令,开关类型窗口设置 ON 4. 工具—...
海泰克触摸屏使用说明
海泰克触摸屏使用说明_电子/电路_工程科技_专业资料。 今日推荐 78...威纶触摸屏宏指令使用说... 84页 1下载券 触摸屏使用说明 6页 免费 海泰克...
更多相关标签:
eb8000宏指令 | 威纶通宏指令使用说明 | 中达优控宏指令说明书 | 总结宏指令的使用方法 | eb8000说明书 | eb8000使用手册 | 威纶通eb8000使用手册 | eb8000使用教程 |