Domina los punteros con formato ANY

Una forma de leer y copiar información dinámica es realizarlo mediante punteros con formato ANY.

Lo que vamos a ver es por un lado cómo se crean a mano los punteros, y luego darle una aplicación práctica.

Pero antes de eso, tenemos que ver un poco (o refrescar) qué es el formato ANY.

Según la documantación de Siemens,  [..] se utiliza cuando el tipo de datos del parámetro actual no se conoce o cuando se  puede utilizar cualquier tipo de datos. [..]

STEP 7 almacena los datos del tipo de parámetro ANY en 10 bytes. Al estructurar un parámetro del tipo ANY, los 10 bytes deben quedar ocupados, ya que el bloque llamado evalúa todo el contenido del parámetro. Si, por ejemplo, especifica un número de DB en el byte 4, deberá indicar también explícitamente el área de la memoria en el byte 6.
STEP 7 gestiona los datos de los tipos de datos simples y compuestos de forma diferente a la de los tipos de parámetros.[..]

¿A que ahora ya te has quedado más tranquilo?

Bueno, pues en cristiano, lo que quiere venir a decir es que con un ANY lo que defines es un área de la memoria (marcas, entradas, db..) y defines la longitud de ese área.  Además, el puntero con formato ANY tiene obligatoriamente 10 bytes de longitud y tienes que rellenar los 10 bytes sean necesarios o no. Así por ejemplo, puedes definir el área definido en un DB en concreto y que sea de un ancho de 24 bytes… por poner un ejemplo.

¿Cómo creamos un puntero con formato ANY?

Bueno, vayamos por partes para entenderlo bien. En la siguiente figura tienes un resumen de cómo hay que rellenar los 10 bytes que forman un ANY en el caso de los tipos de datos simples y compuestos.Formato Any

Vayamos por tanto a repasar cada byte:

Byte 0: Hay que cargar siempre un 10H. Una constante que le sirve a Step 7 para indicar que es un ANY.

Byte 1: Tipo de datos .

Formato Any

 

Tendrás que cargar en hexadecimal en el byte 1 el número según la tabla para indicar qué tipo de datos quieres usar.

Word 2 (Byte 2 y 3): Factor de repetición, es decir, la cantidad de items

Word 4 (Byte 4 y 5): número de DB. Si no es de un DB el área de memoria, pones un bonito 0.

Byte 6: Área de memoria. Es decir, el tipo. Lo indicamos en la siguiente tabla:

Formato Any

 

Byte 7, 8 y 9: La dirección se almacena en formato byte.bit. La dirección de byte se deposita en los bits 0 a 2 del byte 7, en los bits 0 a 7 del byte 8 y en los bits 3 a 7 del byte 9, mientras que la dirección de bit se deposita en los bits 0 a 2 del byte 9.
En el puntero nulo del tipo de datos NIL, todos los bytes estarán ocupados con 0 a partir del byte 1.

Pero también se puede crear un puntero ANY  con informacion sobre un temporizador, contador o bloque.  Es parecido pero no es del todo igual. Veámoslo.

Formato ANY en los tipos de parámetros

En el caso de los tipos de parámetros, STEP 7 almacena el tipo de datos y la dirección de los parámetros. El factor de repetición es siempre 1. Los bytes 4, 5 y 7 son siempre 0. Los bytes 8 y 9 indican el número del temporizador, del contador o del bloque.

ANY

La tabla siguiente muestra la codificación de los tipos de datos para el formato ANY en el caso de los tipos de parámetros.

ANY

¿Y para qué usamos un puntero con formato ANY?

Bueno, pues después de todo este rollo (que está bien saber por otro lado) vamos a ver si podemos darle una utilidad.

Lo que nos va a permitir esto es poder leer áreas de los diferentes tipos de memoria y poder escribirla en otro área de memoria de forma dinámica.

¿Una aplicación práctica para esto?

Pues por ejemplo, en los hornos de curvar parabrisas con los que trabajo, la información de la pauta hay que volcarla en diferentes momentos sobre la zona donde se está curvando. Es decir, en cada zona del horno, se lee la información de potencias de esa potencia para un determinado cajón el cual va cambiando. Es decir, tienes una zona que es dinámica y un carro que es dinámico.

Como ves, aunque no lo vayas a aplicar todos los días, es bastante útil cuando toca.

Copiar áreas de memoria usando los puntero con formato ANY

Como ejemplo vamos a analizar un bloque para copiar dos áreas de memoria. De un DB a otro DB.

Te dejo la fuente AWL  comentada para su mejor entendimiento y estudio:

FUNCTION “Copiar areas MB–>DB” : VOID
TITLE =TRANSFER MB -> DB
VERSION : 0.0
VAR_INPUT
MBSOURCE : INT ; //DB ORIGEN
DBTARGET : INT ; //DB DESTINO
DBWTARGET : INT ; //DBW DESTINO
NBBYTE : INT ; //NUMBERO DE BYTES A TRANSFERIREND_VAR
VAR_TEMP
SOURCE : ANY ; //ANY ORIGEN
TARGET : ANY ; //ANY DESTINO
RET : INT ; //TEMPÒRAL RETURN
END_VAR
BEGIN
NETWORK
TITLE =COMPUTE ANY POINTER FOR SOURCE

LAR1 P##SOURCE; // CARGAMOS EN EL AR1 LA DIRECCION DEL ORIGEN
L B#16#10; // SYNTAXIS PARA S7 (SIEMPRE ES IGUAL)
T LB [AR1,P#0.0]; // -> SE LO CARGAMOS AL ANY EN SU BYTE 0

L B#16#2; // CARGAMOS EL TIPO DE DATO: BYTE
T LB [AR1,P#1.0]; // -> SE LO CARGAMOS AL ANY EN SU BYTE 1

L #NBBYTE; // NUMBERO DE BYTES A TRANSFERIR
T LW [AR1,P#2.0]; // -> SE LO CARGAMOS AL ANY EN SU WORD 2

L 0; // COMO NO ES UN DB, CARGAMOS UN CERO
T LW [AR1,P#4.0]; // -> SE LO TRANSFERIMOS AL ANY EN EL WORD 4

L B#16#83; // CODIGO DE TIPO DE MEMORIA PARA MB
T LB [AR1,P#6.0]; // -> SE LO TRANSFERIMOS AL ANY EN SU BYTE 6

L B#16#0; // LA DIRECCION DE LOS 3 BITS SUPERIORES
T LB [AR1,P#7.0]; // -> SE LO TRANSFERIMOS AL ANY EN SU BYTE 7

L #MBSOURCE; // LEEMOS EL NÚMRO DE MB ORIGEN
SLW 3; // DESPLAZAMOS 3 POSICIONES A LA IZQUIERDA
T LW [AR1,P#8.0]; // -> SE LO TRANSFERIMOS AL ANY EN SU WORD 8
NETWORK
TITLE =COMPUTE ANY POINTER FOR TARGET

LAR1 P##TARGET; // CARGAMOS EL DESTINO EN EL AR1

L B#16#10; // SYNTAXIS PARA S7 (SIEMPRE ES IGUAL)
T LB [AR1,P#0.0]; // -> SE LO CARGAMOS AL ANY EN SU BYTE 0

L B#16#2; // CARGAMOS EL TIPO DE DATO: BYTE
T LB [AR1,P#1.0]; // -> SE LO CARGAMOS AL ANY EN SU BYTE 1

L #NBBYTE; // NUMERO DE BYTES A TRANSFERIR
T LW [AR1,P#2.0]; // -> SE LO CARGAMOS AL ANY EN SU WORD 2

L #DBTARGET; // NUMERO DE DB DESTINO
T LW [AR1,P#4.0]; // -> SE LO TRANSFERIMOS AL ANY EN EL WORD 4

L B#16#85; // CODIGO DE TIPO DE MEMORIA PARA DB
T LB [AR1,P#6.0]; // -> SE LO TRANSFERIMOS AL ANY EN SU BYTE 6

L B#16#0; // LA DIRECCION DE LOS 3 BITS SUPERIORES
T LB [AR1,P#7.0]; // -> SE LO TRANSFERIMOS AL ANY EN SU BYTE 7

L #DBWTARGET; // DBW TARGET
SLW 3; // DESPLAZAMOS 3 POSICIONES A LA IZQUIERDA
T LW [AR1,P#8.0]; // -> ANY POINTER
NETWORK
TITLE =EXECUTE TRANSFER

CALL “BLKMOV” (// BLOCK MOVE
SRCBLK := #SOURCE,// ORIGEN
RET_VAL := #RET,// ERROR
DSTBLK := #TARGET);// DESTINO

NETWORK
TITLE =END OF BLOCK
BEA ;
END_FUNCTION

¿Qué te ha parecido?

Ya sé que este tipo de cosas no se usa todos los días, pero no está demás conocerlas, saber que existe, y que es realmente potente dependiendo de lo que necesites hacer.

¿lo has usado alguna vez?

Acerca de Iñigo Gútiez

Ingeniero industrial por la Escuela de Ingenieros Superiores de Bilbao. Trabajo como ingeniero de proyectos y automatización en Guardian Industries

Te puede interesar

Entrevista a Juan Carlos Martín (REEA)

En esta ocasión traigo al blog algo muy especial. Más bien a alguien especial. La …