Fork me on GitHub

Microcontrolandos

O Blog está passando por uma fase de mudanças. Todos os posts estão sendo atualizados, códigos, links e imagens estão sendo arrumados. Conteúdos novos ainda estão por vir.

AVR: Interrupções - Parte 1

Share:

AVR: Interrupções


O microcontrolador ATMEGA328P possui várias fontes de interrupção.

Cada interrupção possui seu próprio vetor na memória de programa.

Todas as interrupções são habilitadas individualmente.

Quanto mais baixo o endereço do vetor da interrupção, maior é o nível de prioridade.

O vetor de RESET possui a maior prioridade, é claro.

Os vetores de interrupção podem ser movidos para o inicio da área do bootloader, configurando o bit IVSEL do registro MCUCR.

O vetor de RESET também pode ser movido para o início do bootloader, programando o fusível BOOTRST.

Quando uma interrupção ocorre, o bit de Interrupção Global é limpo e, todas as interrupções são desativadas.

A interrupção ocorre quando há um evento (externo ou interno). A flag deste evento é setada. O contador de programa é orientado para o vetor desta interrupção, a fim de manipular a rotina e o hardware limpa a flag de interrupção. Se um evento de interrupção for gerado, e a interrupção estiver desabilitada, mesmo assim sua flag será setada e terá que ser limpa pelo software.

Você poder utilizar instruções assembly para habilitar e desabilitar a interrupção global. A instrução cli desabilita todas as interrupções. Para habilitá-las utilize a instrução sei.

Veja a tabela completa das interrupções para o ATMEGA328P. Para os demais microcontroladores, consulte seu datasheet.



No mikroC PRO a rotina de interrupção possui a seguinte declaração:
<nome da rotina>()   iv   <endereço>   ics   ICS_AUTO

void InterrupcaoExterna0() iv 0x0002 ics ICS_AUTO
{
  //Seu código aqui!!
}

/////OU/////

void InterrupcaoExterna0() iv ADDR_INT0 ics ICS_OFF
{
  //Seu código aqui!!
}

iv  - indica o endereço do vetor de interrupção.
ics (Interrupt Context Saving) - É usado para salvar registros na pilha antes da entrada da rotina de interrupção e restaurá-los na saída. Pode ser usado de duas maneiras:
ICS_OFF - O Compilador não irá salvar registros.
ICS_AUTO - O compilador escolhe se salvará ou não registros.
Seu uso é opcional. Quando omitido, o compilador interpretará como ICS_AUTO.

O próximo post falarei mais detalhadamente sobre as principais interrupções.

6 comentários:

  1. gostaria de saber se vc saberia como acessar as interrupções pela USART (RX e TX) mas no compilador que o site arduino.cc disponibiliza, obrigado.

    ResponderExcluir
    Respostas
    1. unsigned long baud = 9600; //DEFINE BAUDRATE
      unsigned long baudprescale;

      //funcao para enviar um byte
      void USART_Transmit(unsigned char data)
      {
      while ( !( UCSR0A & (1<<UDRE0)) ) ;
      UDR0 = data;

      }

      //ROTINA DE INTERRUPÇÃO
      ISR(USART_RX_vect)
      {
      digitalWrite(13, !digitalRead(13));
      USART_Transmit(UDR0);
      }


      void setup() {
      pinMode(13, OUTPUT);

      baudprescale = (((F_CPU / (baud * 16UL))) - 1); //

      cli();//desabilita interrpçao global

      //RXCIE0 = habilita interrupçao RX
      //TXCIE0 = habilita interrupçao TX
      //RXEN0 = habilita recepcao RX
      //TXEN0 = habilita transimssao TX
      UCSR0B = (1<<RXCIE0) | (0<<TXCIE0) | (1<<RXEN0) | (1<<TXEN0) | (0<<UCSZ02);
      UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); //Assincrono, caracter 8bits

      UBRR0L = baudprescale;
      UBRR0H = (baudprescale >> 8);

      sei(); //habilita interrpçao global
      }

      void loop()
      {

      }

      Excluir
    2. Não é possível utilizar a rotina de interrupção com a função Serial.begin(), pois irá ocorrer um conflito!!

      Excluir
    3. obrigado tiago, testei e o led piscou quando o arduino recebeu algo pela serial, mas a minha dúvida é a seguinte: quando eu receber '1' pela serial o led muda seu estado, onde eu colocaria algo semelhante ao serial.read() para fazer a leitura dos caracteres recebidos pela serial??

      Excluir
    4. ISR(USART_RX_vect)
      {
      //UDR0 recebe o valor do caracter
      if(UDR0=='1')
      {
      digitalWrite(13, !digitalRead(13));
      }
      }

      Excluir
    5. Outro Exemplo: quando receber um caracter de '2' a '9', o pino correspondente ira alterar sua saida.

      volatile char chr;
      ISR(USART_RX_vect)
      {
      chr = UDR0 - '0';
      digitalWrite(chr, !digitalRead(chr));
      }

      Excluir