可锐资源网

技术资源分享平台,提供编程学习、网站建设、脚本开发教程

[西门子PLC] 博途编程之递归算法


首先跟大伙讲一讲哈,递归算法瞅着是挺优雅挺不错的,可实际上没啥大用,在真正的项目里能不用就别用递归,为啥呢?因为用了递归可能会惹出大麻烦,后面会给大伙举例讲讲原因。

那啥叫递归呢?从名字上就能看出来,就是先传出去,再弄回来。举个例子哈,好比有个集团公司要统计月度产量数据,分成总部、工厂、车间这三级。假设每个层级都能去执行统计产量数据这个命令,那递归的表现就是,领导要看数据的时候,给总部层级下达执行统计产量数据的命令,总部层级执行命令的时候,发现数据得靠工厂层级,所以就先给工厂层级下达执行统计产量的命令,同样的,工厂层级依赖车间层级的数据,也先给车间层级下达执行统计产量数据的命令,这就是递归里的“递”,也就是一级一级地往下传命令。



那命令到了车间层级之后呢,车间是最底层啦,产量数据就在它那儿,不依靠别的啥了,所以它能直接执行命令,弄完之后把结果交给工厂层级。工厂层级拿到车间层级的数据再汇总一下,命令就算执行完了,把结果再交给总部层级。总部层级拿到工厂层级的数据也汇总一下,命令执行结束,把结果交给领导,这就是递归里的“归”,也就是一级一级地往上交结果。



所以递归的想法呢,

一是把自己这一级的事儿做好,

二是把下一层级的事儿用同样的办法处理完了再回来,

三是到了最下面那一层级处理完就回来。

所以递归有个特别明显的特点,就是会自己调用自己,也就是函数 A 调用函数 A 调用函数 A ,一直到最下面那一层级。好多刚开始学的人看到这儿可能就不太明白了,函数咋能调用它自己呢?函数都还没执行完,咋就调用自己了?这是操作系统的一个基本常识,咱们可以这么想,函数写完之后,就好比是一份做 5 层套娃的图纸,当你开始按照图纸做套娃的时候,做了一半,也就是在图纸的中间部分,图纸告诉你,最外面第 1 层先做到这儿,回到图纸开头,按照 4/5 的尺寸做第 2 层,第 2 层做到一半的时候,又到了图纸中间部分,又告诉你,第 2 层先到这儿,再回去做第 3 层,就这么依次往下,一直到第 5 层的时候,图纸在中间没打断你,能顺利做完,在图纸最下面,告诉你第 5 层做完之后回到图纸中间做第 4 层,就这么依次往下,一直到第 1 层结束。

注意哈,这里咱们看到的都是同一份图纸,函数就像这图纸似的,咱们做套娃的这个过程就好比 PLC 在执行咱们的函数一样。这样是不是能好理解一点儿啦?




下面通过三个程序示例来展示展示。

示例 1 是反转位序的功能。

在和第三方设备通讯读取一些状态字的时候,有时候会碰到位序反过来的情况。正常来说,一个字节的位序从低到高,是位 0 到位 7 ,反过来的话,从低到高,就是位 7 到位 0 ,所以就得把位序给反转一下。




咱们来试着用递归来实现。函数的输入参数有要反转的字节 byte ,还有层级变量 bitPos ,以及返回的结果。

实现的部分呢,

一是先把自己这一层级的事儿做好,读取当前层级变量 bitPos 位置以及对应逆序位置指示的位变量是不是 1 ,然后把对应逆序位置的位变量设置成 0 或者 1 ,这里用了一些位运算,新手可以拿来练练。

二是对于下一层级的事儿,用同样的办法去处理,也就是调用函数自己去处理下一层级。

三是到了最下面那一层级的时候,就返回数据。因为咱们处理的是字节,所以到了位 3 的时候,就是最下面那一层级啦。




先不管上面处理位运算的那部分,就看下面这一块儿,是不是觉得特别优雅特别神奇,自己调用自己就把事儿给办了。


下面来测试一下,结果是正确的。


再来看示例2,


比如说 PLC 带着好多 Profinet 节点,要求要是有节点出现通讯之类的故障时,得有个指示。

输入的参数里,nodeHwIds 是 Profinet 节点的标识符,pos 是层级,返回的结果是 Bool 型的,用来指示有没有故障。

实现的部分呢,同样是先把本层级的事儿做好,然后用一样的方法去处理下层级的事儿,到了最下层级就直接返回。





咱们测试一下哈,建立一个有 10 个元素的数组,把其中一个值改成 4 (FC_HW_Error 是用来仿真的,当节点标识符除以 5 余数是 4 的时候,就代表故障),能看到结果是对的。




当系统的节点增多之后,比如说变成 20 个,这时候只要把数组的长度改成 20 个就行。不过当你修改完然后下载程序之后,就会发现,PLC 出故障啦,报告函数超出了嵌套深度。




那这到底是为啥呢?要晓得,函数执行是得耗费系统资源的,会消耗内存里栈空间那部分,这个资源是有限的,就跟俄罗斯套娃似的,总归是有局限的。

而递归呢,因为是自己调用自己,每一层级在还没执行完的时候,都会分别占用栈空间的资源,当层级太多超过栈空间了,就会造成栈空间溢出。所以就算递归的想法看上去挺优雅挺不错的,咱们在实际的项目里也别用它。

因为能用递归完成的功能,都能够用循环来完成,而且用循环往往执行效率还更高。下面就是用循环实现的版本。



PLC编程之美丽又危险的递归算法

http://bbs.plcjs.com/forum.php?mod=viewthread&tid=507223&fromuid=17

(出处: PLC论坛-全力打造可编程控制器专业技术论坛)

#非标自动化#

#西门子PLC#

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言