8421码到5421码的转换_你真的会用BCD码指令么?

在我前天发表的文章《图说西门子特殊寄存器之SM1.0-SM1.7》中讲到SM1.6处,我留了一个问题给朋友们,就是:“使用BCD码转整数指令时候,为何输入参数是1113指令运行无错误,而当输入参数是1114时指令运行出错了?”,以这个为引子,开始我今天的文章。

说到BCD码可能会立马想到8421码,读书的时候应该接触的就是这个。其实BCD码还可以分为有权码、无权码,还有什么5421码,但这些都不是我要讲的,本人要说的是西门子200PLC中关于BCD码的指令,特别是BCD码转换指令出错的原因分析。

BCD码(Binary-Coded Decimal‎)也叫二-十进制码,是用4位二进制数表示十进制数中0-9这10个数字的一种码。这个是BCD码的基础定义,不管是什么PLC都要遵守的,所以特意再提出来。

首先来看2张监控截图:

271531632effd0a39c9a6b54cc53f57a.png

BCD指令错误监控图1

b45a955742ac5d112d2dc95ace89cc7a.png

BCD指令错误监控图2

从上边这2张图上,我们可以看到BCD_I指令的输入端输入整数10-15和输入十六进制的ABCDEF时候,该指令都出错了(此时SM1.6会被置1,可以去看前一篇文章),因此后边的ENO都无法输出了,后边的监控线头是灰色,因为没有能流。同时,还可以看到输入整数值16的时候,程序没有出错,为什么呢?

根据BCD码的基础定义“用4位二进制数表示十进制数中0-9这10个数字”,从这句话可知十六进制的ABCDEF就是十进制的10-15,这明显超出了基础定义的0-9,因此16进制下的ABCDEF用作输入参数时指令出错的原因就找到了。

那么为何输入整数16处理的时候就没有出错呢?BCD_I指令的输入端这里,在指令处理的时候BCD端的参数,是以怎样的真实格式化去处理的?

cf9a2784d0ebbb1bd7f3b37a3fefc506.png

Micro/WIN软件中对指令的解释

根据帮助文件的解释和实际的程序,我猜测可能有2种可能:

①是以直接以2进制BCD码的格式来处理的(也就是说16已经被看作一个BCD码数,那他的二进制应该是BCD 2#0001 0110 == 16#16)?

②是以16进制下的值看作BCD的格式来处理的(也就是说将整数16自动转换为16#10,BCD 16#10)?

--为了探明这问题,继续看下一个图片。

842fd673b49122f57bf206cfc467900d.png

BCD指令监控图3

18327c366645530019409beb76b86355.png

BCD指令监控之状态表图

从监控图3可以看到,BCD端输入整数16,被转换为整数10。而将VW0也就是整数10再次作为BCD_I指令的输入端时,指令又出错了。按照上边猜测①的思路16是当做一个BCD码看待的,即BCD 2#0001 0110,那么转化后的结果应该是16才对,而监控中VW0的结果是10,由此可见,思路①的猜测是错误的。

那么只有按照思路②来看,输入端的整数16先是被转换为16进制下的16#10后看作一个BCD码再去转换的,也就是将16#10即2#0001 000看作了BCD码,因此转化为十进制数就是10。以这样的解释来看结果,那么结果就对了,再来多试验看看:

6ce0c4eace3c4ad9e75f96bd13561484.png

BCD指令监控图4

从这个图片可以看到整数17被转换为了11,整数18被转换为了12。

17的16进制表示就是16#11,即BCD 16#11==2#0001 0001,因此转化BCD转化为整数就是11。

18的16进制表示就是16#12,即BCD 16#12==2#0001 0010,因此转化BCD转化为整数就是12。(请忽略本文中的==用法的不准确性,仅为说明问题,谢谢)

所以,到这里BCD_I指令,BCD输入端其实是16进制下的BCD值,BCD_I指令更加准确的描述应该是将16进制BCD码转化为为整数,不知道帮助文件或者西门子200的手册为何没有强调这个16进制。下图是手册上的解释:

994a36bf7ac5e39060baf2ae80d264e2.png

BCD码指令在系统手册上的解释

但是我在西门子找答案网页上发现了西门子的专家置评,见下图:

c65b80caf06f1ae1b6a27c43fe9b2591.png

BCD_I指令的官方评价

所以,文章写到此,可以得出一个结论:BCD_I指令就是将16进制的BCD码转化为整数的一个指令,其在BCD参数输入端的值为16进制数时最好,不为16进制数时系统将自动将其转化成16进制数,而后才对其进行运算。

再进一步来说一下BCD端是要求16进制的问题,下边看一个西门子300的程序切图:

dfbd57ed8994dfe39934e5d962af585a.png

M20.0不为1时切图

这个图片是值运行程序第2行,整数16通过BCD_I指令后结果也是10,证明是和西门子200中的算法一样的。

8dedf2156eb01367b4ae5f7b30004491.png

M20.0为1时切图

这个图片是将M20.0置1,程序第1行也接通,从这个图片上看到PLC还是在运行,ENO还是输出了,这是和西门子200系统不一样的地方,但是MW2的值此时为0,显然是不对的,所以PLC还是给出了提示:

5ec8e79d5e1ec35e9412b6f771058472.png

300系统指示灯报错了

6875a853e747bb6231a90dff668b92a4.png

诊断报告说BCD转换错误

这两个图详细说明了,因为程序第一行的BCD_I指令出现错误,所以系统报错了。报错的真是原因是什么呢?就是整数10被转为了16#0a,而BCD码的基本概念是用4位二进制数表示0-9这10个十进制数,因此BCD #160a是非法的,它不能被看作是一个BCD码。

写到这里,再回头看我在之前的文章中留下的问题:“使用BCD码转整数指令时候,为何输入参数是1113指令运行无错误,而当输入参数是1114时指令运行出错了?”,我想有的朋友已经有答案了。

答案就是:BCD_I指令是要求16进制的BCD码格式,整数1113转化为16进制是16#459,整数1114转化为16进制是16#45A,而出现A就是非法的BCD码。这就是最终的答案。

758cfdd7b026ca9b1e9882050c47be52.png

整数1114转化为16进制是16#45A

本篇文章结束,可能有点费理解,但是提高就是不断的越过障碍,希望通过本文能让朋友们对BCD相关指令编程时候的错误情况有一个更深入的了解,不至于出错了还要想很久才知道哪里错了。

最后,感谢大家的支持,有不明白的地方,敬请关注留言,我会及时回复,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值