4.1 数学运算指令
本节将介绍PLC的数学运算指令
学习目标
- 掌握基本数学运算指令
- 理解数据溢出的处理
- 能够进行复杂的数学计算
1. 数学运算概述
1.1 运算指令分类
PLC数学运算指令分类:
┌─────────────────────────────────────────────────────┐
│ 数学运算指令 │
├────────────┬────────────┬────────────┬──────────────┤
│ 基本运算 │ 高级运算 │ 数学函数 │ 类型转换 │
├────────────┼────────────┼────────────┼──────────────┤
│ · ADD加 │ · MOD取模 │ · SIN正弦 │ · INT→REAL │
│ · SUB减 │ · INC递增 │ · COS余弦 │ · REAL→INT │
│ · MUL乘 │ · DEC递减 │ · TAN正切 │ · BCD↔BIN │
│ · DIV除 │ · NEG取反 │ · SQRT平方根│ · 符号转换 │
└────────────┴────────────┴────────────┴──────────────┘1.2 数据类型与运算
| 数据类型 | 位数 | 范围 | 运算指令 |
|---|---|---|---|
| INT | 16位 | -32768~32767 | ADD, SUB |
| DINT | 32位 | ±21亿 | ADD_DI, SUB_DI |
| REAL | 32位 | 浮点数 | ADD_R, SUB_R |
| UINT | 16位 | 0~65535 | 无符号运算 |
2. 加法指令(ADD)
2.1 基本概念
加法指令:将两个数相加,结果存入目标地址。
加法运算:
┌───────┐
│ 加数1 │─────┐
└───────┘ │ ┌───────┐
├───→│ 结果 │
┌───────┐ │ └───────┘
│ 加数2 │─────┘
└───────┘
公式:结果 = 加数1 + 加数22.2 加法指令梯形图
【梯形图】
┌──────────┐
条件 ─────┤ ADD │
│ │
加数1 ────┤IN1 OUT ├───── 结果
加数2 ────┤IN2 │
└──────────┘
【逻辑表达】
结果 := 加数1 + 加数2;
【数据类型】
· 整数加法(16位)
· 双整数加法(32位)
· 实数加法(浮点)2.3 加法指令格式
【梯形图】
条件
───┤├───────[ADD 源1 源2 目标]───
【指令格式】
ADD [S1] [S2] [D]
· S1:加数1
· S2:加数2
· D:结果存储地址
【示例】
ADD 数据1 数据2 结果 // 结果 = 数据1 + 数据2
ADD 100 数据 结果 // 结果 = 100 + 数据
【连续加法(累加)】
ADD 数据 累加器 累加器 // 累加器 = 数据 + 累加器2.4 溢出处理
加法溢出示例:
16位整数加法:
数据1 = 30000
数据2 = 10000
───────────────
结果 = 30000 + 10000 = 40000
但16位有符号整数最大值为32767
结果溢出!得到错误值
【解决方法】
1. 使用32位运算
2. 先判断是否会溢出
3. 使用浮点数运算
【溢出标志】
各品牌PLC都有溢出标志位,可用于检测运算溢出3. 减法指令(SUB)
3.1 减法指令梯形图
【梯形图】
┌──────────┐
条件 ─────┤ SUB │
│ │
被减数 ───┤IN1 OUT ├───── 结果
减数 ─────┤IN2 │
└──────────┘
【逻辑表达】
结果 := 被减数 - 减数;
【数据类型】
· 整数减法(16位)
· 双整数减法(32位)
· 实数减法(浮点)3.2 减法指令格式
【梯形图】
条件
───┤├───────[SUB 源1 源2 目标]───
【指令格式】
SUB [S1] [S2] [D]
· D = S1 - S2
【示例】
SUB 数据1 数据2 结果 // 结果 = 数据1 - 数据2
SUB 100 数据 结果 // 结果 = 100 - 数据4. 乘法指令(MUL)
4.1 乘法特点
乘法运算注意事项:
16位 × 16位 = 可能需要32位结果
示例:
30000 × 3 = 90000(超过16位范围)
因此乘法通常:
· 输入:16位
· 输出:32位(占用连续两个字)
三菱:
D0 × D10 → (D21,D20)
高16位 低16位4.2 乘法指令梯形图
【梯形图】
┌──────────┐
条件 ─────┤ MUL │
│ │
乘数1 ────┤IN1 OUT ├───── 结果
乘数2 ────┤IN2 │
└──────────┘
【逻辑表达】
结果 := 乘数1 × 乘数2; // 结果用双整数存储
【数据类型】
· 整数乘法(16位输入,32位输出)
· 双整数乘法
· 实数乘法4.3 乘法指令格式
【梯形图】
条件
───┤├───────[MUL 源1 源2 目标]───
【16位乘法】
MUL 数据1 数据2 结果
· 数据1 × 数据2 → 结果(32位)
· 结果存储在连续两个字单元
【32位乘法】
· 对于大数据,使用32位乘法指令
· 结果可能为64位5. 除法指令(DIV)
5.1 除法特点
除法运算结果:
被除数 ÷ 除数 = 商 ... 余数
示例:
17 ÷ 5 = 3 ... 2
商=3,余数=2
三菱DIV指令结果存储:
D20 = 商
D21 = 余数5.2 除法指令梯形图
【梯形图】
┌──────────┐
条件 ─────┤ DIV │
│ │
被除数 ───┤IN1 OUT ├───── 结果
除数 ─────┤IN2 │
└──────────┘
【逻辑表达】
商 := 被除数 / 除数;
余数 := 被除数 MOD 除数;
【数据类型】
· 整数除法(得商和余数)
· 双整数除法
· 实数除法(无余数)5.3 除法指令格式
【梯形图】
条件
───┤├───────[DIV 源1 源2 目标]───
【指令格式】
DIV [S1] [S2] [D]
· D = S1 ÷ S2 的商
· D+1 = 余数(整数除法)
【示例】
DIV 17 5 结果
· 结果 = 3(商)
· 结果+1 = 2(余数)
【除零保护】
条件 [除数<>0]
───┤├───────────┤├───────[DIV 被除数 除数 结果]───
重要:必须检查除数不为零!5.4 除零错误处理
除零错误处理:
【错误做法】
DIV 数据 0 结果 // 除数为0,运行错误!
【正确做法】
// 先检查除数
始终 [除数 <> 0]
───┤├───────────┤├───────[DIV 被除数 除数 结果]───
// 或使用条件判断(逻辑表达)
IF 除数 <> 0 THEN
结果 := 被除数 / 除数;
ELSE
结果 := 0; // 或设置错误标志
END_IF;6. 取模运算(MOD)
6.1 取模概念
取模运算:求除法的余数
示例:
17 MOD 5 = 2(17÷5=3...2)
10 MOD 3 = 1(10÷3=3...1)
8 MOD 4 = 0(8÷4=2...0,整除)
应用场景:
· 判断奇偶:N MOD 2(0为偶,1为奇)
· 循环计数:N MOD 10(0-9循环)
· 周期判断6.2 取模指令使用
【逻辑表达】
余数 := 被除数 MOD 除数;
【示例】
// 判断奇偶
IF (计数器 MOD 2) = 0 THEN
// 偶数
ELSE
// 奇数
END_IF;
【通过DIV指令获取余数】
条件
───┤├───────[DIV 被除数 除数 结果]───
结果+1单元中存储的就是余数
【提取余数】
MOV 结果+1 余数存储 // 将余数存入指定位置7. 递增与递减指令
7.1 递增指令(INC)
递增:将指定地址的值加1
【梯形图】
┌──────────┐
条件 ─────┤ INC │
│ │
数据 ─────┤IN/OUT │
└──────────┘
或:
条件
───┤├───────[INC 数据]───
效果:数据 = 数据 + 17.2 递减指令(DEC)
递减:将指定地址的值减1
【梯形图】
┌──────────┐
条件 ─────┤ DEC │
│ │
数据 ─────┤IN/OUT │
└──────────┘
或:
条件
───┤├───────[DEC 数据]───
效果:数据 = 数据 - 18. 三角函数与数学函数
8.1 常用数学函数
| 函数 | 功能 | 说明 | 输入单位 |
|---|---|---|---|
| SIN | 正弦 | 求角度正弦值 | 弧度 |
| COS | 余弦 | 求角度余弦值 | 弧度 |
| TAN | 正切 | 求角度正切值 | 弧度 |
| ASIN | 反正弦 | 反三角函数 | - |
| SQRT | 平方根 | 开平方 | - |
| LN | 自然对数 | 以e为底 | - |
| EXP | e的幂 | 指数函数 | - |
| ABS | 绝对值 | 取绝对值 | - |
8.2 数学函数梯形图
【梯形图】
┌──────────┐
条件 ─────┤ SIN │
│ │
角度 ─────┤IN OUT ├───── 结果
└──────────┘
【逻辑表达】
// 三角函数(输入为弧度)
结果 := SIN(角度); // 正弦
结果 := COS(角度); // 余弦
结果 := TAN(角度); // 正切
// 其他数学函数
结果 := SQRT(数值); // 平方根
结果 := ABS(数值); // 绝对值
结果 := LN(数值); // 自然对数
结果 := EXP(数值); // e的幂
// 角度转弧度
弧度 := 角度 × 3.14159 / 180.0;8.3 数学函数应用示例
【SIN正弦】
条件
───┤├───────[SIN 角度 结果]───
· 角度:输入角度值
· 结果:正弦值
【COS余弦】
条件
───┤├───────[COS 角度 结果]───
【TAN正切】
条件
───┤├───────[TAN 角度 结果]───
【SQRT平方根】
条件
───┤├───────[SQRT 数据 结果]───
· 数据:被开方数
· 结果:平方根值9. 数据类型转换
9.1 整数与实数转换
类型转换梯形图:
【整数→实数】
┌──────────┐
条件 ─────┤ INT_TO_ │
│ REAL │
整数 ─────┤IN OUT ├───── 实数
└──────────┘
【实数→整数】
┌──────────┐
条件 ─────┤ REAL_TO_ │
│ INT │
实数 ─────┤IN OUT ├───── 整数
└──────────┘
【逻辑表达】
实数值 := INT_TO_REAL(整数值);
整数值 := REAL_TO_INT(实数值); // 四舍五入
整数值 := TRUNC(实数值); // 截断
【取整方式】
TRUNC : 截断(3.7→3,-3.7→-3)
ROUND : 四舍五入(3.5→4)
FLOOR : 向下取整(3.7→3,-3.2→-4)
CEIL : 向上取整(3.2→4)9.2 BCD与BIN转换
BCD码与二进制转换:
BCD(Binary Coded Decimal):
· 每4位表示一个十进制数字
· 用于数码管显示
示例:
数值 1234
BIN: 0000 0100 1101 0010(0x04D2)
BCD: 0001 0010 0011 0100(0x1234)
【BIN→BCD】(用于数码管显示)
条件
───┤├───────[BCD 数据 显示输出]───
· 将二进制数据转为BCD码输出到数码管
【BCD→BIN】(读取拨码开关)
条件
───┤├───────[BIN 拨码输入 数据]───
· 将BCD输入转为二进制存入数据寄存器10. 应用实例
10.1 温度换算(华氏↔摄氏)
公式:
°F = °C × 9/5 + 32
°C = (°F - 32) × 5/9
【梯形图实现】(整数运算避免小数)
// °F = °C × 9 / 5 + 32
始终
───┤├───────[MUL 摄氏温度 9 中间值]─── // 中间值 = °C × 9
[DIV 中间值 5 中间值]─── // 中间值 = 中间值 / 5
[ADD 中间值 32 华氏温度]─── // °F = 中间值 + 32
【逻辑表达】(浮点运算)
华氏温度 := 摄氏温度 × 1.8 + 32.0;
摄氏温度 := (华氏温度 - 32.0) / 1.8;10.2 流量计算
需求:根据流速和管径计算流量
公式:Q = π × r² × v × 3600
· Q:流量(m³/h)
· r:管道半径(m)
· v:流速(m/s)
【逻辑表达】
半径 := 0.05; // 50mm半径
流量 := 3.14159 × 半径 × 半径 × 流速 × 3600.0;10.3 平均值计算
需求:计算10个采样值的平均值
数据:采样值[0]-[9]存储10个采样值
结果:平均值
【梯形图】
始终
───┤├───────[MOV 0 累加和]─── // 清零
[ADD 采样值0 累加和 累加和]─── // 累加
[ADD 采样值1 累加和 累加和]───
...
[ADD 采样值9 累加和 累加和]───
[DIV 累加和 10 平均值]─── // 除以10
【逻辑表达】(使用循环)
累加和 := 0;
FOR i := 0 TO 9 DO
累加和 := 累加和 + 采样值[i];
END_FOR;
平均值 := 累加和 / 10;10.4 PID增量计算
PID增量式算法:
Δu = Kp × (e(k) - e(k-1)) + Ki × e(k) + Kd × (e(k) - 2e(k-1) + e(k-2))
【逻辑表达】
// 定义变量
误差[0..2] // 当前、上次、上上次误差
Kp, Ki, Kd // PID参数
增量输出 // 输出增量
// 比例项
比例项 := Kp × (误差[0] - 误差[1]);
// 积分项
积分项 := Ki × 误差[0];
// 微分项
微分项 := Kd × (误差[0] - 2.0×误差[1] + 误差[2]);
// 总输出
增量输出 := 比例项 + 积分项 + 微分项;
// 误差移位(保存历史)
误差[2] := 误差[1];
误差[1] := 误差[0];本节小结
数学运算指令要点:
┌────────────────────────────────────────────────────┐
│ 基本运算 │
│ · ADD加法、SUB减法、MUL乘法、DIV除法 │
│ · 注意数据类型和溢出处理 │
│ · 除法前检查除数不为零 │
├────────────────────────────────────────────────────┤
│ 特殊运算 │
│ · MOD取模:求余数 │
│ · INC/DEC:递增/递减 │
│ · NEG:取反 │
├────────────────────────────────────────────────────┤
│ 数学函数 │
│ · 三角函数:SIN/COS/TAN(输入为弧度) │
│ · 其他:SQRT/ABS/LN/EXP │
├────────────────────────────────────────────────────┤
│ 类型转换 │
│ · INT↔REAL:整数与实数互转 │
│ · BCD↔BIN:用于数码管显示 │
└────────────────────────────────────────────────────┘练习题
- 编写程序计算两个16位整数的平均值。
- 设计一个温度转换程序(摄氏转华氏)。
- 如何避免除法运算时的除零错误?
- 说明16位乘法结果为什么需要32位存储。