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.
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.
ResponderExcluirunsigned long baud = 9600; //DEFINE BAUDRATE
Excluirunsigned 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()
{
}
Não é possível utilizar a rotina de interrupção com a função Serial.begin(), pois irá ocorrer um conflito!!
Excluirobrigado 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??
ExcluirISR(USART_RX_vect)
Excluir{
//UDR0 recebe o valor do caracter
if(UDR0=='1')
{
digitalWrite(13, !digitalRead(13));
}
}
Outro Exemplo: quando receber um caracter de '2' a '9', o pino correspondente ira alterar sua saida.
Excluirvolatile char chr;
ISR(USART_RX_vect)
{
chr = UDR0 - '0';
digitalWrite(chr, !digitalRead(chr));
}