工控论坛
26-10-22 13:43 微博认证:工控网工控论坛bbs.gkong.com官方微博

西门子模拟量为何偏偏是 27648?从原理讲透这个"怪数字"

详细:http://t.cn/AXjAFHeJ

每一个学西门子 PLC 的人,都绕不开一个数字:**27648**。

0~10V 对应 0~27648,4~20mA 对应 0~27648,±10V 对应 -27648~+27648。第一次见到它的人几乎都会问同一句话:

> "为什么不凑个整?30000 不行吗?32767 不好吗?"

这个数字看起来随意,实际上是西门子几十年工程经验凝结出来的一个精巧设计。今天我们从寄存器底层往上,一层一层把它讲透。

一、先看容器:一个 16 位有符号整数

模拟量转换后的数值,在 S7 里存放在一个 **16 位有符号整数(Int)** 中,取值范围是:

```
-32768 ~ +32767
```

这是整个故事的舞台。注意两个事实:

1. 正方向最大是 **32767**,不是 32768;
2. 这个容器是**带符号的**——这一点是理解 27648 的第一把钥匙。

现在问题变成了:**在这个 16 位容器里,额定满量程应该放在哪个位置?**

最直觉的答案是放到头:0~10V 就用 0~32767。但西门子没有这么做,因为——

---

二、留余量:过量程与欠量程的"缓冲带"

真实的工业现场,信号不会乖乖停在量程之内。

- 传感器有一定超限能力,0~10V 的板卡实际可能收到 10.5V 甚至 11V;
- 4~20mA 的仪表断线、短路时,电流会掉到量程之外;
- 温度变送器在超温时,输出可能轻微超过 20mA。

如果 10V 就顶到 32767,那么 10.01V 会发生什么?**溢出**。数值瞬间翻卷,程序里看到的是一个大负数,报警逻辑完全乱套,你还失去了"信号只是轻微超标"和"信号已经彻底异常"的区分能力。

于是西门子把额定满量程从 32767 往回撤,撤到 27648,硬生生留出了两段缓冲带:

| 数值区间 | 含义 | 对应 0~10V 板卡的实际电压 |
|---|---|---|
| 0 ~ 27648 | **额定量程**(正常工作区) | 0 ~ 10.0V |
| 27649 ~ 32511 | **过量程(Overrange)** | 约 10.0 ~ 11.76V |
| 32512 ~ 32767 | **溢出(Overflow)** | 超出可表示范围 |

负方向对称:-27649 ~ -32511 是欠量程,-32512 ~ -32768 是溢出。

这样一来,程序拿到数值就能直接"读出"现场状态:

- 落在 0~27648:一切正常,正常换算;
- 落在 27649~32511:**信号有,但超标了**——报警"测量值超限",但数值仍然可信、可用;
- 落到溢出区:**信号不可信**——立即打报警、锁存故障。

至于 4~20mA:4mA 对应 0,20mA 对应 27648。低于 0 的负值区间(最低可到约 1.185mA 对应 -4864)专门用来做**断线检测**——电流掉进这个"活零点以下"的区间,几乎可以断定回路断了。这就是 4~20mA"活零点"设计在数字侧的完整闭环。

一句话总结这一层:**27648 = 给异常留出的呼吸空间。量程不是刻度的尽头,而是信任的边界。

三、为什么偏偏是 27648,而不是 27000、30000?

"留余量"解释了满量程应该小于 32767,但为什么是 27648 这个数?这里藏着最"复古"也最优雅的一层。

把 27648 转成十六进制:

27648 = 0x6C00

再看二进制:

27648 = 0110 1100 0000 0000

看出来了吗?**低 10 位全是 0**。也就是说:

27648 = 27 × 1024 = 27 × 2^10

在上世纪七十~九十年代,PLC 里跑的是没有浮点单元(FPU)的 8 位、16 位处理器,乘除法极其昂贵,而**除以 2 的幂次,只需要一条移位指令(甚至免费——进位标志顺带就做了)**。

满量程取 27×2^10,意味着"满量程 ÷ 1024"这种高频运算零成本。0x6C00 在十六进制世界里的地位,就和十进制世界里的"27000"一样——是一个**round number(整数)**。西门子工程师选的不是 27648,选的是 **0x6C00**。

再补充一个巧合般的整洁关系:

27648 / 32768 = 27 / 32 = 0.84375

即额定量程恰好占满 15 位(含符号)空间的 84.375%,两侧各留出约 **17.6%** 的过量程余量——这个比例正好覆盖了当时绝大多数传感器、运放电路的实际超限能力(0~10V 板卡实测普遍能线性测到约 11.5V)。

> 顺带一提,32511 = 0x7EFF——过量程的终点在十六进制下同样是个"整数"。整个编码表,处处透着二进制美学。

至于"27"这个系数最原始的出处,要追溯到西门子更早期的 S5 系列乃至 TELEPERM 过程控制系统的编码传统,属于历史遗留的约定。但可以确定的是:**留余量 + 移位友好 + 比例合理**,这三点让 0x6C00 成了那个年代最合理的答案,并且一用就是半个世纪。

四、更深一层:与硬件分辨率"解耦"

还有一个常被忽略的设计意图。

模拟量板卡的分辨率一直在变:S5 时代是 12 位(0~4095),后来有 13 位、14 位、15 位,高精度模块到 16 位。如果 PLC 程序直接使用 ADC 原始码值,那么**换一块板卡,全厂程序里的标定常数都得重算**。

西门子的做法是:不管你 ADC 是多少位,模块固件统一把额定满量程**归一化到 27648。

- 12 位板卡:1 LSB 原始码 ≈ 6.75 个机器数;
- 16 位板卡:额定量程被压缩映射到同一区间。

结果就是:**你的程序永远面对同一个标尺**。今天把 ET200SP 的 16 位模块换成 S7-300 的老 12 位模块,用户程序一行都不用改。这在"程序寿命往往超过硬件寿命"的工业界,价值巨大。

TIA Portal 里 `NORM_X` / `SCALE_X` 指令、模拟量通道的"硬件标定",背后都是这套以 27648 为锚点的归一化体系。

## 五、落到实操:换算代码怎么写

标准换算公式(以 0~10V → 0~100.0% 为例):

工程值 = (模拟量原始值 / 27648.0) × 量程上限

SCL 写法:

```scl
// 0~10V → 0.0~100.0 %
#rValue := DINT_TO_REAL(#diRaw) / 27648.0 * 100.0;

三个工程提醒:

1. **先判状态再换算**。先检查原始值是否在 0~27648 之外,落入过量程/溢出区间就直接走报警分支,别让异常数据混进 PID。
2. **整数路径优先**。若精度要求不高,用 `raw * 1000 / 27648` 的纯整数运算(注意中间结果用 DINT,防止 16 位乘法溢出),比浮点更快更稳。
3. **记住几个换算常数**:10V ÷ 27648 ≈ **361.7 µV/码**,20mA 量程下 ≈ **0.5787 µA/码**,心里对"一个码值代表多少物理量"有数,调试时对异常数据会敏感得多。

六、结语:一个数字里的工程哲学

回头看,27648 至少回答了三个问题:

- **为什么不满量程用 32767?** —— 给过量程、断线检测留缓冲带,正常、超标、故障,三态可分;
- **为什么是这么个怪数?** —— 它是 0x6C00,27×2^10,低 10 位全零,对没有浮点单元的老 CPU 极度友好;
- **为什么几十年不变?** —— 它把硬件分辨率和用户程序解耦,程序活得比模块久。

27648 不是自然界的常数,它是**工程妥协的最优解**:在 16 位带符号容器里,同时装下"正常测量、超限预警、故障检测"三种需求,还顺手让老处理器的除法变成了移位。

下次再在博途里看到 27648,希望你想起的不是一个"怪数字",而是一整套完整的信号处理哲学——**好的工程数字,从来都不是凑出来的整数,而是算出来的边界。**

发布于 广东