LIST P=16F887
#include "[Link]"
; Configuración de fusibles
__CONFIG _CONFIG1, _FOSC_INTRC_NOCLKOUT & _WDTE_OFF &
_PWRTE_ON & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF &
_CP_OFF
__CONFIG _CONFIG2, _BOR4V_BOR21V
;***************************
; Variables
;***************************
cblock 0x20
ADC_HIGH ; Parte alta del resultado ADC
TEMP ; Temporal
PWM_WIDTH ; Ciclo de trabajo PWM
CONTADOR ; Contador general
endc
#define VALOR_ADC_50C D'15' ; Valor de ADC a 50°C
#define PWM_MIN D'51' ; Mínimo PWM (20% de 255)
;***************************
; Vectores
;***************************
ORG 0x00
clrf PCLATH
goto INICIO
ORG 0x04
clrf PCLATH
retfie
;***************************
; Programa principal
;***************************
INICIO
; Configurar oscilador interno a 8 MHz
banksel OSCCON
movlw B'01110000'
movwf OSCCON
; Configurar puertos
banksel ANSEL
clrf ANSELH
movlw B'00000001' ; AN0 como analógico
movwf ANSEL
movlw B'00000000'
banksel ADCON1
movwf ADCON1
banksel TRISA
bsf TRISA, 0 ; RA0 como entrada (AN0)
banksel TRISC
bcf TRISC, 1 ; RC1 como salida
banksel PORTC
bcf PORTC, 1 ; RC1 inicialmente apagado
; Configurar ADC
banksel ADCON0
movlw B'00000001' ; ADC ON, canal AN0, Fosc/8
movwf ADCON0
;***************************
; Bucle principal
;***************************
LOOP
call ADC_LECTURA
call CALCULA_PWM
call PWM_MANUAL
goto LOOP
;***************************
; Subrutinas
;***************************
; Lectura del ADC
ADC_LECTURA
call PEQUEÑO_DELAY
banksel ADCON0
bsf ADCON0, GO
ESPERA_ADC
btfsc ADCON0, GO
goto ESPERA_ADC
banksel ADRESH
movf ADRESH, W
banksel ADC_HIGH
movwf ADC_HIGH
return
; Calcular ciclo de trabajo PWM
CALCULA_PWM
banksel ADC_HIGH
movf ADC_HIGH, W
sublw VALOR_ADC_50C ; W = 26 - ADC_HIGH
btfss STATUS, C
goto PWM_APAGADO ; Si ADC_HIGH > 26, apagar
; Invertir proporcionalmente
movf ADC_HIGH, W
movwf TEMP
movlw D'255'
subwf TEMP, W
movwf PWM_WIDTH
; Verificar mínimo PWM
movf PWM_WIDTH, W
sublw PWM_MIN
btfss STATUS, C
goto PWM_OK
movlw PWM_MIN
movwf PWM_WIDTH
PWM_OK
return
PWM_APAGADO
clrf PWM_WIDTH
return
; PWM "manual" en RC1
PWM_MANUAL
banksel PWM_WIDTH
movf PWM_WIDTH, W
btfss STATUS,Z
goto PWM_ON
; PWM_WIDTH == 0 ? apagar LED
banksel PORTC
bcf PORTC,1
call RETARDO_COMPLETO
return
PWM_ON
bsf PORTC,1
movwf CONTADOR
CICLO_ON
call PEQUEÑO_DELAY
decfsz CONTADOR,F
goto CICLO_ON
bcf PORTC,1
movlw D'255'
subwf PWM_WIDTH,W
movwf CONTADOR
CICLO_OFF
call PEQUEÑO_DELAY
decfsz CONTADOR,F
goto CICLO_OFF
return
; Retardo corto
PEQUEÑO_DELAY
nop
nop
return
; Retardo completo de periodo PWM
RETARDO_COMPLETO
movlw D'255'
movwf CONTADOR
RETRASO
call PEQUEÑO_DELAY
decfsz CONTADOR,F
goto RETRASO
return
;***************************
; Fin
;***************************
END