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顺序功能流程图中,行动块中调用此“打印行动”