terça-feira, junho 26, 2007

Controlando um LED com um PIC - Parte II

Nesta parte vamos ver o software do nosso projeto.

Uma vez que o software é bastante simples, vamos desenvolvê-lo em linguagem assembler e usar o ambiente de desenvolvimento MPLab, disponibilizado gratuitamente pela Microchip.

Definido o algorítmo é só pegar o manual de referência do PIC e enfrentar as esquisitices do conjunto de instruções. Alguns pontos a destacar:
  • a execução começa sempre no endereço 0, a interrupção desvia sempre para o endereço 4. No endereço 0 foi colocado um GOTO para desviar para o corpo do programa, que fica após o tratamenteo da interrupção.

  • é preciso tomar cuidado com o fato dos registradores de controle (SFR) estarem armazenados em dois bancos (BANK0 e BANK1). Antes de acessar um registrador de controle é preciso garantir que o banco correto está selecionado.

  • no início da rotina de interrupção é preciso salvar os registradores W e STATUS. Ao final da interrupção estes registradores precisam ser restaurados.

  • o PIC não possui instruções de desvio condicional convencionais. As instruções condicionais são sempre na forma de Skip If, na qual a instrução seguinte é pulada se uma determinada condição for verdadeira.
No inicio do programa deve-se definir a configuração do PIC, que será gravada em uma área especial da Flash:

; Configuração do PIC;
- habilita BrownOut Detect;
- desabilita pino MCLR;
- desabilita Watchdog;
- usa o oscilador interno
__CONFIG _BODEN_ON & _MCLRE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT

Uma variável (MODO_LED) é usada armazenar o modo atual de atuação do LED (APAGADO, ACESO ou PISCANDO). Quando for detectado o pressionamento do botão o modo será avançado para o modo seguinte (circularmente).

; Estados do LED
#define APAGADO 0
#define ACESO 1
#define PISCANDO 2

; Loop principal
PRINC
BTFSS MODO_BOTAO, BOTAO_APERT
GOTO PRINC ; aguarda apertar o botão
BCF MODO_BOTAO, BOTAO_APERT ; limpa indicação
MOVF MODO_LED,W
XORLW APAGADO
BTFSC STATUS,Z
GOTO ACENDER
MOVF MODO_LED,W
XORLW ACESO
BTFSC STATUS,Z
GOTO PISCAR

; Estava piscando, vamos apagar
MOVLW APAGADO
MOVWF MODO_LED
BCF LED
GOTO PRINC

; Estava apagado, vamos acender
ACENDER
MOVLW ACESO
MOVWF MODO_LED
BSF LED
GOTO PRINC

; Estava aceso, vamos piscar
PISCAR
MOVLW PISCANDO
MOVWF MODO_LED
GOTO PRINC

O tratamento do botão possui uma pequena dificuldade: quando o botão é apertado ou solto, por alguns instantes o contato abre e fecha rapidamente. Isto é chamado de 'bounce' (algo como 'quicar'). Para evitar que cada uma destas aberturas/fechamentos seja tratada como um aperta/solta do botão, é preciso aguardar que o sinal do botão fique estável por um certo tempo.

Para fazer o LED piscar e executar o 'debounce' do botão, vamos configurar o Timer 0 do PIC para gerar interrupções periodicamente. O valor que adotei foi aproximadamente 50 milisegundos, o que permite um piscar nítido e fazer o debounce simplesmente exigindo duas leituras iguais em interrupções consecutivas.

; Inicia o timer
BANK0
BCF INTCON,T0IF ; limpa a interrupção do timer
MOVLW .256-CNT_TIMER
MOVWF TMR0 ; programa o timer
BSF INTCON,T0IE
BSF INTCON,GIE ; permite interrupções

O piscar do LED fica bastante simples: na interrupção testamos se o modo atual é piscar; se sim invertemos o sinal no pino do LED.

MOVF MODO_LED,W
XORLW PISCANDO
BTFSS STATUS,Z
GOTO TRATA_BOTAO
MOVLW 0x01
XORWF GPIO,F ; pisca o LED
TRATA_BOTAO

A lógica do botão é um pouco mais complicada. São usados três valores lógicos, armazenados em três bits de uma variável (MODO_BOTAO):

  • o estado do botão na interrupção anterior, que é atualizado ao final de toda interrupção

  • o estado do botão após o debounce, que é atualizado somente quando o estado atual do botão é igual ao estado anterior

  • uma indicação de que o botão foi apertado, que é ligado na interrupção quando o estado após o debounce passa de solto para apertado. Esta indicação é limpa no laço principal do programa, após tratar o acionamento da tecla.


; Controles do estado do botão
#define BOTAO_ANT 0x01 ; este bit indica o estado anterior
#define BOTAO_DEB 0x02 ; este bit tem o valor c/ "debounce"
#define BOTAO_APERT 0x04 ; este botão indica que foi detectado
; um pressionmento do botão

TRATA_BOTAO
BTFSC BOTAO ; testa o botão
GOTO SOLTO

; botao apertado
BTFSC MODO_BOTAO,BOTAO_ANT ; testa leitura anterior
GOTO APERT_10
BSF MODO_BOTAO,BOTAO_ANT ; mudou
GOTO FIM_INT
APERT_10 ; igual a vez anterior
BTFSC MODO_BOTAO,BOTAO_DEB
GOTO FIM_INT ; ja estava apertado
BSF MODO_BOTAO,BOTAO_APERT ; apertou agora
BSF MODO_BOTAO,BOTAO_DEB
GOTO FIM_INT

SOLTO ; botao solto
BTFSS MODO_BOTAO,BOTAO_ANT
GOTO SOLTO_10
BCF MODO_BOTAO,BOTAO_ANT ; mudou
GOTO FIM_INT
SOLTO_10 ; igual a vez anterior
BCF MODO_BOTAO,BOTAO_DEB

O fonte completo está aqui

Na próxima parte vamos encerrar esta série, vendo como montar o circuito e as referências para maiores detalhes.

4 comentários:

Anônimo disse...

Boa noite.

Você tem o código desse projeto em linguagem C para PIC??

Atenciosamente,

Jutai C.S
jutaics@hotmail.com

jr92009 disse...

ola Daniel,



Parabens pela iniciativa...e gostaria de pedir um exemplo de como fazer um led piscar 4 vezes e para apagado em um interfalo de 3 segundo..... detse ja agradeço pela atençao!! Raul Leles

Tiago disse...

Olá amigo

Você pode voltar a disponibilizar o código fonte completo

Obrigado

Daniel Quadros disse...

Tiago,

Está lá nos arquivos do blog no skydrive (icone e link no canto superior direito da página). Algum dia eu saio acertando os links post a post...

Daniel