quinta-feira, 24 de setembro de 2015

Arduino - Manipulação Direta de Portas

Registradores de Portas

Registradores de portas (PORT) nos permitem acesso de baixo-nível e uma manipulação mais eficiente das portas de e/s do microcontrolador, em uma placa Arduino. Vamos falar dos chips utilizados, que podem variar entre o ATMega8, 168 e 328. Estes chips em questão possuem 3 canais de Portas:
  • B (portas digitais de 8 a 13)
  • C (entradas analógicas)
  • D (portas digitais de 0 a 7)
Cada canal é controlado por 3 Registradores (sendo 1 de configuração, um de manipulação de portas digitais e um só de leitura), e cada qual pode ser definido como variável de sistema, na linguagem do Arduino.

1) Existe um registrador chamado DDR que configura o sentido da porta se ela é de saida (OUTPUT) ou de entrada (INPUT).
2) O Registrador PORT controla se a porta está no estado lógico alto (HIGH) ou baixo (LOW).
3) Existe também o Registrador PIN que efetua a leitura das portas configuradas como INPUT pela função pinMode().

O mapeamento dos chips ATmega8 e ATmega168 mostram essas portas. O chip Atmega328p que é mais novo, segue o mesmo modelo de portas do Atmega168 exatamente!

Os Registradores DDR e PORT podem ser escritos e lidos. Já o Registrador PIN só pode ser lido!

PORTD mapeado para as portas digitais 0 até 7 do Arduino
DDRD - Registrador de Sentido do Port D - leitura/escrita
PORTD - Registrador de Estado do Port D - leitura/escrita
PIND - Registrador das Entradas do Port D - leitura apenas
PORTB mapeado para as portas digitais 8 até 13 do Arduino. Os dois bits mais altos (6 e 7) são dos pinos do cristal e não são usados.
DDRB - Registrador de Sentido do Port B - leitura/escrita
PORTB - Registrador de Estado do Port B - leitura/escrita
PINB - Registrador das Entradas do Port B - leitura apenas
PORTC mapeado para as portas analógicas 0 até 5 do Arduino. Pinos 6 e 7 são acessíveis apenas no Arduino Mini
DDRC - Registrador de Sentido do Port C - leitura/escrita
PORTC - Registrador de Estado do Port C - leitura/escrita
PINC - Registrador das Entradas do Port C - leitura apenas
Cada bit desses 3 Registradores correspondem a uma única porta; exemplo: os bits mais baixos dos Registradores DDRB, PORTB e PINB são referentes ao pino PB0 (porta digital 8). Para conhecer o mapeamento completo de portas do Arduino e dos bits dos Registradores, acesse o diagrama correspondente ao seu chip: ATmega8, ATmega168. (Nota: Alguns bits de algumas portas podem ser usados para outras funcionalidades além de e/s (entrada/saida); seja cuidadoso para não alterar os bits correspondentes a essas portas)

Atenção! Nota do Renato Aloi! Não altere os bits da porta serial! Você pode desligar ela e vai ser difícil ligar ela de novo! Veja mais abaixo, continue lendo...

Exemplos

Se pegarmos os pinos do mapeamento acima, os Registradores referentes ao PortD controlam as portas digitais 0 até 7.

Você deve notar, entretanto, que as portas 0 e 1 já são usadas pela comunicação serial, para carregar programas e para depuração. Portanto, alterar os bits dessas portas deve ser evitado para não desligar a serial! Esteja avisado que estes procedimentos podem interferir no funcionamento da Serial e que você pode acabar não conseguindo mais carregar programas no Arduino!

DDRD é o registrador que configura a direção para o PortD (portas digitais 0-7 do Arduino). Os bits nesse Registrador controlam se as portas do PORTD estão configuradas como entradas ou saídas, por exemplo:

DDRD = B11111110;  // configura portas 1 ate 7 como saidas,
                   //e a porta 0 como entrada
 
DDRD = DDRD | B11111100;  // esta eh uma forma mais segura 
                   // de configurar os pinos 2 ate 7 como saida
                   // sem mudar as configuracoes dos 
                   // pinos 0 e 1 que sao da serial 


Vide operadores de bit nas páginas de referência The Bitmath Tutorial do Playground (traduzido para português por Renato Aloi).

PORTD é o Registrador dos estados das saídas. Por exemplo:

PORTD = B10101000; // registra valor HIGH 
                   // nas portas digitais 7,5,3

Você deverá ver 5V saindo nessas portas, mas só se você configurou o Registrador DDRD como saída, ou através da função pinMode().


PIND é o Registrador das entradas. E ele faz a leitura de todas as portas digitais de uma só vez!

Porque usar Manipulação Direta de Portas?

Retirado do The Bitmath Tutorial:

De forma geral, fazer esse tipo de acesso direto a portas não é uma boa ideia. Porque não? Aqui vão algumas razões:
  • O código fica muito mais difícil de ler e de manter. Além de ser muito mais difícil para outras pessoas poderem entender ou reaproveitar seu código. Leva apenas alguns microsegundos para que o processador execute o código, mas você pode levar horas para encontrar algum defeito e consertá-lo!
  • O código é menos "portável". Se você usar as funções digitalRead() e digitalWrite(), é muito mais fácil de escrever códigos que vão funcionar em todas as versões das placas Arduino. Já controlar diretamente os Registradores é diferente para cada tipo de microcontrolador.
  • Não é difícil causar avarias por acidente enquanto programando e testando acesso direto às portas digitais. Executar a linha DDRD = B11111110; trocando o 0 final por 1, sem querer, ou por distração mudará a configuração do pino RX da serial para saída em vez de entrada e seu Arduino ficará "surdo" da serial.
Então você deve estar pensando: Legal! Nunca vou usar esse negócio então! Mas não é bem assim, existem muitas vantagens em se usar essa técnica de acesso direto às portas, tais como:
  • Você pode querer mudar o estado (entre ligado e desligado) de uma porta muito rapidamente, em frações de microsegundo. Se você der uma olhada no código lib/targets/arduino/wiring.c, verá que as funções digitalRead() e digitalWrite() são compostas de uma dúzia de linhas, que ao serem compiladas formam algumas instruções de máquina. Cada instrução de máquina precisa de um ciclo de clock rodando a 16Mhz, que pode adicionar erros de tempo em circuitos críticos, como processamento de sinal, etc. Manipulação direta das portas pode fazer o mesmo serviço em muito menos ciclos de clock.
  • Algumas vezes você precisa acionar várias portas digitais ao mesmo tempo, e não pode esperar acionar uma primeiro pra depois acionar a outra. Chamando a função digitalWrite(10,HIGH); seguida por digitalWrite(11,HIGH); fará com que a porta 10 primeiro fique em estado HIGH, para apenas vários microsegundos depois a porta 11 também ficar com estado HIGH. Se houver algum circuito externo que espere que ambas as portas fiquem ativas ao mesmo tempo, ele não funcionará. Mas usando acesso direto as portas, você pode configurar as portas para ficarem ativas ao mesmo tempo, com a mesma instrução PORTB |= B1100;
  • Ou se você está sem memória FLASH, você pode usar essas tecnicas para fazer seu código ficar menor. Pois muito menos instruções serão geradas para alterar o estado das portas usando manipulação direta do que pelas funções. As vezes esses truques são a diferença que fazem seu programa caber na memória flash ou não!

Veja Também

The text of the Arduino reference is licensed under a Creative Commons Attribution-ShareAlike 3.0 License. Code samples in the reference are released into the public domain.
Tradução livre do original https://www.arduino.cc/en/Reference/PortManipulation
Por Renato Aloi

Um comentário:

  1. ADMIRO SEU TRABALHO, MUITO ESCLARECEDOR E COM LINGUAGEM OBJETIVA.
    NENHUM ASSUNTO FICA A DESEJAR.

    PARABENS E OBRIGADO.

    ResponderExcluir