Escolar Documentos
Profissional Documentos
Cultura Documentos
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. Tradução
literal, ANY pode ser qualquer coisa. E ele é. Veja as figuras abaixo.
1. Byte 0:
Indica o header do ANY, sendo que no S7 é obrigatório que esse byte
possua o valor 10h (B#16#10).
2. Byte 1:
Indica o tipo de dados representado pela ANY, podendo ser:
6. Byte 7, 8 e 9:
Nesses bytes está representado o endereço (no
padrão Byte.Bit,ou 00000bbbbbbbbbbbbbbbb.xxx, onde b=número
do byte e x número do bit).
1. Byte 0:
Indica o header do ANY, sendo que no S7 é obrigatório que esse byte
possua o valor 10h (B#16#10).
2. Byte 1:
Indica o tipo de dados representado pela ANY em questão, podendo
ser:
Código Hexadecimal Tipo do Dado Descrição
B#16#17 BLOCK_FB Número do FB
B#16#18 BLOCK_FC Número do FC
B#16#19 BLOCK_DB Número do DB
B#16#1A BLOCK_SDB Número do SDB
B#16#1C COUNTER Número do Contador
B#16#1D TIMER Número do
Temporizador
Bom, até aqui eu somente fiz uma tradução simples do help do S7. O que
por um lado é bom, e por outro é ruim.
O bom é que por mais complexo que pareça, o TIPO ANY é simples de
entender, o ruim é que o help básico do S7 não contempla bons exemplos
com o ANY. O que pode ser facilmente corrigido, fazendo uma procura
no www4.ad.siemens.de.
VAR_INPUT
IoIn : ANY ; //Pointer entrada digital para ser forçada
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 parâmetro ANY é
passado para o FC, pois se vocês perceberem, o IoIn é um parâmetro de
entrada. Mas se ele é um parâmetro de entrada, como pode estar sendo
sobrescrito? No mínimo deveria ser um parâmetro do tipo Input/Output.
Não vamos nos desviar do nosso foco, o ANY. A grande sacada é perceber
que o ANY nos informa o tipo e o endereço do dado que está sendo
passado, e com isso poderiamos avaliar todas as informações possíveis
sobre este dado.
No FC acima, foi executada a instrução
L P#IoIn
LAR1
Mas que raio isso significa?
A instrução 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 memória local anterior. E o que significa isso?
Resumidamente, significa que o ANY em questão está armazenado na área
local (L stack) do bloco que o chamou. Aqui é o segredo da coisa. Pois, com
a próxima instrução, LAR1, o conteúdo do ACCU1 será copiado para o
registrador de endereço 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 variável apontanda
inicialmente pelo IoIn. Dessa forma:
L D[AR1,P#6.0]
LAR1
Uma vez que você tem o ponteiro de onde sua informação 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 instrução A #IN01 não deveria ser problema para quem está querendo
aprender o ANY. No caso essa instrução está iniciando uma operação lógica
com o bit IN01 (parâmetro de entrada do tipo BOOL, ver declaração do FC).
Ok, mas o que significa =[AR1,P#0.0]? Significa que o resultado da operação
lógica (RLO para os íntimos) será atribuída ao endereço apontado por AR1
(que guardou o endereço do parâmetro IoIn, conforme código acima)
deslocada de zero bit, conforme o OFFSET P#0.0. Lindo, não?
Se você quisesse escrever no endereço apontado por AR1, porém
deslocado de 2 bits você poderia fazer o seguinte:
Opção A:
= [AR1, P#0.2]
Dessa forma você está mudando o deslocamento através do OFFSET da
instrução de escrita.
Opção B:
L P#0.2
+AR1
= [AR1,P#0.0]
Sim, amigo. Existe notação de ponteiros no PLC da Siemens. No caso as
instruções L P#0.2 +AR1, somou o deslocamento de 2 bits ao endereço
apontado por AR1. Evidentemente nesse caso, perdeu-se o endereço
apontado por IoIn.
Conclusão:
Percebe-se por este pequeno post, que o uso do ANY é muito mais
complexo do que a sua documentação 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,
porém tudo parte do principio que o ANY pode apontar para esses dados
através de seus 80 bits.
Evidentemente e forçadamente eu tentei evitar o seu uso em lógicas
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 NÃO SE USA O ANY AONDE NÃO É
PRECISO, porém o seu uso pode facilitar e muito certos problemas.
Exemplos aonde o ANY pode ser utilizado:
Leituras e Escritas de records extensos;
Criação de funções com buffers e vetores;
Funções que precisam avaliar o tipo de dado que está sendo passado, e
que o mesmo pode mudar ao longo da execução do programa.
Blocos de Comunicação (quase todos os que eu conheço usam o ANY como
parâmetro).
Criação de funções que demandem alto processamento de copy, move, set
e reset.
Funções que demandem acessos indexados.
Formatação do Pointer