Reorganizacion de libreria.

This commit is contained in:
2026-07-20 08:15:06 +02:00
parent e0b9f4a206
commit 2b9dbc1f27
280 changed files with 9799 additions and 9398 deletions
@@ -0,0 +1,549 @@
FUNCTION_BLOCK "FB15148_ZC_SEC_MB_CLIENT"
TITLE = FB15148_ZC_SEC_MB_CLIENT
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
VAR_INPUT
Habilitar : Bool := FALSE; // Habilitacion General
Iniciar : Bool; // Iniciar secuencia
Ack : Bool; // Acuse general para resetear la secuencia
Pulso1Seg : Bool; // Pulso de 1 segundo
AutoDesconexion : Bool; // 0= Deshabilitada / 1= Habilitada
Numero : Int; // Numero total de bloques
DONE { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
BUSY { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
ERROR { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
STATUS { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Word;
END_VAR
VAR_OUTPUT
Finalizado : Bool; // Secuencia finalizada
EnEjecuccion : Bool; // Secuencia en ejecucion
AlgunError { ExternalWritable := 'False'} : Bool := FALSE; // Algun error
ErrorEnBloque { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..8] of Bool := [8(FALSE)];
REQ { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
DISCONNECT { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
END_VAR
VAR RETAIN
s_Etapa : Int := #ETAPA_0_REPOSO;
END_VAR
VAR
s_AlgunError { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool := FALSE;
s_NumeroActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
s_SP_TiempoEsperaBusy : Int := 20;
s_TiempoEsperaBusy : Int;
s_Error : Array[1..8] of Bool := [8(FALSE)];
END_VAR
VAR RETAIN
s_NumeroError : Array[1..8] of UInt;
s_NumeroDone : Array[1..8] of UInt;
END_VAR
VAR_TEMP
for_i : Int;
END_VAR
VAR CONSTANT
ETAPA_0_REPOSO : Int := 0;
ETAPA_10_PROCESANDO_1 : Int := 10;
ETAPA_20_PROCESANDO_2 : Int := 20;
ETAPA_30_PROCESANDO_3 : Int := 30;
ETAPA_40_PROCESANDO_4 : Int := 40;
ETAPA_50_PROCESANDO_5 : Int := 50;
ETAPA_60_PROCESANDO_6 : Int := 60;
ETAPA_70_PROCESANDO_7 : Int := 70;
ETAPA_80_PROCESANDO_8 : Int := 80;
END_VAR
BEGIN
(*
ZEUS CONTROL, S.A.
(c)Copyright (2025) All Rights Reserved
--------------------------------------------------------------------------------------
Software: TIA Portal 18
Restricciones: PLC serie 1200/1500
Nombre: FB15148_ZC_SEC_MB_CLIENT
Descripcion: Bloque de funcion para gestion de comunicaciones secuenciales MODBUS.
Dependencias:
FC: -
FB: -
DB: -
UDT: -
Change log:
Version Fecha Tecnico a cargo Descripcion
01.00.00    04.07.2025  (ABH)   Primera version
//=====================================================================================
*)
REGION LIMITES
#s_NumeroActual := #Numero;
IF #s_NumeroActual > 8 THEN
#s_NumeroActual := 8;
END_IF;
IF #s_NumeroActual < 1 THEN
#s_NumeroActual := 1;
END_IF;
END_REGION
REGION ORDEN_DE_INICIO
IF NOT #Habilitar OR #Ack THEN
#s_AlgunError := FALSE;
FOR #for_i := 1 TO 8 DO
#REQ[#for_i] := FALSE;
#DISCONNECT[#for_i] := TRUE;
#s_Error[#for_i] := FALSE;
#s_NumeroDone[#for_i] := 0;
#s_NumeroError[#for_i] := 0;
END_FOR;
#s_Etapa := #ETAPA_0_REPOSO;
END_IF;
IF #Habilitar AND #s_Etapa = 0 AND #s_NumeroActual > 0 AND #Iniciar THEN
#s_AlgunError := FALSE;
#s_Etapa := #ETAPA_10_PROCESANDO_1;
// Reinicializamos las variables REQ y ERROR
FOR #for_i := 1 TO 8 DO
#REQ[#for_i] := FALSE;
#s_Error[#for_i] := FALSE;
IF #AutoDesconexion THEN
#DISCONNECT[#for_i] := TRUE;
END_IF;
END_FOR;
END_IF;
END_REGION
REGION SECUENCIA
CASE #s_Etapa OF
#ETAPA_0_REPOSO:
;
#ETAPA_10_PROCESANDO_1:
REGION MB_CLIENT_1
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[1] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 0 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[1] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[1] THEN
// Quitamos la peticion
#REQ[1] := FALSE;
#s_NumeroDone[1] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_20_PROCESANDO_2;
// En caso de error mostramos informacion
ELSIF #ERROR[1] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[1] := TRUE;
#REQ[1] := FALSE;
#s_NumeroError[1] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_20_PROCESANDO_2;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[1] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_20_PROCESANDO_2:
REGION MB_CLIENT_2
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[2] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 1 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[2] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[2] THEN
// Quitamos la peticion
#REQ[2] := FALSE;
#s_NumeroDone[2] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_30_PROCESANDO_3;
// En caso de error mostramos informacion
ELSIF #ERROR[2] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[2] := TRUE;
#REQ[2] := FALSE;
#s_NumeroError[2] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_30_PROCESANDO_3;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[2] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_30_PROCESANDO_3:
REGION MB_CLIENT_3
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[3] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 2 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[3] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[3] THEN
// Quitamos la peticion
#REQ[3] := FALSE;
#s_NumeroDone[3] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_40_PROCESANDO_4;
// En caso de error mostramos informacion
ELSIF #ERROR[3] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[3] := TRUE;
#REQ[3] := FALSE;
#s_NumeroError[3] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_40_PROCESANDO_4;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[3] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_40_PROCESANDO_4:
REGION MB_CLIENT_4
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[4] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 3 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[4] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[4] THEN
// Quitamos la peticion
#REQ[4] := FALSE;
#s_NumeroDone[4] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_50_PROCESANDO_5;
// En caso de error mostramos informacion
ELSIF #ERROR[4] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[4] := TRUE;
#REQ[4] := FALSE;
#s_NumeroError[4] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_50_PROCESANDO_5;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[4] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_50_PROCESANDO_5:
REGION MB_CLIENT_5
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[5] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 4 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[5] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[5] THEN
// Quitamos la peticion
#REQ[5] := FALSE;
#s_NumeroDone[5] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_60_PROCESANDO_6;
// En caso de error mostramos informacion
ELSIF #ERROR[5] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[5] := TRUE;
#REQ[5] := FALSE;
#s_NumeroError[5] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_60_PROCESANDO_6;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[5] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_60_PROCESANDO_6:
REGION MB_CLIENT_6
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[6] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 5 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[6] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[6] THEN
// Quitamos la peticion
#REQ[6] := FALSE;
#s_NumeroDone[6] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_70_PROCESANDO_7;
// En caso de error mostramos informacion
ELSIF #ERROR[6] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[6] := TRUE;
#REQ[6] := FALSE;
#s_NumeroError[6] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_70_PROCESANDO_7;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[6] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_70_PROCESANDO_7:
REGION MB_CLIENT_7
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[7] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 6 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[7] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[7] THEN
// Quitamos la peticion
#REQ[7] := FALSE;
#s_NumeroDone[7] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_80_PROCESANDO_8;
// En caso de error mostramos informacion
ELSIF #ERROR[7] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[7] := TRUE;
#REQ[7] := FALSE;
#s_NumeroError[7] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_80_PROCESANDO_8;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[7] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_80_PROCESANDO_8:
REGION MB_CLIENT_8
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[8] := FALSE;
// Lanzamos la orden del GET
#REQ[8] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[8] THEN
// Quitamos la peticion
#REQ[8] := FALSE;
#s_NumeroDone[8] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_0_REPOSO;
// En caso de error mostramos informacion
ELSIF #ERROR[8] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[8] := TRUE;
#REQ[8] := FALSE;
#s_NumeroError[8] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_0_REPOSO;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[8] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_REGION
ELSE
#s_Etapa := #ETAPA_0_REPOSO;
END_CASE;
END_REGION
REGION SALIDAS
#Finalizado := #s_Etapa = 0;
#EnEjecuccion := #s_Etapa <> 0;
// Gestion señales de salida de bloque
#s_AlgunError := FALSE;
FOR #for_i := 1 TO 8 DO
#ErrorEnBloque[#for_i] := #s_Error[#for_i];
IF #s_Error[#for_i] THEN
#s_AlgunError := TRUE;
END_IF;
END_FOR;
#AlgunError := #s_AlgunError;
END_REGION
END_FUNCTION_BLOCK
@@ -0,0 +1,274 @@
FUNCTION_BLOCK "FB15150_ZC_SEC_S7COM"
TITLE = FB15150_ZC_SEC_GET
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//ZEUS CONTROL, S.A.
//(c)Copyright (2023) All Rights Reserved
//--------------------------------------------------------------------------------------
//
//Software: TIA Portal 16
//Restricciones: PLC serie 1200/1500
//
//Nombre: FB15150_ZC_SEC_GET
//Descripcion: Bloque de funcion para gestion de comunicaciones secuenciales GET.
//
//Dependencias:
// FC: -
// FB: -
// DB: -
// UDT: -
//
//
//Change log:
//
// Version Fecha Tecnico a cargo Descripcion
//
// 01.00.00    24.05.2023  (ABH)   Primera version
// 01.00.01 21.09.2023 (ABH) Cambio a SCL.
//
////=====================================================================================
VAR_INPUT
Habilitar : Bool := FALSE; // Habilitacion General
Iniciar : Bool; // Iniciar secuencia
Ack : Bool; // Acuse general para resetear la secuencia
Pulso1Seg : Bool; // Pulso 1 segundo
NumeroBloques { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Int := 1; // Numero de bloques de comunicacion en la secuencia
TiempoEspera { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Int := 10; // Tiempo espera estado bloque comunicacion
NDR_DONE : Array[1..#N_MAX] of Bool;
ERROR : Array[1..#N_MAX] of Bool;
END_VAR
VAR_OUTPUT
Finalizado : Bool; // Secuencia finalizada
EnEjecuccion : Bool; // Secuencia en ejecucion
AlgunError { ExternalWritable := 'False'} : Bool := FALSE; // Algun error
EnError { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..#N_MAX] of Bool := [8(FALSE)];
REQ { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..#N_MAX] of Bool;
END_VAR
VAR RETAIN
s_Etapa { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int := #REPOSO; // Etapa actual
END_VAR
VAR
s_IndiceActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Indice actual del bloque de comunicacion en ejecuccion
s_AlgunError { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool := FALSE; // Indicador de algun error
s_NumeroBloques { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Numero de bloques
END_VAR
VAR RETAIN
s_TiempoEsperaActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Tiempo de espera actual
END_VAR
VAR
s_Error { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..#N_MAX] of Bool := [8(FALSE)];
END_VAR
VAR RETAIN
s_NumeroError { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..#N_MAX] of UInt;
s_NumeroDone { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..#N_MAX] of UInt;
END_VAR
VAR_TEMP
for_i : Int;
END_VAR
VAR CONSTANT
REPOSO : Int := 0; // Etapa reposo
PROCESANDO : Int := 10; // Etapa procesando
N_MAX : Int := 8; // Numero maximo de bloques de comunicacion
END_VAR
BEGIN
REGION DESCRIPCION
//=======================================================================
// (C)Copyright ZeusControl 2024 - 2026
//=======================================================================
(*
### Información del Sistema
| Hardware Compatible | Entorno de Ingeniería |
|---------------------|-----------------------|
| PLC serie 1200/1500 | TIA Portal 18 |
---
### Descripción Funcional
El bloque `FB15150_ZC_SEC_S7COM` implementa un gestor de comunicaciones secuenciales S7 (PUT/GET) que ejecuta, de forma ordenada y con gestión de errores, una secuencia de peticiones a otros tantos bloques de comunicación. Garantiza que las operaciones se lancen una a una, esperando a la finalización de cada una (correcta o con error) antes de continuar con la siguiente, y permite acotar el tiempo de espera por petición para detectar bloqueos de la comunicación.
Funcionalidades principales:
- Habilitación y Ack: cuando el bloque se deshabilita (`#Habilitar := FALSE`) o se activa la entrada de acuse `#Ack`, se reinicializan todas las variables internas y de salida, se vacían los flags de error, se resetea la etapa a `REPOSO` y se sale del bloque mediante `RETURN`.
- Límite de dimensionamiento: se valida `#NumeroBloques` contra la constante de dimensionamiento `#N_MAX`, acotando el valor entre 1 y `#N_MAX`.
- Arranque ordenado: cuando se recibe la entrada `#Iniciar` estando en `REPOSO`, se inicializa el índice de proceso, se limpian las peticiones y los flags de error, y se transita a la etapa `PROCESANDO`.
- Procesamiento secuencial: para cada bloque actual, se lanza la activación de `#REQ` y se monitorizan las señales de fin `#NDR_DONE` y `#ERROR`. Se avanza al siguiente bloque tanto en caso de éxito como de error.
- Control de tiempo de espera: si la petición actual no finaliza antes de cumplir `#TiempoEspera` (incrementado con `#Pulso1Seg`), se da por fallida y se avanza al siguiente bloque, contabilizándolo como error.
- Salidas de estado: `#EnEjecuccion` indica que la secuencia está en curso (`#s_Etapa <> REPOSO`) y `#Finalizado` indica que la secuencia ha concluido. Por cada bloque se expone `#EnError` y un `#AlgunError` global que se activa si cualquier petición ha fallado.
> **Restricciones:** Ninguna.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 00.00.01 | 24.05.2023 | (ABH) | Primera versión. |
| 00.00.02 | 21.09.2023 | (ABH) | Cambio a SCL. |
| 00.00.03 | 24.08.2025 | (ABH) | Se añade tiempo de espera para dar como error. |
| 01.00.00 | 02.07.2026 | (ABH) | Refactorización de lógica para estandarización. Se añade constante de dimensionamiento. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION HABILITACION
// En caso de no estar habilitado el bloque o pulsar el boton ACK, reinicializamos valores y salimos inmediatamente
IF NOT #Habilitar OR #Ack THEN
#s_AlgunError := FALSE;
FOR #for_i := 1 TO #N_MAX DO
#REQ[#for_i] := FALSE;
#s_Error[#for_i] := FALSE;
#s_NumeroDone[#for_i] := 0;
#s_NumeroError[#for_i] := 0;
#EnError[#for_i] := FALSE;
END_FOR;
#s_Etapa := #REPOSO;
#s_TiempoEsperaActual := 0;
#s_IndiceActual := 1;
#Finalizado := FALSE;
#EnEjecuccion := FALSE;
#AlgunError := FALSE;
RETURN;
END_IF;
END_REGION HABILITACION
// ==========================================================================================================
REGION LIMITES
// Traspaso de numero de bloques a variable interna
#s_NumeroBloques := #NumeroBloques;
// Limite de bloques
IF #s_NumeroBloques > #N_MAX THEN
#s_NumeroBloques := #N_MAX;
ELSIF #s_NumeroBloques < 1 THEN
#s_NumeroBloques := 1;
END_IF;
END_REGION LIMITES
// ==========================================================================================================
REGION ORDEN_DE_INICIO
IF #Habilitar AND #s_Etapa = #REPOSO AND #Iniciar THEN
#s_AlgunError := FALSE;
#s_Etapa := #PROCESANDO;
#s_IndiceActual := 1; // Apuntamos al primer BLOQUE
// Reinicializamos las variables REQ y ERROR antes de empezar
FOR #for_i := 1 TO #N_MAX DO
#REQ[#for_i] := FALSE;
#s_Error[#for_i] := FALSE;
END_FOR;
#s_TiempoEsperaActual := 0;
END_IF;
END_REGION ORDEN_DE_INICIO
// ==========================================================================================================
REGION SECUENCIA
CASE #s_Etapa OF
#REPOSO:
; // Esperando orden de inicio
#PROCESANDO:
// Verificacion de final de la secuencia
IF #s_IndiceActual > #s_NumeroBloques THEN
// Si hemos procesado todos los bloques, finalizamos la secuencia
#s_Etapa := #REPOSO;
RETURN;
END_IF;
// Procesamos
REGION GESTION_COMUNICACIONES
// Lanzamos orden request para el bloque de comunicaciones
#REQ[#s_IndiceActual] := TRUE;
// Esperamos a que finalice correctamente el bloque de comunicaciones
IF #NDR_DONE[#s_IndiceActual] THEN
#REQ[#s_IndiceActual] := FALSE;
#s_NumeroDone[#s_IndiceActual] += 1;
#s_TiempoEsperaActual := 0;
// Avanzamos al siguiente bloque de comunicaciones
#s_IndiceActual += 1;
// En caso de error o Timeout
ELSIF #ERROR[#s_IndiceActual] OR #s_TiempoEsperaActual >= #TiempoEspera THEN
#s_Error[#s_IndiceActual] := TRUE;
#REQ[#s_IndiceActual] := FALSE;
#s_NumeroError[#s_IndiceActual] += 1;
#s_TiempoEsperaActual := 0;
// Avanzamos al siguiente bloque de comunicaciones
#s_IndiceActual += 1;
END_IF;
// Contador de tiempo de Timeout
IF #Pulso1Seg THEN
#s_TiempoEsperaActual += 1;
END_IF;
END_REGION GESTION_COMUNICACIONES
ELSE
#s_Etapa := #REPOSO;
END_CASE;
END_REGION SECUENCIA
// ==========================================================================================================
REGION SALIDAS
#Finalizado := (#s_Etapa = #REPOSO);
#EnEjecuccion := (#s_Etapa <> #REPOSO);
// Gestion señales de salida de bloque
#s_AlgunError := FALSE;
FOR #for_i := 1 TO #N_MAX DO
#EnError[#for_i] := #s_Error[#for_i];
IF #s_Error[#for_i] THEN
#s_AlgunError := TRUE;
END_IF;
END_FOR;
#AlgunError := #s_AlgunError;
END_REGION SALIDAS
END_FUNCTION_BLOCK