Você está na página 1de 3

; CONVERSOR A/D EM ASSEMBLY

; Eu configurei o PIC para trabalhar na resolução máxima do conversor, ou seja, 10 bit


s com o resultado da conversão justificado à direita. O que o meu programa tem que f
azer é muito simples: ele lê a tensão analógica presente no canal AN0/RA0 do PIC e, se e
la ultrapassar 3V, um led ligado ao pino RB7 acende; se ela estiver abaixo de 3V
, o led não acende. É uma simples comparação de maior ou menor e leitura do canal 0 do c
onversor AD.
; Lembrando que, 3V convertido para digital de 10 bits é 614 (decimal) ou 10011001
10 (binário) ou 0x266 (hexadecimal).
#INCLUDE <P16F876.INC> ;arquivo de definições para o PIC em questão
__CONFIG _BODEN_OFF & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _HS_OSC
CBLOCK 0x0070 ;endereço inicial da memória do usuário
ADH
ADL
ENDC ;fim do bloco de memória
#DEFINE BANK0 BCF STATUS,RP0 ;seleciona banco 0 da memória RAM
#DEFINE BANK1 BSF STATUS,RP0 ;seleciona banco 1 da memória RAM
#DEFINE LED PORTB,1

ORG 0x0000 ;endereço inicial de processamento


GOTO INICIO
ORG 0x0004 ;endereço inicial de interrupção
RETFIE ;retorna da interrupção
; INICIO DO PROGRAMA
INICIO
BANK1
MOVLW B'10001110' ;ra0 como entrada analógica e resultado justificado à direita
MOVWF ADCON1
MOVLW B'00000001'
MOVWF TRISA ;define todo o porta como saida, exceto RA0
MOVLW B'00000000'
MOVWF TRISB ;define todo o portb como saida
MOVLW B'00000000'
MOVWF TRISC ;define todo o portc como saida
MOVLW B'10001000'
MOVWF OPTION_REG ;prescaler 1:1 no wdt
;demais configurações irrelevantes
MOVLW B'00000000'
MOVWF INTCON ;interrupções desativadas
BANK0 ;altera para o banco 0
MOVLW B'11000001' ;canal 0, clock interno , AD ligado
MOVWF ADCON0
CALL DELAY
; ROTINA PRINCIPAL
MAIN
CLRF PORTA ;limpa o porta
CLRF PORTB ;limpa o portb
CLRF PORTC ;limpa o portc
CLRF ADH
CLRF ADL
BANKSEL ADRESL
CLRF ADRESL ;limpa parte baixa do registrador do AD
BANKSEL ADRESH
CLRF ADRESH ;limpa parte alta do registrador do AD
GOTO LE_AD ;chama sub-rotina que lê o conversor AD
LE_AD
BANKSEL ADCON0
BSF ADCON0,GO ;inicia conversão
BTFSC ADCON0,GO ;terminou a conversão?
GOTO $-1 ;Não.Então, aguarda terminar
BANKSEL ADRESH
MOVF ADRESH,W
MOVWF ADH ;Guarda resultado (2 bits)
BANKSEL ADRESL
MOVF ADRESL,W
MOVWF ADL ;Guarda resultado (8 bits). Total de 10 bits.
COMPARA ;Se AD for menor do que 614, led não acende. Se AD for maior do que 614, l
ed acende
;Em base hexadecimal: 614 = 0x266 = 1001100110 (10 bits).
;Justificado à direita:
;ADRESL: 01100110 e ADRESH: 00000010.
BCF STATUS,C ;apaga bit de carry do registrador status
MOVLW 0x02
SUBWF ADH,W ;Após esta operação, W = ADH - W
BTFSS STATUS,C ;Testa carry. Qual o resultado?
GOTO MENOR ;Negativo. Então, ADH < 0x02. Desvia
;Positivo. Então, ADH >= 0x02. Desvia
BCF STATUS,C
MOVLW 0x66
SUBWF ADL,W ;Após esta operação, W = ADL - W
BTFSS STATUS,C ;Testa carry. Qual resultado?
GOTO MENOR ;Negativo. Então, ADL < 0x66. Desvia
GOTO MAIOR ;Positivo. Então, ADL >= 0x66. Desvia
MENOR
BANKSEL PORTB ;seleciona o banco correto para o portb
BCF LED ;limpa bit RB1
GOTO LE_AD ;desvia para ler AD novamente
MAIOR
BANKEL PORTB ;seleciona o banco correto para o portb
BSF LED ;seta bit RB1
GOTO LE_AD ;desvia para ler AD novamente
DELAY ;### SUB-ROTINA DE DELAY DE 80us ###
;Fosc = 20MHz => (Tosc = 20MHz/4 = 5MHz => 1/5MHz = 200ns)
;(255 * 200ns) + (150 * 200ns) = 81us
CLRF TMR0 ;limpa o tmr0
BCF INTCON,T0IF ;limpa flag da int. do tmr0
BTFSS INTCON,T0IF ;timer 0 >= 255?
GOTO $-1 ;não, retorna
;sim, terminou
CLRF TMR0 ;limpa o tmr0
BCF INTCON,T0IF ;apaga flag da int. do tmr0
MOVLW (.255-.150)
MOVWF TMR0 ;carrega tmr0 com 105
BTFSS INTCON,T0IF ;timer 0 >= 255?
GOTO $-1 ;não, retorna
;sim, terminou
RETURN ;retorna à pilha
END ;fim do programa
;===============================================================================
============

Você também pode gostar