INTERRUPÇÕES DO PIC
As interrupções são muito utilizadas no mundo dos microcontroladores. Um exemplo típico são nossos microcomputadores PC. Sempre que pressionamos uma tecla, uma interrupção é gerada para o microprocessador, solicitando o tratamento desta. Assim, o PC não é obrigado a varrer constantemente o teclado em busca de uma tecla. Porém é claro que para que isso seja feito, “alguém ou alguma coisa” deve fazer esta varredura por ele. Isso é feito por um microcontrolador dedicado, interno em todos os teclados de PC. Assim temos a geração de uma interrupção no processamento central por parte de um “periférico”.
No caso do PIC16F877A existem as seguintes interrupções:
Interrupção por overflow do Timer0;
Interrupção RB (mudança de estado das portas B);
Interrupção externa;
Interrupção de conversão analógico/digital;
Interrupção de transmissão de dados da porta serial (RS232);
Interrupção de recepção de dados da porta serial (RS232);
Interrupção por overflow do Timer1;
Interrupção por comparação do Timer2;
Interrupção do módulo CCP1 e CCP2;
Interrupção de atividade da comunicação SPI ou I2C;
Interrupção de colisão de dados do barramento;
Interrupção de escrita da EEPROM;
Interrupção de evento do comparador.
Em todas as interrupções é necessário habilitar as interrupção global e interrupção dos periféricos(exceto algumas), configurando o seguinte registro:
GIE: Habilita a interrupção global:
0 - Desabilitado
1 - Habilitado
PEIE: Habilita a interrupção dos periféricos:
0 - Desabilitado
1 - Habilitado
Interrupção por Overflow do TIMER0
Esta interrupção ocorre quando acontece o overflow do TIMER0, ou seja, quando a contagem do TIMER0 estoura de 255 para 0.
O bit que habilita essa interrupção é o INTCON.TMR0IE - (habilita com 1).
A flag de sinalização dessa interrupção é o INTCON.TMR0IF- (habilita com 1).
Interrupção RB ou interrupção por mudança de estados da Porta B
Esta interrupção ocorre quando qualquer um dos pinos (RB4 - RB7) muda de estado.
O bit que habilita essa interrupção é o INTCON.RBIE - (habilita com 1).
A flag de sinalização dessa interrupção é o INTCON.RBIF - (habilita com 1).
Interrupção Externa
Esta interrupção ocorre quando a entrada do pino RB0/INT recebe um sinal de nivel logico 1.
O bit que habilita essa interrupção é o INTCON.INTE - (habilita com 1).
A flag de sinalização dessa interrupção é o INTCON.INTF - (habilita com 1).
Outros registros que configura as demais interrupções:
Interrupção de conversão do módulo ADC
Esta interrupção ocorre quando a conversão analógico/digital foi concluída.
O bit que habilita essa interrupção é o PIE1.ADIE - (habilita com 1).
A flag de sinalização dessa interrupção é o PIR1.ADIF - (habilita com 1).
Interrupção de transmissão de dados RS232
Esta interrupção quando houver uma transmissão de dados no canal da porta serial.
O bit que habilita essa interrupção é o PIE1.RCIE - (habilita com 1).
A flag de sinalização dessa interrupção é o PIR1.RCIF - (habilita com 1).
Interrupção por overflow do TIMER1
Esta interrupção ocorre quando acontece o overflow do TIMER1, ou seja quando a contagem estoura de 65536 para 0.
O bit que habilita essa interrupção é o PIE1.TMR1IE - (habilita com 1).
A flag de sinalização dessa interrupção é o PIR1.TMR1IF - (habilita com 1).
Interrupção por comparação entre TMR2 e PR2
Esta interrupção ocorre quando há uma comparação entre o registro TMR2 e o registro PR2.
O bit que habilita essa interrupção é o PIE1.TMR2IE - (habilita com 1).
A flag de sinalização dessa interrupção é o PIR1.TMR2IF - (habilita com 1).
Interrupção do módulo CCP1 e CCP2
Ocorre quando houver uma captura ou comparação do módulo correspondente.
O bit que habilita essa interrupção CCP1 é o PIE1.CCP1IE - (habilita com 1).
A flag de sinalização dessa interrupção CCP1 é o PIR1.CCP1IF - (habilita com 1).
O bit que habilita essa interrupção CCP2 é o PIE2.CCP2IE - (habilita com 1).
A flag de sinalização dessa interrupção CCP2 é o PIR2.CCP2IF - (habilita com 1).
Interrupção por colisão de dados do barramento
Esta interrupção ocorre quando acontece uma colisão nos dados no barramento do MCU.
O bit que habilita essa interrupção é o PIE2.BCL1IE - (habilita com 1).
A flag de sinalização dessa interrupção é o PIR2.BCL1IF - (habilita com 1).
Interrupção de operação de escrita na EEPROM
Esta interrupção ocorre quando houver uma ação de escrita na EEPROM.
O bit que habilita essa interrupção é o PIE2.EE1IE - (habilita com 1).
A flag de sinalização dessa interrupção é o PIR2.EE1IF - (habilita com 1).
Interrupção do Comparador
O bit que habilita essa interrupção é o PIE2.CMIE - (habilita com 1).
A flag de sinalização dessa interrupção é o PIR2.CMIF - (habilita com 1).
Exemplo com uma interrupção:
void interrupt() { ...; PIR1.TMR1IF = 0; }
Exemplo com duas interrupções:
void interrupt() { if(PIR1.TMR1IF) { ...; // atendimento da interrupção de TIMER1 PIR1.TMR1IF = 0; } if(PIR1.TXIF) { ...; // atendimento da interrupção de Transmissão pela UART PIR1.TXIF = 0; } }
Oi, não entendi direito. Depois que eu habilitar as interrupções posso escrever o programa todo normalmente e criar uma subrotina que, ao gerar a interrupção, o programa se desvia para ela? e depois é só botar um return no fim dessa sub-rotina que ele volta pra onde estava no programa?
ResponderExcluirObrigado
Voce está programando em assembly? Porque pra sair da rotina de interrupção utiliza-se a instrução RETFIE
ExcluirNo caso estou programando em C, no CCS. Não entendi direito onde eu crio a rotina de interrupção dentro do programa e o que acontece quando ocorre a interrupção (quando o pic detecta).
Excluir//Cria-se a rotina da interrupção
Excluir#int_EXT //identifica a interrupção( timer0, externa, etc... )
void rotina_isr()
{
//seu código
}
//Dentro da rotina principal vc deve ativar a int. global e a int. desejada
void main()
{
enable_interrupts(global); //habilita int. global
enable_interrupts(int_ext); //habilita a interrupção, no caso, habilita a int. externa
while(TRUE)
{
//código atual
}
}
Quando ocorre uma interrupção, o PIC deixa de executar o código atual , pra executar o código da rotina de interrupção. Apos executada, volta ao código atual.
Criei um programa simples e deu certo mas, por algum motivo, ele funciona só uma vez. botei um pushbutton no rb0 com pull-down de 10k e fiz ele acender um led por um segundo, mas ai só funciona de novo quando eu desligo. também usei o clear_interrupt (int_ext).
ExcluirMuito obrigado, seu blog ajuda muito :)
Só funcionou uma vez provavelmente porque você não limpou a flag de interrupção. No exemplo que ele deu do timer 1, a flag era "PIR1.TMR1IF = 0;" tem que ver qual interrupção voce usou e limpar a flag na saída da interrupção para que ela possa ocorrer novamente.
ExcluirEu posso estar enganado mas acho que o CCS já limpa a flag automaticamente, sem precisar incluir a instrucao clear_interrupt()
ExcluirOla, eu estou fazendo um projeto de despertador em PIC, que no caso o despertador irá parar de tocar a buzina, quando houver a mudança em uma entrada de 1 para 0 ou de 0 para 1.
ResponderExcluirNo caso, eu usaria essa técnica que você mostrou ai?
Obrigado
Ola gostaria de saber quando ocorre a interrupcao no codigo atual ele volta de onde parou?
ResponderExcluirsim.
ExcluirNo momento que ocorre a interrupção, o PIC salva o endereço da próxima instrução que iria executar na pilha; executa então a rotina de interrupção; recupera o endereço salvo na pilha e volta a executar as instruções a partir desse endereço.
Parabéns pelo artigo, muito bom.
ResponderExcluirBom dia para todos,que Deus ilumine vossas mentes.
ResponderExcluir