Vous êtes sur la page 1sur 10

Acesso indexado no Step7

maio 10, 2007 Mrcio Roberto








2 Votes

Eu costumo comentar com as pessoas que o divisor de guas entre quem pode afirmar que conhece, e
bem o PLC da Siemens e quem sabe o usar o PLC, exatamente o conhecimento e o uso do tipo ANY.
Genericamente falando o ANY um dado muito pretensioso, pois ele pode ser qualquer coisa e apontar
para qualquer coisa dentro do PLC. Traduo literal, ANY pode ser qualquer coisa. E ele . Veja as figuras
abaixo.

Formatao do ANY para variveis na memria.


Formatao do ANY para blocos de dados (parmetros).
Essas figuras documentam a formatao do dado ANY, que possui em sua estrutura 80 bits. Com essa
formatao ele pode simplesmente apontar para qualquer rea no PLC. Isso mais do que ser uma forma
de endereamento varivel.
Geralmente, associamos o termo endereamento varivel ou endereamento indireto ao uso de dados que
ora apontam para uma regio de memria e ora apontam para outra regio. No esse o caso, pois o
ANY pode inclusive apontar para funes, atuando quase que como um ponteiro para funo do C/C++.
Se voc precisa somente de um ponteiro que aponte para endereos de memria, voc poderia utilizar o
tipo POINTER do PLC.
Veja a figura abaixo.

Formatao do Pointer
O uso do POINTER e ANY de forma a apontarem para endereos de memria so muito semelhantes,
sendo que o POINTER possui em sua estrutura 48 bits, mas por hora me atentarei ao uso do ANY, que
muito mais completo e muito mais mutante.
Vamos analisar a estrutura completa do ANY.
Primeiramente vamos analisar a estrutura apontando para endereos de variveis na memria do PLC.
1. Byte 0:
Indica o header do ANY, sendo que no S7 obrigatrio que esse byte possua o valor 10h
(B#16#10).
2. Byte 1:
Indica o tipo de dados representado pela ANY, podendo ser:
Cdigo Hexadecimal Tipo do Dado Descrio
B#16#00 NIL Ponteiro Nulo
B#16#01 BOOL Bits
B#16#02 BYTE Byte (8 bits)
B#16#03 CHAR Caracteres (8 bits)
B#16#04 WORD Palavra (16 bits)
B#16#05 INT Inteiro (16 bits)
B#16#06 DWORD Dupla Palavra (32 bits)
B#16#07 DINT Duplo Inteiro (32 bits)
B#16#08 REAL Nmero de Ponto
Flutuante (32 bits)
B#16#09 DATE Data
B#16#0A TIME_OF_DAY (TOD) Hora do Dia
B#16#0B TIME Tempo
B#16#0C S5TIME Tempo tipo S5TIME
B#16#0E DATE_AND_TIME (DT) Data e Hora (64 bits)
B#16#13 STRING Texto
3. Byte 2 e Byte 3 (Word 2):
Indica o fator de repetio, ou seja, quantos dados esse ANY representa.
4. Byte 4 e Byte 5 (Word 4):
Indica o nmero do DB, caso o ANY esteja representando dados de um DB em especfico, ou o
valor zero caso no aponte para nenhum DB.
5. Byte 6:
Indica o tipo de memria representada pelo ANY, podendo ser:
Cdigo Hexadecimal rea Descrio
B#16#81 I rea de Entrada
B#16#82 Q rea de Sada
B#16#83 M rea de Bit Memory
(Flags ou Markers)
B#16#84 DB Bloco de Dados
B#16#85 DI Bloco de Dados
Instanciados
B#16#86 L rea Local (L stack)
B#16#87 V rea de Local Anterior
6. Byte 7, 8 e 9:
Nesses bytes est representado o endereo (no
padro Byte.Bit,ou 00000bbbbbbbbbbbbbbbb.xxx, onde b=nmero do byte e x nmero do bit).
Agora vamos analisar a estrutura apontando para parmetros de blocos na
memria do PLC
1. Byte 0:
Indica o header do ANY, sendo que no S7 obrigatrio que esse byte possua o valor 10h
(B#16#10).
2. Byte 1:
Indica o tipo de dados representado pela ANY em questo, podendo ser:
Cdigo
Hexadecimal
Tipo do Dado Descrio
B#16#17 BLOCK_FB Nmero do FB
B#16#18 BLOCK_FC Nmero do FC
B#16#19 BLOCK_DB Nmero do DB
B#16#1A BLOCK_SDB Nmero do SDB
B#16#1C COUNTER Nmero do Contador
B#16#1D TIMER Nmero do Temporizador
3. Byte 2 e Byte 3 (Word 2):
No relevantes, sendo que o valor dessa Word ser sempre 1.
4. Byte 4 e Byte 5 (Word 4):
No relevante, sendo que o valor dessa Word ser sempre 0.
5. Byte 6:
No relevante, sendo que o valor dessa Word ser sempre 0.
6. Byte 8 e 9 (Word 8):
Indica o nmero do FB, FC, DB, SDB, Contador ou Temporizador representado pelo ANY.
Bom, at aqui eu somente fiz uma traduo simples do help do S7. O que por
um lado bom, e por outro ruim.
O bom que por mais complexo que parea, o TIPO ANY simples de
entender, o ruim que o help bsico do S7 no contempla bons exemplos com
o ANY. O que pode ser facilmente corrigido, fazendo uma procura
no www4.ad.siemens.de.
Mas faamos o seguinte, outro dia o Williams me perguntou como fazer um FC
para reescrever os valores das entradas.
De bate pronto eu comentei com ele que plenamente possvel fazer isso com:
A I0.0
NOT
= I0.0
Ou seja, se o cdigo acima (em STL) estiver rodando na primeira linha do OB1,
a entrada I0.0 ser invertida a cada comeo de ciclo de CPU (observe que
estou desconsiderando a possibilidade de utilizar-se o particionamento de
imagem de periferia do S7) e ter o valor invertido durante este ciclo em
qualquer parte do programa.
Para tentar ser mais claro, poderia fazer o seguinte:
A M4.3
= I0.0
Se esse cdigo estiver rodando na primeira linha do OB1, a entrada (ou mais correto dizer, o endereo)
I0.0 ser cpia do valor de M4.3.
Se voc no sabia desse fato, fique sabendo agora, e saiba tambm que todo PLC a principio segue esse
comportamento.
Devido a esse comportamento, que eu vivo criando ferramentas de simulao de I/O para tudo quanto
tipo de PLC, assim como queria fazer o Williams.
Legal, mas aonde entra o ANY nisso tudo? Esse o ponto meu camarada! O Williams que no bobo,
queria fazer uma funo parametrizada que fizesse isso por ele. Logo ele iria entrar com o endereo inicial
da entrada que ele iria simular e os valores que deveriam ser forados. Nada mais prtico!
Bom, eu mandei uma sugesto para ele, sendo que poderia criar o seguinte FC:
FUNCTION FC 3 : VOID
TITLE =
FAMILY : Sim
NAME : SimIO
VERSION : 1.0
VAR_INPUT
IoIn : ANY ; //Pointer entrada digital para ser forada
IN00 : BOOL ; //Valor da entrada 0
IN01 : BOOL ; //Valor da entrada 1
IN02 : BOOL ; //Valor da entrada 2
IN03 : BOOL ; //Valor da entrada 3
IN04 : BOOL ; //Valor da entrada 4
IN05 : BOOL ; //Valor da entrada 5
IN06 : BOOL ; //Valor da entrada 6
IN07 : BOOL ; //Valor da entrada7
END_VAR
VAR_TEMP
DB_NR : WORD ;
END_VAR BEGIN NETWORK
TITLE =Inicializa apontador
//Ver que esta sendo usado um parametros do tipo ANY
//Dever ser chamado este bloco passando o primeiro bit da rea a ser
//sobreescrita.
//////////////////////////////////////////////////////////////////////////////////////////////
L P##IoIn;
LAR1 ;
//Abre o DB, se estiver sendo utilizado
L W [AR1,P#4.0];
T #DB_NR;
OPN DB [#DB_NR];
//carrega pointeiro de area cruzada. Ver ponteiro any
L D [AR1,P#6.0];
LAR1 ;
//////////////////////////////////////////////////////////////////////////////////////////////
NETWORK
TITLE =Sobreescreve os bits apontados pelo parametro IoIn
//////////////////////////////////////////////////////////////////////////////////////////////
//Entrada 00
A #IN00;
= [AR1,P#0.0];
//Entrada 01
A #IN01;
= [AR1,P#0.1];
//Entrada 02
A #IN02;
= [AR1,P#0.2];
//Entrada 03
A #IN03;
= [AR1,P#0.3];
//Entrada 04
A #IN04;
= [AR1,P#0.4];
//Entrada 05
A #IN05;
= [AR1,P#0.5];
//Entrada 06
A #IN06;
= [AR1,P#0.6];
//Entrada 07
A #IN07;
= [AR1,P#0.7];
//////////////////////////////////////////////////////////////////////////////////////////////
END_FUNCTION
Bom, pra ser sincero, o segredo desse FC est em como o parmetro ANY passado para o FC, pois se
vocs perceberem, o IoIn um parmetro de entrada. Mas se ele um parmetro de entrada, como pode
estar sendo sobrescrito? No mnimo deveria ser um parmetro do tipo Input/Output.
No vamos nos desviar do nosso foco, o ANY. A grande sacada perceber que o ANY nos informa o tipo e
o endereo do dado que est sendo passado, e com isso poderiamos avaliar todas as informaes
possveis sobre este dado.
No FC acima, foi executada a instruo
L P#IoIn
LAR1
Mas que raio isso significa?
A instruo L P#IoIn est carregando o ponteiro de 32 bits no acumulador 1 da CPU (ou o ACCU1), ela
retorna algum valor do tipo DW#16#8700XXYY, onde:
B#16#87: Corresponde a memria local anterior. E o que significa isso? Resumidamente, significa que o
ANY em questo est armazenado na rea local (L stack) do bloco que o chamou. Aqui o segredo da
coisa. Pois, com a prxima instruo, LAR1, o contedo do ACCU1 ser copiado para o registrador de
endereo 1 (ou o AR1).
Como o AR1 est apontando exatamente para o ANY que foi passado, basta copiarmos a parte do
ponteiro de 32 Bits de rea cruzada desse ANY para o AR1, e logo o AR1 ir apontar exatamente para a
varivel apontanda inicialmente pelo IoIn. Dessa forma:
L D[AR1,P#6.0]
LAR1
Uma vez que voc tem o ponteiro de onde sua informao est armazenada, s acess-la. Como? Veja
isso:
A #IN01
= [AR1,P#0.0]
O que significa esse raio pior ainda?
Calma, vamos analisar.
A instruo A #IN01 no deveria ser problema para quem est querendo aprender o ANY. No caso essa
instruo est iniciando uma operao lgica com o bit IN01 (parmetro de entrada do tipo BOOL, ver
declarao do FC).
Ok, mas o que significa =[AR1,P#0.0]? Significa que o resultado da operao lgica (RLO para os ntimos)
ser atribuda ao endereo apontado por AR1 (que guardou o endereo do parmetro IoIn, conforme
cdigo acima) deslocada de zero bit, conforme o OFFSET P#0.0. Lindo, no?
Se voc quisesse escrever no endereo apontado por AR1, porm deslocado de 2 bits voc poderia fazer o
seguinte:
Opo A:
= [AR1, P#0.2]
Dessa forma voc est mudando o deslocamento atravs do OFFSET da instruo de escrita.
Opo B:
L P#0.2
+AR1
= [AR1,P#0.0]
Sim, amigo. Existe notao de ponteiros no PLC da Siemens. No caso as instrues L P#0.2 +AR1, somou
o deslocamento de 2 bits ao endereo apontado por AR1. Evidentemente nesse caso, perdeu-se o
endereo apontado por IoIn.
Concluso:
Percebe-se por este pequeno post, que o uso do ANY muito mais complexo do que a sua documentao
sugere. At porque fizemos um uso at que simples para ele.
Poderiamos aumentar as possibilidade utilizando dados complexos (maiores que 32 bits) como , array,
structs, UDT, date and time e outros, porm tudo parte do principio que o ANY pode apontar para esses
dados atravs de seus 80 bits.
Evidentemente e foradamente eu tentei evitar o seu uso em lgicas simples, como para intertravamentos
ou o uso do ANY onde outros meios fariam a mesma coisa e com uma simplicidade de entendimento e
desenvolvimento muito melhor. Logo NO SE USA O ANY AONDE NO PRECISO, porm o seu uso
pode facilitar e muito certos problemas.
Exemplos aonde o ANY pode ser utilizado:
Leituras e Escritas de records extensos;
Criao de funes com buffers e vetores;
Funes que precisam avaliar o tipo de dado que est sendo passado, e que o mesmo pode mudar ao
longo da execuo do programa.
Blocos de Comunicao (quase todos os que eu conheo usam o ANY como parmetro).
Criao de funes que demandem alto processamento de copy, move, set e reset.
Funes que demandem acessos indexados.
No caso de funes que demandem somente acessos indexados simples, eu sugiro antes de usar o ANY o
estudo do uso do seguintes acessos indexados:
Ponteiro de 16 Bits com uso de memria (para DBs, temporizadores e contadores). Ex.:
OPN DB[ MW100]
SE[MW100]
CD[MW100];
Ponteiro de 32 Bits com uso de memria (com rea interna). Ex.:
L P#0.0
T MD100
L IW[MD100]
Ponteiro de 32 Bits com uso de registrador indireto (com rea interna). Ex.:
L P#0.0
LAR1
L IW[AR1,P#0.0]
Ponteiro de 32 Bits com uso de registrador indireto (com rea cruzada). Ex.:
L P#I0.0
LAR1
L W[AR1,P#0.0]
Ponteiro de 48 Bits com uso de registrador indireto (com rea cruzada).
Este permite o acesso ao nmero do DB utilizado.
Este ponteiro funciona como o ponteiro de 32 Bits com uso de registrador indireto e com rea cruzada. A
principal diferena que ele pode ser declarado como parmetro em FB e FC. Sua estrutura segue o
padro da figura abaixo.

Formatao do Pointer
O uso de parmetros complexos, como o Ponteiro de 48 Bits e o ANY (80 Bits) tem restries quando
utilizados em FB e FC, porm no vou entrar em detalhes, pois o prprio Step7 no deixar voc utiliz-los
de forma errada, porm fao grandes advertncias em relao ao uso dos registradores de endereo, AR1
e AR2.
Cuidados com o uso do AR1 e do AR2:
Cuidado com o uso do AR1 em FCs que chamam blocos que pedem dados complexos (string,
array,structure e UDT) como parmetro. O mesmo vale para FBs que passam esses parmetros como
IN_OUT.
Cuidado com o uso do AR2 dentro de FBs, pois ele utilizado para acessar os dados do DB Instance, logo
dependendo da forma como voc alter-lo, pode impedir o acesso aos dados do DB instance desse FB.
Uma luz no fim do tnel:
Pra quem est dizendo:
No entendi nada!
Que porcaria esse ANY e esses acessos indexados!
T perdido!
Eu dou um conselho. No entre em pnico!
Felizmente voc pode passar a vida toda sem se preocupar em ter que aprender o ANY e seus derivados,
pois o seu processo pode ser extremamente simples e no demandar algo do tipo. Ou ento voc pode
precisar de algo do tipo e acabar de vez com os seus problemas programando o PLC com a linguagem SCL
(o texto estruturado da IEC61131-3). Veja que facilidade em fazer um acesso indexado sobre um DB
indexado sendo que o componente interno desse DB tambm ser acessado de forma indexada:
word_to_db(nmero_DB).DW[nmero_componente].
Nada mais simples!
Evidentemente o que est rolando por trs muito acesso indexado com o ANY e seus derivados. Mas
voc nem precisaria saber isso!
About these ads
Relacionado
Horrio de vero, o meu pior pesadelo.Em "Blogroll"
Como voc detecta os erros no seu sistema?!Em "CLP"
Parceiros para Desenvolvimento de Software LivreEm "SCADA"
Publicado em CLP. 12 Comments
12 Respostas to Acesso indexado no Step7
1. Willams Vitor Says:
maio 11, 2007 s 12:03 am

0

0

Rate This
Mrcio, a funo citada acima, eu a modifiquei um pouco para sua utilizao tornar-se o mais
simples possvel. Observe que no formato exibido todos os bits so forados, o que
acabaria por comprometer status reais de elementos fsicos do sistema. Optei por utilizar
apenas um nico bit por chamada, conforme pode ser visualizado abaixo.
FUNCTION Force IO : VOID
TITLE =Funo Simulao de status de entradas e sadas digitais
//Projeto Elaborado por: Willams Vitor e Mrcio Roberto
//
AUTHOR : Wil
FAMILY : IO
NAME : IoCtrl
VERSION : 1.1
VAR_INPUT
IoIn : ANY ; //Pointer: Entrada/Sada digital para ser forada
BitVal : BOOL ; //Valor do force (0/1)
END_VAR
VAR_TEMP
DB_Nr : WORD ;
END_VAR
BEGIN
NETWORK
TITLE =Inicializa apontador
//Obervar que estamos usando um parmetro tipo Any
//Dever ser chamado este bloco passando o primeiro bit da rea a ser
//sobrescrita.
//No caso IX.0
//
L P##IoIn; // Byte de entrada digital
LAR1 ; // Transfere para o registro de endereos
// Carrega ponteiro da rea cruzada
L D [AR1,P#6.0];
LAR1 ;
NETWORK
TITLE =Fora IO
//Sobreescreve o bit apontado pelo parmetro IoIn
A #BitVal;
= [AR1,P#0.0];
END_FUNCTION

Vous aimerez peut-être aussi