Entrada e Saída – Manipulando Registradores

Para determinar os estados de suas entradas e saídas o microcontrolador possui registradores na qual esses dados são armazenados. Ao chamar as funções de entrada e saída fornecidas pela biblioteca padrão do Arduino o que fazemos é nada mais que modificar tais registradores. Então porque acessar estes registradores diretamente?

A manipulação direta de registradores permite que:

  • A leitura e escrita em pinos seja feita muito mais rápida.
  • Ler e escrever em mais de um pino de uma mesma porta por vez.
  • O código produzido é menor, em alguns casos esse fator pode fazer a diferença entre seu código caber na memória flash ou não.

Essa técnica também possuí desvantagens:

  • O código produzido é menos portável, difícil de debbugar e de ser mantido.

Na abordagem dos conceitos a seguir o microcontrolador atmega328 presente na placa Arduino Uno será utilizado. Para acompanhar esse tutorial é necessário algum conhecimento de lógica digital.

Todos os registradores desse microcontrolador possuem 8 bits. Os pinos de entrada e saída são divididos em PORTs. O atmega328 possui 3 PORTs, como podemos observar no diagrama a seguir:

Cada PORT possui 3 registradores com diferentes funções:

DDR

Os registradores do tipo DDR (Data Direction Register) são responsáveis por determinar se os pinos de um determinado PORT se comportarão como entrada ou saída. Cada bit do registrador DDR controla o estado do respectivo pino. Por exemplo: O bit 1 do registrador DDRB (DDB1) controlará o estado do pino PB1 e consequentemente o pino D9 do Arduino Uno como mostrado no mapa.

Para definir um pino como saída devemos setar seu respectivo bit do registrador DDR como 1 e  para defini-lo como entrada seta-lo para 0.

/* Equivalente:
pinMode(9,OUTPUT);
pinMode(9,INPUT);
*/

DDRB |= (1 << DDB1);
DDRB &= ~(1 << DDB1);

PORT

Os registradores do tipo PORT são responsáveis por determinar se um pino está definido como alto (HIGH) ou baixo (LOW).

portb

Para definir um pino como alto devemos setar seu respectivo bit do registrador PORT como 1 e para defini-lo como baixo seta-lo para 0.

 

/* Equivalente:
pinMode(9,OUTPUT);
digitalWrite(9,LOW);
*/
 
DDRB |= (1 << DDB1);
PORTB &= ~(1 << PORTB1);

Outro exemplo:

/* Equivalente:
digitalWrite(8,HIGH);
digitalWrite(9,HIGH);
digitalWrite(10,HIGH);
digitalWrite(11,HIGH);
digitalWrite(12,HIGH);
digitalWrite(13,HIGH);
*/
 
PORTB = 0xFF;

 

PIN

Os registradores do tipo PIN são responsáveis por guardar o estado lógico de um pino.

/* Equivalente:
pinMode(9,INPUT);
digitalWrite(9,HIGH); //Nesse contexto, ativa o pull-up interno.
bool x = digitalRead(9);
*/
 
DDRB &= ~(1 << DDB1);
PORTB |= (1 << PORTB1);
bool x = (PINB & (1 << PINB1));
Todo o conteúdo apresentado pode ser encontrado no datasheet do microcontrolador.

Privacy Preference Center