信捷C语言POU封装举例

一般而言,我们使用POU都是为了将特定的功能,做成一个函数,在需要重复使用这个功能的时候,只需要调用这个函数,分配给他对应的寄存器进行数据运算即可。免去重复写很多相同的程序。POU分为FC与FB两种,在使用POU进行封装的时候,我们要考虑以下几件事情:1、这个“功能”是在不同地方重复使用的么?这关系到封装是否有意义。2、这个“功能”是一个小功能么?3、如果不是那么可以继续拆分成几个小功能么?。思考完这几个问题后,我们可以得出一个基本的结构,最小的功能单元由FC实现,最大的整体的由FB来实现。因为FC自己不占用数据空间,可以打个比方,我们有一个数学函数f(x),给x一个值,就可以得出另一个值。而FB需要为其分配数据区,就像一个函数集合,写在一张纸上,想要得出一个最终结果,输入值会在若干个函数中来回传递,中间产生的每一段临时结果会被写在空白的地方辅助下一步计算。所以下面我会举例说明。

我们在程序开发中有时会遇到设备累计运行时间,某机构累计运行时间,如定时提示更换、维保。针对这种场景,如果开发一个POU,那么在不同设备上,或者一个设备的不同工位上,就可以重复调用,不用写完一遍来回复制。对于这个功能我们可以先进行开发分析,累计时间我们可以使用系统内置的时钟脉冲来累计,然后这里面涉及到很多的运算,数据需要存储所以整体要用FB,内部可以拆出一个采集时钟脉冲上升沿的FC。然后我们进行开发,首先开发上升沿采集函数。

首先定义一个边沿采集函数结构体

Struct

{
       Bool Ex;//采集对象

       Bool Status;//状态锁存

       Bool Q;//边沿输出

}Edge_Trige_Struct;

然后定义上升沿函数FC,

声明区

VAR_INOUT Edge Edge_Trige_Struct

函数区

void R_Trige(Edge_Trige_Struct* Edge)//定义一个名为Edge的Edge_Trige_Struct类型结构体指针

{

       #define SysRegAddr_HD_D_HM_M

       if(Edge->Ex == 1 && Edge->Status == 0)//当此刻为1锁存为0,则认为0~1

    {

        Edge->Q = 1;//输出1

    }

    else

    {

        Edge->Q = 0;

    }

    Edge->Status = Edge->Ex;//锁存此刻状态

}

上升沿函数开发完毕后继续开发主体函数。

声明区

VAR_INPUT Start Bool//启动计时器

VAR Second Real//中间计算量-秒

VAR MinuteReal//中间计算量-秒

VAR HourReal//中间计算量-秒

VAR Day Real//中间计算量-秒

VAR U_M Real//累计分钟

VAR U_H Real//累计小时

VAR U_D Real//累计天数

VAR R_Trige0 Edge_Trige_Struct//边沿采集函数参数结构体传递

VAR_OUTPUT Minutes//输出累计分钟

VAR_OUTPUT Hours//输出累计小时

VAR_OUTPUT Days//输出累计天数

函数区

void TMR_S_BODY(TMR_S* self)//定义一个名为self的TMR_S类型结构体指针

{

#define SysRegAddr_HD_D_HM_M_SM



    if ( self->Start )

    {

        self->R_Trige0.Ex = SM[13];//上升沿函数结构体采集对象赋值

        R_Trige ( &self->R_Trige0 );//函数内部参数是结构体指针形式,所以外部要以取地址形式来写

        if ( self->R_Trige0.Q )

        {

            self->Second = self->Second + 1;



            if ( self->Second >= 60 )

            {

                self->Minute = self->Minute + 1;

                self->Second = 0;

            }

            if ( self->Minute >= 60 )

            {

                self->Hour = self->Hour + 1;

                self->Minute = 0;

            }

            if ( self->Hour >= 24 )

            {

                self->Day = self->Day + 1;

                self->Hour = 0;

            }

        }

    }

    self->U_M =  self->Day * 24 * 60 + self->Hour * 60 + self->Second / 60 + self->Minute;

    self->U_H = ( self->Day * 24 ) + ( self->Hour ) + ( self->Minute / 60 ) + ( self->Second / 3600 );

    self->U_D = ( self->Day ) + ( self->Hour / 24 ) + ( self->Minute / 1440 ) + ( self->Second / 86400 );

 

    self->Minutes = self->U_M;

    self->Hours = self->U_H;

    self->Days = self->U_D;

}

其实写到这里,如果看明白了,你会发现我这似乎是把FC写成了FB,因为都变成了结构体指针传递的形式。其实我一开始的边沿函数是三个参数直接写在外面的,然后FB内部定义静态变量,再放给函数参数。这样可以少一个结构体,相对来说灵活,但不够简洁。写这篇文章的时候,我发现如把边沿函数的参数改为结构体形式,可能会使看到这里的你恍然大悟,对于FB与FC理解的更透彻,所以直接修改了一下。一般我们希望FC实现的是y=kx这样给一个x立刻出一个y不需要上面那种锁存的功能。所以也可以理解为瞬时的动作我们用FC,连续的处理用FB。实际上在IEC标准下,例如TIAPORTAL或者CODESYS里,边沿函数都是FB的形式。

本篇就到这里,受本人水平所限,错漏之处请多包涵。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贰佰肆拾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值