Neste post, vou mostrar um exemplo simples de interrupções com MSP430 usando o mspgcc.
Para falarmos de interrupções, vou iniciar com o trecho de um texto que eu li na internet falando sobre o assunto.
Um passo muito importante quando passamos de uma programação básica de microcontroladores para uma programação avançada é a introdução de interrupções em seu códgo. Interrupções são partes de código, como funções, que são executadas quando um evento externo ocorre. Interrupções podem ser usadas para reagir à todos os tipos de entradas externas, incluindo a mudança de estados do pino por meio de um dispositivo externo. Com o uso de interrupções, você dá ao seu código a capacidade de reagir a eventos que acontecem chamando a função de interrupção (interrompendo o código principal), em vez de esperar seu código chegar em um lugar onde ele possa tratar o evento (que é conhecido como “polling”). É uma idéia de programação que pode levar algum tempo para se acostumar, mas o poder que lhe dá em um sistema embarcado vale a pena o esforço.
Fonte: http://www.nerdkits.com/videos/interrupts_and_ps2_keyboard/
Usando como base o exemplo de acionamento do display de sete seguimentos, vamos adicionar ao esquma elétrico dois botões, e no lugar de exibir os valores no display automaticamente em ordem crecente, vamos usar os botões sendo um para incrementar o valor do display e outro para decrementar.
Assim, logo que um botão é pressionado, o processador para o que estava fazendo, guarda o conteúdo do registrador PC, e o conteúdo do registrador SR, para que ele possa retornar, e executa a Rotina de Serviço de Interrupção (ISR – Interrupt Service Routine)
PC [Program Counter] – indica onde estava a execução no momento da interrupção.
SR [Status Register] – armazena bits com informações necessárias para o momento que o microcontrolador retornar ao que estava fazendo.
O esquema elétrico é semelhante ao anterior, apenas inclui os dois botões do tipo push button.
Vamos ao código…
// Inclusão do header para o mspg2231 #include <msp430x20x1.h> // Neste arquivo estão definidas as Rotinas de Serviço de Interrupção #include <signal.h> // Protótipo da funcão Delay void Delay(void); // Vetor de caracteres hexadecimais correspondente a um digito no display char bcd[10] = {0x3f, 0x6, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x7, 0x7f, 0x6f}; // Variável que representa qual digito está sendo mostrado no display volatile int i = 0; // Função principal do programa int main(void) { WDTCTL = WDTPW | WDTHOLD; // Parando o watchdog timer P1DIR = 0xff; // Seta todos os pinos de P1 como saída P1OUT = bcd[0]; // Coloca na porta P1 o caractere do vetor bcd com indice igual a 0 (exibindo 0 no display) P2SEL = 0x00; // Configura a porta 2 (P2) como entrada e saída (I/O) P2DIR = 0x00; // Seta todos os pinos de P2 como entrada (No caso do MSP430G2231 P2.6 e P2.7) P2REN = 0xc0; // Habilita os resistrores nos pinos P2.6 e P2.7 P2OUT = 0xc0; // Seleciona o modo pull-Up para os resistores nos pinos P2.6 e P2.7 P2IE = 0xc0; // Habilita interrupções nos pinos P2.6 e P2.7 P2IES = 0xc0; // Configura a interrupção nos pinos P2.6 e P2.7 na borda de descida P2IFG = 0x00; // Limpa a flag de interrupção da porta P2, informando que não existem interrupções pendentes _BIS_SR(GIE); // Habilita interrupções com mspgcc (General Interrupt Enable) for (;;) { // Loop infinito fica fazendo nada, até que aconteça uma interrupção } } // Definição da Rotina de Serviço de interrupção na porta P2 (Lembrando que este código é para compilar com mspgcc) interrupt(PORT2_VECTOR) PORT2_ISR(void) { // Quando o microcontrolador detecta a interrupção executa o seguinte código // Caso o P2.7 (0x80 = 10000000) ou P2.6 (0x40 = 01000000) estejam pressionados while(P2IN == 0x80 || P2IN==0x40){ switch(P2IN){ // Caso P2.7 tenha sido pressionado case 0x80: // Se i for menor que 9 incrementa o valor de i if(i0) i--; break; } // Coloca na porta P1 o valor do caractere no vetor com indice igual a i P1OUT = bcd[i]; // Gasta um pouco de tempo para que seja perceptivel a mudança dos digitos no display Delay(); } // Limpa a flag de interrupção da porta P2, informando que não existem interrupções pendentes P2IFG = 0x0; } // Função para gastar tempo void Delay(void) { unsigned int dly = 30000; while(--dly); { // Nothing:D } }
Então pessoal, desta vez fiz os comentários no próprio código.
Mais detalhes sobre o o tratamento de interrupções com o mspgcc podem ser encontradas na documentação do projeto em http://mspgcc.sourceforge.net/manual/x918.html.
Para finalizar um vídeo demonstrando como ficou.
Espero que o exemplo seja útil para alguém, e até mais.
Uma coisa importante que nao foi abordada neste tópico: Prioridades das interruption. No MSP430 isso não eh configurável, as prioridades sao fixas, portanto eh muito importante ter conhecimento disso quando estiver trabalhando com multiplas interuptions pois ja tive problemas com isso.
Abraço
Muito obrigado Flávio, eu não sabia disso, vou ler mais sobre o assunto. Valeu pela dica!
Olá, tudo bem, sou estudante do Instituto federal de Poços de Caldas, tenho muito interesse no aprendizado do msp430 porém pouco se tem informações sobre ele bem detalhadas como aqui, há algum site em portugues ainda mais detalhado? Se houver seria muito grato se puder me enviar os links. Muito Obrigado