Beremiz运动控制,IEC61131编程语言SFC关联动作限制符: N、R、S、L、D、P、P0、P1、SD、DS、SL含义与区别

 Refer:

1. SFC语言编辑器 · NetPAC操作使用手册 · 看云 (kancloud.cn) https://www.kancloud.cn/gastonfeng/kvpac_beremiz/1841545

2. 开源PLC编程软件Beremiz (kaikong.cn)   https://www.kaikong.cn/Beremiz/

IEC61131-3 规定 Program Organization Units(POU)程序组织单元,包含Program,Fuction Block,Fuction,POU是个封装的单元,可以独立编译,并作为其他程序的部件,经编译的POU可以连接在一起组成完整的程序.

Beramiz 提供符合IEC61131-3标准的编程开发环境。IEC 61131-3是PLC编程开发的国际标准,这个标准将程序的基本单位称为程序组织单元( Program Organisation Unit,POU),并定义了三种程序组织单元:函数(FC)、函数块(FB)和程序(PROG)。今天这篇文章,我们就来详细介绍下程序组织单元。

IEC 61131-3定义了三种 程序组织单元POU,分别是:

函数(FC):Function可以有输入/输出参数,但是没有静态变量。使用相同的参数调用函数时,总会产生相同的输出结果。另外,定义函数时,必须指定返回值类型;
函数块(FB):Function Block也被称为“功能块”,可以有输入/输出参数,并且可以有静态变量。使用相同的参数调用函数块时,由于静态变量的保持性,可能产生不同的输出结果;
程序(Prog):Program类似于C语言的Main函数。程序内部调用函数或函数块,外部被任务(Task)调用而执行;

SFC语言的主要元素是:初始步骤步骤、转换、动作块、分支、“跳跃”。 SFC程序由通过转换连接的一组步骤组成。

一旦具有SFC图表编辑功能的标签被激活,下一个面板就会出现在工具栏中(请参见图49 )。

图49 -SFC图表编辑面板

按钮外观按钮名称按钮功能:

调用开始按钮创建一个新的初始步骤;根据IEC61131-3,SFC图表上必须有一个初始化步骤,该步骤可表征SFC图表的初始状态。

调用步骤编辑对话框 创建新步骤;根据需求编辑对话框,勾选三种连接器:输入、输出、动作,前面的勾号。

调用条件转移编辑对话框 创建一个新的转换/跃迁;根据需求编辑转换对话框,选择转换类型{参照/引用:预定义转换;在线:ST语言代码;连接:BOOL输入型左触点连接器}及其优先级。ST语言实例:(IncStep=9)&(NOT OddPeriod)

调用动作块编辑对话框 创建一个新的动作块;根据需求编辑动作块对话框,动作块、动作、动作属性{”限定符”、“持续时间”、“类型{动作、变量、在线}”、“值”、“指示器”}接下来,本篇文章侧重说明其中的  “动作/行动块”

调用发散和收敛按钮 创建一个新“选一或同步”分支/收敛;根据需求编辑分支对话框,选择分支类型{“选一发散”、“选一收敛”、“并行发散”、“并行收敛”} 和 分支数量选一分支发散线输出端,必须与“转换”直链;并行分支收敛线输入端,必须与“转换”直链;

调用无条件跳转按钮 创建一个新的无条件“跳转”调用;根据IEC61131-3,必须在步和跳之间定义“转换”

 

一、行动块、动作、动作属性概述

1、动作/块的执行:当一个步被活动(激活),动作块中的所有动作根据动作限定符的条件设定执行。当一个步在活动状态,动作块中的每个动作每周期执行一次。
动作块包括:一组动作。 您可以通过单击“添加” 按钮并设置必要的参数,来添加新动作:

  • “限定符”; 即合格验证,动作限定符;这个非常重要
  • “持续时间”;
  • “类型”:“动作”,“变量”,“在线”;
  • “值”;
  • “指示器”

 

 

 

二、动作(顺序)限定

IEC编程,SFC关联 动作限制符: N、R、S、L、D、P、P0、P1、SD、DS、SL含义与区别

AQ /动作限定符为每个动作定义运行时序;它能决定当步活动时动作如何执行;每个动作只可指定一个 AQ。
动作类型决定了当步变为非活动状态时输出是保持还是复位。需要时,改变初始设置或向程序中添加复位过程。

• 对于位,如果保持动作限定符(S)未被指定,输出将复位;如果保持动作限定符(S)已指定,输出将保持。
• 对于梯形图程序,输出默认复位,默认设置可变为保持输出状态。
• 对于 ST 程序,默认输出状态保持,必要时,在程序中写入复位过程并使用动作标志(当 ST 程序中对应步变为非活动时,该标志变为 ON)来控制复位过程。

 

 

SFC语言编辑器动作限定符

动作限定符

 动作限定词名称(合格验证) 定时器设置 功能  动作块行为 注释
N

 普通(默认)

非存储的

动作执行跟步活动时间一样长  该步骤处于活动状态时执行该动作  
R  重写复位  / 

当步变为活动,且他的动作是由“S、SL、SD或DS”限定符,指定动作停止并复位。
如果动作正在执行,但不是由“S、SL、SD或DS”限定符执行,动作只是复位(不停止)。
复位操作设置如下: OUT/OUT NOT指令: “OFF”,TIM/TIMH 指令:“复位”;其它定时器/计数器/转换寄存器:“保持”

 禁用图表后将执行该动作  
S  置位(存储)  /  步活动时动作执行,即使步变成非活动也持续执行,要取消执行,使用R限定符    
P  脉冲Pulse  / 

是若最终扫描功能使能,当步活动时动作执行2个扫描周期。
若最终 扫描功能非使能,当步活动时,动作执行1个周期。

   
P0  下降沿脉冲  /   每当步变为非活动时动作执行一次    
P1  上升沿脉冲  /  每当步变为活动时动作执行一次。    
如下:时间限定,它们都是需要一个以Time恒定格式的时间值。 e.g.  T#10ms
D 延时执行Delay 从步活动开始, 过去用户指定时间后动作执行。如果在用户指定时间到期之前步变为非活动,动作将不执行。 动作经过一定的时间后成为活动的(如果步依旧活动的话),然后只要是步是活动的,动作也保持活动 该动作将在特定的指定时间后开始执行(如果该步骤仍处于活动状态), 并且只要此步骤处于活动状态就将执行
L 限时执行Limit  是


当步活动后, 动作执行直到用户指定时间到达。如果步变为非活动,动作执行将终止。

动作在一定时间内是活动的,最长持续时间赞同于步的活动的时间 在某个预定时间间隔内执行该动作,此后该动作停止
SD 置位和延时Set&Delay  是 步活动后直到用户指定时间到达,动作开始执行,即使步变成非活动也持续执行,要取消执行,使用R限定符 动作一定时间后是活动的,并一直保持活动直到收到一个'复位命令'。 即使该步骤不再处于活动状态,该动作也会在一段时间后开始执行。
DS 延时和置位Delay&Set  是

执行时类似"SD"。同SD不同,如果步在用户指定延迟时间到期之前变为非活动,动作将不操作。要取消执行,使用R限定符。

动作在一定时间后是活动的,此后只要步是活动的,动作也保持活动的,直到收到一个'复位'命令。

仅在该步骤仍处于活动状态时,该动作才会在特定的指定时间后开始执行。

SL 置位和限时Set&Limit  是 步活动时动作执行,直到用户指定时间到期。与“L”不同的是,即使步变成非活动也持续执行,要取消执行,使用R限定符。  存储和时间限制    动作在一定时间内是活动的 该动作在指定的时间间隔内处于活动状态

 

D,DS,L控制动作执行的时序,使用步定时器,时间单位与动作块被分配的步的定时器一致。
SD和SL用与步定时器不同的定时器控制时间,因为他们操作独立于步状态。
如果动作限定符设置为“N”,梯形图程序将不能正确检测步的上升沿激活状态。
因此,如果一个过程根据步的激活状态只执行一次,需要使用“P1”动作限定符。

 

 

                           图1 各限定动作执行时序图

 

 

三、动作持续时间

只有“动作限定”为 D、L、DS、SD、SL这个属性才有意义。

通常使用格式: T#3s  、 T#100ms

 

四、动作类型”:“动作”,“变量”,“在线”

“类型”定义将在动作激活期间执行的代码或特定动作。

4.1 动作/行动

行动/动作,是Function Block“功能块”右键菜单中创建。 动作/行动块,添加动作,类型选择为"行动",就可以引用

SFC选择“动作”的情况下,与转换的情况相同,可以使用SFC语言编写的该POU在项目树中使用预定的动作。

 

 

 

4.2 变量

变量,是在编辑区上方的,变量添加区创建。动作/行动块,添加动作,类型选择为"变量",就可以引用

(步骤激活后,根据变量的类型, 此变量将采用值0、0.0,FALSE和其他类型的空值。
动作开始执行后,变量将采用值1、1.0,TRUE和其他类型的单位值。

如果动作停止执行,则变量将再次采用值0、0.0,FALSE和另一个零值,具体看其类型。

 

 

 

 

4.3 在线

在线指ST代码。

 动作/行动块,添加动作,类型选择为"在线",则可以在“值”上转换为以ST语言编写为将在动作导向的状态下执行的代码: var := var + 1;

注意,与用于"转换"的内置代码相反,在使用动作的内置代码末尾, 您需要添加分号“;”

五、Beremiz生成C代码解析

5.1  PLC_APP 逻辑程序块

 
结构层次

1.程序入口

(操作系统适配)

2.plc默认变量 init 3.项目配置(用户定义)变量 init 4.资源(触发器/POU实例)初始化与运行 程序POU 功能块POU
动作            

Beremiz界面

数据对象

      资源选项卡:
1、任务,指两种触发器 ”循环定时器/中断 “
2、实例,指"程序POU"对象

项目选项卡:

1.配置变量,指所有程序的外部变量

 
源文件 plc_app_dyplc.c plc_main.c config.c

Resource1.c

...

Resource.c

POUS.C  
A-数据初始化 startPLC

plc_app_abi_t plc_dyplc_app 

{
.start = startPLC,

}

__init config_init__

RESOURCE1_init__

...

RESOURCEx_init__ 

AI_init__  
 函数实现  

int startPLC(int argc,char **argv)
{
if(__init(argc,argv) == 0){
PLC_SetTimer(0, common_ticktime__);
return 0;
}else{
return 1;
}
}

 int __init(int argc,char **argv)

{
int res = 0;
init_level = 0;

/* Effective tick time with 1ms default value */
if(!common_ticktime__)
common_ticktime__ = 1000000;

config_init__();
__init_debug();
init_level=1; if((res = __init_py_ext(argc,argv))){return res;}
return res;
}

 

void config_init__(void) {
BOOL retain;
retain = 0;
__INIT_GLOBAL_LOCATED(CONFIG,DI0,__IX1_0,retain)
__INIT_GLOBAL(BOOL,DI0,__INITIAL_VALUE(__BOOL_LITERAL(FALSE)),retain)
__INIT_GLOBAL_LOCATED(CONFIG,DI1,__IX1_1,retain)

...
RESOURCE1_init__();
}

 void RESOURCE1_init__(void) {
BOOL retain;
retain = 0;

TIMER0 = __BOOL_LITERAL(FALSE);
TIMER1 = __BOOL_LITERAL(FALSE);
MODBUS_init__(&PER4,retain);
AI_init__(&PER6,retain);
AO_init__(&PER5,retain);
POINT_init__(&PER0,retain);
}
   
 B-线程运行

 runPLC

plc_app_abi_t plc_dyplc_app 

{
.run   = runPLC,

}

 __run 

 

 config_run__  

RESOURCE1_run__
...
RESOURCEx_run__

 AI_body__  
 函数实现  

void runPLC(void)
{
PLC_GetTime( &__CURRENT_TIME );
__run();
}

void __run(void)
{
__tick++;
if (greatest_tick_count__)
__tick %= greatest_tick_count__;

__retrieve_py_ext();

/*__retrieve_debug();*/

config_run__(__tick);

__publish_debug();

__publish_py_ext();

}

 

void config_run__(unsigned long tick) {
RESOURCE1_run__(tick);
}

 

void RESOURCE1_run__(unsigned long tick) {
TIMER0 = !(tick % 200);
TIMER1 = !(tick % 1);
if (TIMER0) {
MODBUS_body__(&PER4);
}
if (TIMER0) {
AI_body__(&PER6);
}
if (TIMER0) {
AO_body__(&PER5);
}
if (TIMER1) {
POINT_body__(&PER0);
}
}

 

   
 C-工具函数

void PLC_GetTime(...);

void PLC_SetTimer(...);

int startPLC(int argc,char **argv)

int stopPLC();

//void runPLC(void)

         

 

5.2  PLC_RTE 线程运行时

// plc_main_rte.c :: plc_rts_task
while (1)
{
    //printf("[%s:%d] tick:%d\n",__FUNCTION__, __LINE__, HAL_GetTick());
    dbg_handler();

    if(plc_state == PLC_STATE_STARTED)
    {
        plc_curr_rte->get_input();     // plc_get_input()::plc_main_rte.c
        plc_iom_get();                 // plc_iom.c::plc_iom_get() -> plc_hw.c::plc_dio_get()
        
        if((g_u64timer - before_iec) >= g_u64tick_period)
        {
            plc_curr_app->run();        // plc_app_dyplc.c :: runPLC()
            before_iec = g_u64timer;
        }

        plc_iom_set();                //plc_iom.c::plc_iom_set() -> plc_hw.c::plc_dio_set()
        plc_curr_rte->set_output();   //plc_set_output()::plc_main_rte.c
    }
}

线程入口初始化:

 

 

       
 线程函数入口 plc_rts_task () plc_main_rte.c   
  dbg_init();

plc_timer_init();
plc_iom_init(); plc_hw.c
plc_iom_test_hw();

   
 

plc_load_rte();
plc_curr_rte->init_dio();

   
 

plc_load_app();

plc_app_start();

   

线程主循环体:

       
读IO输入
plc_curr_rte->get_input();     
 // plc_main_rte.c::plc_get_input()  

通过PLC位置定义“%IX0.0”,实现读入区I-RAM 与 PLC变量名关联

(粉红色数字,为内存偏移量

plc_iom_get();                 
 // plc_iom.c::plc_iom_get() -> plc_hw.c::plc_dio_get()  
 
if((g_u64timer - before_iec) >= g_u64tick_period)
{
    plc_curr_app->run();        
    before_iec = g_u64timer;
}
 // plc_app_dyplc.c :: runPLC()  

 通过PLC位置定义“%QX0.0”,实现输出区Q-RAM 与 PLC变量名关联

(粉红色数字,为内存偏移量

plc_iom_set();             

 // plc_iom.c::plc_iom_set() -> plc_hw.c::plc_dio_set()

 
写IO输出
plc_curr_rte->set_output();  
// plc_main_rte.c ::plc_set_output()  

  

5.1 项目·配置选项卡

 

1. 配置变量(Config variables)  : 硬件 I/O 引脚分配、全局变量预定义。例如:%IX1.1,%MB2.   I/Q/M :输入/输出/内存,X/B:位:字节。详见:IEC61131-3可编程语言标准中文版.pdf, 变量位置定义。

2.项目属性

3.配置

 

5.2 资源·config.resource1配置选项卡

资源主要是,把硬件定时器程序绑定生成任务实例
定时器分类:循环Cyclic、中断Interrupt两种。

 

5.3  程序·Program程序POU

 

 

 

 

 

5.4  功能块·FuctionBlock功能块POU

 

5.5 添加变量打印,方便调试

第一步、新建结构化语言POU:功能块 : ST:FB_Printf

 

 内部添加如下C语言代码:

{{    
//__SET_VAR(data__->TRANSPORTCMD1.,BCR_RACKNO,,__GET_EXTERNAL(data__->BCR_RACKNO,));
  // __SET_EXTERNAL(data__->,J2_ADDR,,__GET_VAR(data__->TRANSPORTCMD1.J2_ADDR,)); //获取局部变量:__GET_VAR(data__->ASPPOS,)
uint8_t done
= __GET_EXTERNAL(data__->A1_D1,); //GetFbVar(DONE);
printf("[%s:%d] (A1Init) tick:%d\n",__FUNCTION__, __LINE__, done); // HAL_GetTick()); SetFbVar(DONE,done); }}

第二步、在功能块:SFC:xxxx下,添加“行动”

uint16_t j1_addr = __GET_EXTERNAL(data__->J1_ADDR,);
    if(0!=j1_addr)
printf("####[%s:%d] J1_ADDR:%d####\n",__FUNCTION__, __LINE__, j1_addr);

 

第三步、SFC顺序功能流程图中,行动块中调用此“打印行动”

 

posted @ 2022-12-17 17:07  suntroop  阅读(1938)  评论(1)    收藏  举报