Básico - Projeto 82

Interrupção externa utilizando registradores de portas do Arduino

Objetivo

Neste projeto vamos mostrar como utilizar registradores de portas DDR e PORT para realizar interrupções externas no Arduino. Vamos, desta forma, exemplificar o conceito de interrupção externa utilizando os registradores DDR, PORT, EIMSK e EICRA para apresentar a técnica mais eficiente para ligar e desligar um componente eletrônico através de um botão ou de um sensor de entrada qualquer (no projeto vamos utilizar um botão e um sensor de toque).

Vantagens de se utilizar registradores com interrupção externa:

  1. Maior velocidade de acesso, pois acionaremos a porta diretamente sem a necessidade de funções.
  2. Otimização de memória do microcontrolador.
  3. Executar duas tarefas quase que simultaneamente.

Desvantagens de se utilizar registradores com interrupção:

  1. Código de difícil entendimento.
  2. Criar códigos utilizando registradores não irão funcionar em todos os tipos e versões do Arduino. Cada microcontrolador possui estruturas de pinos digitais e analógicos diferentes.
  3. É muito mais fácil causar problemas de funcionamento não intencionais com acesso direto à porta.

Observações:

1. Interrupção externa: É quando o programa do Arduino está instruído para reagir à mudança de um sinal externo, por exemplo,  mudança do nível lógico de um sinal gerado por um botão ou por um sensor qualquer (Referência Arduino). Veja o tutorial: Projeto 78 - Como realizar interrupção externa no Arduino usando sensor de toque

1.1. ISR - Interrupt Service Routine ou Rotina de Serviço de Interrupções em português, são instruções que são executadas quando ocorre uma interrupção externa. Entretanto, estas instruções são especiais e possuem algumas limitações, sendo:

. Uma ISR não recebe argumentos e não retorna nada.

. Uma ISR deverá ser a mais curta e rápida possível.

. Se o seu programa utiliza múltiplas ISRs, apenas uma poderá ser executada de cada vez.

. A função delay() não funcionara em uma ISR.

. A função millis() não poderá ser incrementada dentro de uma ISR.

. A função delayMicroseconds() ao não utilizar nenhum contador, funcionará normalmente em uma ISR.

2. O conceito DDR e PORT utilizado neste projeto é específico para Arduino UNO R3 que utiliza o microcontrolador ATmega328. Outros microcontroladores podem ter configurações diferentes. Para saber mais, leia os artigos: Arduino - Manipulação Direta de Portas do blog do Renato Aloi, Port Registers - Documento de Referência Arduino e os projetos: Projeto 81 - Ligar e desligar um led por manipulação direta de portas do Arduino, Projeto 61 - Dado eletrônico com leds e uso de manipulação direta de portas do Arduino e Projeto 60 - Dado eletrônico com Arduino (uso de manipulação direta de portas).

3. O conceito de registradores para interrupções externas EIMSK e EICRA também utilizados no projeto são específicos para o microcontorlado ATmega328, onde utilizamos os pinos INT0 e INT1 (pinos 2 e 3 do Arduino Uno). Para se aprofundar mais sobre a arquetetura do microcontrolador ATmega328 leia: http://www.dca.fee.unicamp.br/~rferrari/EA075_2s2017/Cap.%203.1%20-%20Microcontrolador_ATMega328P.pdf

4. Para avançarmos um pouco mais na utilização de registradores de portas do Arduino, vamos precisar de um conhecimento básico sobre operadores bitwise. Para isso, recomendo que leiam o artigo Operadores Bitwise (Bit-a-Bit) do blog Diogo Matheus.

5. ATENÇÃO: Tome muito cuidado em utilizar o conceito de manipulação direta de portas. Qualquer erro pode danificar permanentemente a sua placa de Arduino.

Registradores de portas do Arduino Uno R3

Registradores de portas (DDR, PORT e PIN) permitem o acesso direto às portas do Arduino. Veja abaixo a imagem que mostra todas portas disponíveis do Arduino UNO:

Nos microcontroladores Arduino Uno, existem 3 canais de portas:

  • Porta B (portas digitais de 8 a 13)
  • Porta C (entradas analógicas)
  • Porta D (portas digitais de 0 a 7)

Para exemplificar melhor vamos utilizar o canal de portas D referente às portas digitais 0 a 7 do Arduino UNO. Microcontroladores de 8bits, como o Arduino UNO por exemplo, cada canal de portas possui 8 bits. Portanto, cada bit representa uma porta (ou pino) de cada canal de portas.

Cada porta do microcontrolador possui 3 registradores, sendo eles:

  • DDR que configura o sentido da porta se ela é saída (OUTPUT) ou entrada (INPUT). Substitui a função pinMode().
  • PORT que controla se a porta está no estado lógico alto (HIGH) ou baixo (LOW).
  • PIN que efetua a leitura das portas configuradas como INPUT pela função pinMode().

No nosso projeto vamos utilizar os registradores DDR e PORT conforme as instruções abaixo:

4.1. Para imprimir o valor 1 em um bit, use sempre o padrão:

DDRporta |= (1 << bit que se pretende configurar como OUTPUT);

PORT |= (1<< bit que se pretende enviar HIGH);

4.1.1. No nosso exemplo, teremos as instruções: DDRD |= (1<<3); e PORTD |= (1<<3)

Obs.: DDRD |= (1<<3); pode ser escrito da seguinte forma: DDRD = DDRD | (1<<3);

4.2. Para imprimir o valor 0 em um bit, use sempre o padrão:

DDR &= ~(1<< bit que se pretende configurar como entrada);

PORT &= ~(1 << bit que se pretende enviar LOW);

DDR (Data Direction Register - read/write)

  • No caso do registrador DDR, vamos acrescentar o canal de portas D, ficando portanto como DDRD (portas digitais de 0 a 7 no Arduino Uno).
  • Definimos para cada porta se é saída (OUTPUT), usando o 1 ou se é entrada (INPUT), usando o 0.
  • A ordem das portas é decrescente e vai de PD7 até PD0 e PB5 até PB0 (desconsidere o erro na imagem, leia PB5 no lugar de PB6)
  • Como é um número binário, devemos colocar o modificador "B" na frente, veja o exemplo a seguir:

Ex.:

DDRD = B11111110;  // configura portas 1 ate 7 como saídas,e a porta 0 como entrada

Usando operadores bitwise, podemos configurar cada pino individualmente da seguinte forma:

  • DDRporta |= (1 << bit que se pretende configurar como OUTPUT); // imprime o valor 1 no bit e configura como saída - defina a Porta B, C ou D e o bit específico.
  • DDRporta &= ~(1<< bit que se pretende configurar como INPUT); // imprime o valor 0  no bit e configura como entrada - defina a Porta B, C ou D e o bit específico.

Ex.:

DDRB |= (1<<4);  // configura o bit 4 da Porta B como OUTPUT - pino 12 saída
DDRD &= ~(1<<3);  // configura o bit 3 da Porta D como INPUT - pino 3 entrada

PORT (Data Register - read/write)

  • Como no registrador DDR, vamos acrescentar no PORT o canal de portas D, ficando portanto como PORTD (portas digitais de 0 a 7 do Arduino Uno).
  • Definimos para cada porta, se está no estado lógico HIGH, usamos 1 ou se está no estado lógico LOW, usamos 0.
  • A ordem das portas vai de PD7 até PD0.
  • Como é um número binário, devemos colocar o modificador "B" na frente, veja o exemplo a seguir:
PORTD = B10101000;  // registra valor HIGH nas portas digitais 7,5 e 3

Usando operadores bitwise podemos controlar cada pino individualmente, como:

  • PORTporta |= (1<< bit que se pretende enviar HIGH); // envia um sinal de alto nível (1) para o bit desejado
  • PORTporta &= ~(1 << bit que se pretende enviar LOW); // envia um sinal de baixo nível (0) para o bit desejado
  • PORTporta ^= (1 << bit que se pretende enviar HIGH e LOW) // liga e desliga a cada vez que o botão é pressionado. Operador XOR - Referência Arduino.

Ex.:

PORTB |= (1<<4);  // envia HIGH para o bit 4 da Porta B - pino 12
PORTB &= ~(1<<4);  // envia LOW para o bit 4 da Porta B - pino 12

Registradores para interrupção externa

Para configurarmos um interrupções externas nos projetos com Arduino, podemos utilizar basicamente 2 registradores:

  • EIMSK - Habilita INT0 e INT1 do Arduino UNO
  • EICRA - Define como INT0 e INT1 são ativadas (LOW, RISING, FALLING ou CHANGE)

EIMSK (External Interrupt Mask Register)

  • EIMSK |= (1<<INT0); // habilita a interrupção externa INT0 no pino 2 Arduino
  • EIMSK |= (1<<INT1); // habilita a interrupção externa INT0 no pino 3 Arduino

Atenção: Necessário que a interrupção global também esteja ativa

Funções para habilitar e desabilitar interrupções globalmente

  • sei(); // função que habilita as interrupções externas globalmente
  • cli(); // função que desabilita as interrupções externas globalmente

EICRA (External Interrupt Control Register A)

EICRA INT0 (pino 2)

  • EICRA |= (0<<ISC01) | (1<<ISC00); // configura interrupção externa int 0 - CHANGE
  • EICRA |= (1<<ISC01) | (0<<ISC00); // configura interrupção externa int 0 - FALLING
  • EICRA |= (1<<ISC01) | (1<<ISC00); // configura interrupção externa int 0 - RISING

EICRA INT1 (pino 3)

  • EICRA |= (0<<ISC11) | (1<<ISC10); // configura interrupção externa int 1 - CHANGE
  • EICRA |= (1<<ISC11) | (0<<ISC10); // configura interrupção externa int 1 - FALLING
  • EICRA |= (1<<ISC11) | (1<<ISC10); // configura interrupção externa int 1 - RISING

Rotina de Serviço de Interrupções (ISR)

  • ISR (INT0_vect) { ... } // define a rotina para quando ocorre interrupção no INT0
  • ISR (INT1_vect) {... } // define a rotina para quando ocorre interrupção no INT0

Aplicação

Para fins didáticos e projetos exigem a utilização de códigos profissionais.

Componentes necessários

Protoboard Protoboard 830 pontos 1 Resultado de imagem para protoboard 830v

No mínimo utilizar protoboard com 830 pontos

Jumpers Kit cabos ligação macho / macho 1  
Sensor de toque capacitivo Sensor touch TP223B 1

Tensão de Operação: 2 a 5V

Saída estado Alto (HIGH): 0,8V

Saída estado Baixo (LOW): 0,3V

Tempo de resposta: 220ms (LOW) e 60ms (HIGH)

datasheet

Led 5mm Led 5 mm 1

1 LED difuso (poderão ser utilizados leds de qualquer cor)

Você poderá utilizar também LEDs de 3 mm e na cor que desejar.

Resistor Resistor 1

1 Resistor de 150Ω ou superior

Push Button Push button 6X6X5mm 1  
Capacitor Cerâmico Capacitor Cerâmico 2nF a 10nF 1 3 Pçs 2.2nf X 2kv Capacitor 222 2200 105°c 2kv Capacitores - R$ 21 ...

O capacitor será utilizado para estabilizar a função do botão (push button) no caso de se utilizar interrupção externa

Arduino UNO R3 Arduino UNO 1

Você poderá utilizar uma placa Arduino UNO original ou similar

Montagem do Circuito

Conecte os componentes no Protoboard como mostra a figura abaixo. Verifique cuidadosamente os cabos de ligação antes de ligar seu Arduino. Lembre-se que o Arduino deve estar totalmente desconectado da força enquanto você monta o circuito.