4.2 移位与循环指令
本节将介绍PLC的移位和循环操作指令
学习目标
- 掌握移位指令的类型和用法
- 理解逻辑移位与算术移位的区别
- 能够灵活运用移位指令
1. 移位指令概述
1.1 什么是移位操作
移位操作是将数据的所有位向左或向右移动指定位数的操作。
移位操作示意图:
原始数据: [1][0][1][1][0][0][1][0]
↓ 左移2位
移位后: [1][1][0][0][1][0][0][0]
↑↑
补0(左移右侧补0)
原始数据: [1][0][1][1][0][0][1][0]
↓ 右移2位
移位后: [0][0][1][0][1][1][0][0]
↑↑
补0(逻辑右移左侧补0)1.2 移位指令分类
移位指令类型:
┌─────────────────────────────────────────────────────┐
│ 移位指令 │
├────────────────┬────────────────┬───────────────────┤
│ 逻辑移位 │ 算术移位 │ 循环移位 │
├────────────────┼────────────────┼───────────────────┤
│ · SHL 逻辑左移 │ · 保留符号位 │ · ROL 循环左移 │
│ · SHR 逻辑右移 │ · 右移时高位 │ · ROR 循环右移 │
│ · 补0 │ 补符号位 │ · 移出位回到另端 │
└────────────────┴────────────────┴───────────────────┘1.3 移位指令通用格式
| 功能 | 通用指令 | 说明 |
|---|---|---|
| 逻辑左移 | SHL | 右侧补0 |
| 逻辑右移 | SHR | 左侧补0 |
| 循环左移 | ROL | 移出位回右侧 |
| 循环右移 | ROR | 移出位回左侧 |
| 位移位寄存器 | SFTR/SFTL | 位元件批量移位 |
2. 左移指令(SHL)
2.1 逻辑左移原理
逻辑左移(SHL)原理:
所有位向左移动,右侧补0,左侧移出的位丢弃
示例:左移2位
Before: [1][0][1][1][0][1][0][0] = 0xB4 (180)
↓
After: [1][1][0][1][0][0][0][0] = 0xD0 (208)
└─┬─┘ ↑↑
丢弃 补0
数学意义:左移n位 ≈ 乘以2ⁿ
180 × 4 = 720(但结果溢出,实际为208)2.2 左移指令梯形图
【梯形图】
┌──────────┐
条件 ─────┤ SHL │
│ │
数据 ─────┤IN OUT ├───── 结果
移位数 ───┤N │
└──────────┘
【逻辑表达】
结果 := SHL(数据, 移位数);
// 或
结果 := 数据 SHL 移位数;
【数据类型】
· 16位字左移
· 32位双字左移2.3 位元件左移指令
位元件批量左移(SFTL):
【梯形图】
条件 源 目标 位数 长度
───┤├───────[SFTL 源 目标 位数 长度]───
【参数说明】
· 源:移入数据源
· 目标:移位区起始
· 位数:每次移位位数
· 长度:移位区总长度
【工作过程】
移位区数据向左移动,右侧移入新数据3. 右移指令(SHR)
3.1 逻辑右移原理
逻辑右移(SHR)原理:
所有位向右移动,左侧补0,右侧移出的位丢弃
示例:右移2位
Before: [1][0][1][1][0][1][0][0] = 0xB4 (180)
↓
After: [0][0][1][0][1][1][0][1] = 0x2D (45)
↑↑ └─┬─┘
补0 丢弃
数学意义:右移n位 ≈ 除以2ⁿ
180 ÷ 4 = 453.2 算术右移
算术右移(SAR)原理:
右移时保留符号位(最高位)
示例:算术右移2位(有符号数-76)
Before: [1][0][1][1][0][1][0][0] = 0xB4 (-76有符号)
↓
After: [1][1][1][0][1][1][0][1] = 0xED (-19有符号)
↑↑ └─┬─┘
补符号位 丢弃
数学意义:-76 ÷ 4 = -19
保持负数特性3.3 右移指令梯形图
【梯形图】
┌──────────┐
条件 ─────┤ SHR │
│ │
数据 ─────┤IN OUT ├───── 结果
移位数 ───┤N │
└──────────┘
【逻辑表达】
结果 := SHR(数据, 移位数);
// 或
结果 := 数据 SHR 移位数;
【数据类型】
· 16位字右移(逻辑)
· 32位双字右移3.4 位元件右移指令
位元件批量右移(SFTR):
【梯形图】
条件 源 目标 位数 长度
───┤├───────[SFTR 源 目标 位数 长度]───
【参数说明】
· 源:移入数据源
· 目标:移位区起始
· 位数:每次移位位数
· 长度:移位区总长度
【工作过程】
移位区向右移动,左侧移入新数据4. 循环移位指令(ROL/ROR)
4.1 循环左移(ROL)
循环左移原理:
左侧移出的位回到右侧,形成循环
示例:循环左移2位
Before: [1][0][1][1][0][1][0][0]
↓
After: [1][1][0][1][0][0][1][0]
↑↑
从左侧移出的位
移出的[1][0]回到了右侧4.2 循环右移(ROR)
循环右移原理:
右侧移出的位回到左侧,形成循环
示例:循环右移3位
Before: [1][0][1][1][0][1][0][0]
↓
After: [1][0][0][1][0][1][1][0]
↑↑↑
从右侧移出的[1][0][0]
移出的位回到了左侧4.3 循环移位指令梯形图
【梯形图】
┌──────────┐
条件 ─────┤ ROL │
│ │
数据 ─────┤IN OUT ├───── 结果
移位数 ───┤N │
└──────────┘
【逻辑表达】
// 循环左移
结果 := ROL(数据, 移位数);
// 循环右移
结果 := ROR(数据, 移位数);
【特点】
· 不丢失任何位
· 适合位图循环显示
· 适合密钥轮换等应用5. 字移位指令
5.1 字移位指令
字右移(WSFR):
条件
───┤├───────[WSFR 源 目标 长度]───
· 源:移入数据
· 目标:移位区起始
· 长度:移位区长度(字数)
工作原理:
Before: 目标[0]=A, 目标[1]=B, 目标[2]=C, 目标[3]=D, 目标[4]=E
移位后: 目标[0]=源, 目标[1]=A, 目标[2]=B, 目标[3]=C, 目标[4]=D
E被移出丢弃5.2 FIFO/LIFO操作
FIFO(先进先出)队列:
【入队指令】
条件
───┤├───────[SFWR 数据 队列 容量]─── // 数据入队
【出队指令】
条件
───┤├───────[SFRD 队列 目标 容量]─── // 从队列出队
队列结构:
队列[0] = 当前元素个数
队列[1..n] = 数据区
说明:
· FIFO:先入先出,适合排队处理
· LIFO:后入先出,适合堆栈操作6. 移位寄存器应用
6.1 步进控制
移位寄存器实现步进控制:
需求:控制8个工位依次动作
节拍信号 移入 步进 位数 长度
───┤P├──────[SFTL 1 步进区 位数 长度]───
· 每次节拍信号脉冲,步进区中的1向左移动一位
· 步进区[0]=1→步进区[1]=1→...→步进区[7]=1
输出控制:
步进区[0]
───┤├───────( 工位1 )───
步进区[1]
───┤├───────( 工位2 )───
...
步进区[7]
───┤├───────( 工位8 )───6.2 产品跟踪
应用:传送带产品跟踪
传感器检测产品,跟踪产品在传送带上的位置
节拍脉冲 入口检测 跟踪区 位数 长度
───┤├───────[SFTL 入口检测 跟踪区 位数 长度]───
· 节拍脉冲:传送带节拍信号(如编码器脉冲)
· 入口检测:入口检测(有产品=1)
· 跟踪区:跟踪区域(20个位置)
当跟踪区[10]=1时,表示产品到达位置10
跟踪区[10]
───┤├───────( 位置10动作 )──6.3 流水灯效果
流水灯程序:
方法1:循环移位
秒脉冲 数据 移位数
───┤├───────[ROL 数据 1 数据]───
始终
───┤├───────[MOV 数据 输出组]───
· 秒脉冲:1秒时钟脉冲
· 数据初始值=1
· 每秒循环左移1位
· 输出到LED组
方法2:表格循环
秒脉冲
───┤P├──────[INC 索引]───
[索引 > 7]────[MOV 0 索引]───
始终
───┤├───────[SHL 1 索引 输出]───
效果:LED0→LED1→LED2→...→LED7→LED0 循环7. 移位运算技巧
7.1 乘除法替代
用移位代替乘除法(效率更高):
乘法:
· X × 2 = X SHL 1
· X × 4 = X SHL 2
· X × 8 = X SHL 3
· X × 2ⁿ = X SHL n
除法:
· X ÷ 2 = X SHR 1
· X ÷ 4 = X SHR 2
· X ÷ 8 = X SHR 3
· X ÷ 2ⁿ = X SHR n
示例:X × 10 = X × 8 + X × 2 = (X SHL 3) + (X SHL 1)7.2 位提取
提取特定位:
提取第n位的值:
结果 = (数据 SHR n) AND 1
【梯形图】提取数据第5位
始终
───┤├───────[SHR 数据 5 中间值]───
[AND 中间值 1 结果]───
结果 = 数据的第5位值(0或1)7.3 位设置/清除
设置特定位为1:
数据 = 数据 OR (1 SHL n)
清除特定位为0:
数据 = 数据 AND (NOT (1 SHL n))
翻转特定位:
数据 = 数据 XOR (1 SHL n)
【梯形图】设置数据第3位为1
始终
───┤├───────[SHL 1 3 掩码]─── // 掩码 = 0x08
[OR 数据 掩码 数据]─── // 数据第3位置18. 应用实例
8.1 信号灯循环控制
需求:8个信号灯循环点亮
程序:
// 初始化
首次扫描 // 首次扫描标志
───┤├───────[MOV 1 数据]─── // 数据 = 0x0001
// 定时移位
定时器
───┤├───────[ROL 数据 1 数据]─── // 循环左移
// 定时器(500ms)
始终 定时器
───┤├─────────┤/├─────[OUT 定时器 500ms]───
// 输出
始终
───┤├───────[MOV 数据 输出组]─── // 输出到LED组
效果:LED0→LED1→LED2→...→LED7→LED0 循环8.2 数据加密(简单异或+移位)
简单加密算法:
加密:
1. 与密钥异或
2. 循环左移3位
解密:
1. 循环右移3位
2. 与密钥异或
【加密梯形图】
加密按钮
───┤├───────[XOR 明文 密钥 中间值]─── // 异或
[ROL 中间值 3 密文]─── // 循环左移
【解密梯形图】
解密按钮
───┤├───────[ROR 密文 3 中间值]─── // 循环右移
[XOR 中间值 密钥 明文]─── // 异或还原8.3 串行数据接收
移位寄存器接收串行数据:
数据输入 // 数据输入
───┤├───────[MOV 数据输入 接收位]───
时钟脉冲 // 时钟脉冲
───┤P├──────[SFTL 接收位 数据区 1 16]──
每个时钟脉冲:
· 读取数据输入状态到接收位
· 数据区左移1位
· 接收位移入数据区
16个脉冲后,数据区存储16位串行数据本节小结
移位指令要点:
┌────────────────────────────────────────────────────┐
│ 逻辑移位 │
│ · SHL左移:右侧补0 │
│ · SHR右移:左侧补0 │
│ · 移出的位丢弃 │
├────────────────────────────────────────────────────┤
│ 算术移位 │
│ · 右移时保留符号位 │
│ · 用于有符号数除法 │
├────────────────────────────────────────────────────┤
│ 循环移位 │
│ · ROL/ROR:移出位回到另一端 │
│ · 不丢失数据,适合循环显示 │
├────────────────────────────────────────────────────┤
│ 应用技巧 │
│ · 移位代替乘除(×2ⁿ/÷2ⁿ) │
│ · 位提取/设置/清除 │
│ · 步进控制、产品跟踪 │
└────────────────────────────────────────────────────┘练习题
- 说明逻辑右移和算术右移的区别。
- 编写程序实现8个LED灯的流水效果。
- 如何用移位指令实现乘以10的运算?
- 设计一个移位寄存器实现5工位步进控制。