PIC16F88 - compare los resultados de ADC con un valor constante

0

Estoy tratando de escribir mi primer programa en ensamblador para PIC16F886. El programa debe hacer lo siguiente:

  • Lee el valor de ADC en el canal AN0
  • Si el valor es menor que 128, apague el LED
  • De lo contrario, encienda el LED

El esquema es bastante simple:

Yaquíestámicódigodeensamblaje.

list p=16f886 ; list directive to define processor #include <p16f886.inc> ; processor specific variable definitions __CONFIG _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT __CONFIG _CONFIG2, _WRT_OFF & _BOR21V org 00 ;start at 0x00 VALUE EQU 0x80 ;value to compare adc results cblock 0x20 RESULTLO ;ADC 8-bit result endc port_config movlw b'11111110' ;set RB0 on PORTB to output movwf TRISB start bsf PORTB, 0 ;turn LED on adc_config BANKSEL ADCON1 movlw 0x00 ;left justify MOVWF ADCON1 ;Vdd and Vss as Vref BANKSEL TRISA ; BSF TRISA,0 ;Set RA0 to input BANKSEL ANSEL ; BSF ANSEL,0 ;Set RA0 to analog adc_sample BANKSEL ADCON0; MOVLW b'11000001' ;ADC Frc clock, MOVWF ADCON0 ;AN0, On BSF ADCON0,GO ;Start conversion BTFSC ADCON0,GO ;Is conversion done? GOTO $-1 ;No, test again BANKSEL ADRESH MOVF ADRESH,W ;Read lower 8 bits MOVWF RESULTLO ;Store in GPR space ; if RESULT <= VALUE movf RESULTLO,w addlw 255 - VALUE skpnc goto led_off ; if RESULT > VALUE movf VALUE,w addlw 255 - RESULTLO + 1 skpnc goto led_on ;loop goto adc_sample led_on bsf PORTB, 0 goto adc_sample led_off bcf PORTB, 0 goto adc_sample end

Espero que el led se encienda / apague cuando cambio la resistencia de la olla, pero en cambio el led permanece encendido.

Actualización: sospecho que tiene algo que ver con la forma en que comparo RESULT y VALUE desde que recibí la siguiente advertencia durante la compilación: Argument out of range. Least significant bits used.

Actualización: Como mencioné en los comentarios, el esquema se toma directamente de Proteus. En el dispositivo real, el controlador se alimenta desde una fuente de 5 V, debe tener una resistencia limitadora en serie con un led (a menos que conduzca el mcu desde un voltaje más pequeño) y nMCLR está conectado a + 5V a través de un Resistencia 5k.

    
pregunta Ashton H.

3 respuestas

1

He logrado arreglar mi código eventualmente. Tenía los siguientes problemas:

  1. Olvidé agregar un pequeño retraso para que ADC se inicialice correctamente
  2. PORTB no se inicializó correctamente
  3. La rutina de comparación no funcionó como esperaba
    list        p=16f886    ; list directive to define processor
    #include    <p16f886.inc>   ; processor specific variable definitions

    __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
    __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

    org 00                      ;start at 0x00

VALUE EQU 0x80                  

    cblock  0x20
        RESULTHI                ;ADC 8-bit result
    endc

port_config
    bsf    STATUS,RP0           ;select Registers at Bank 1
    movlw b'11111111'           ;set PORTA to input
    movwf TRISA
    movlw b'11111110'           ;set RB0 on PORTB to output
    movwf TRISB
    bcf    STATUS,RP0           ;select Registers at Bank 0

start
    bsf PORTB, 0                ;turn LED on

adc_config
    BANKSEL ADCON1              
    movlw 0x00                  ;left justify
    MOVWF ADCON1                ;Vdd and Vss as Vref
    BANKSEL TRISA               ;
    BSF TRISA,0                 ;Set RA0 to input
    BANKSEL ANSEL               ;
    BSF ANSEL,0                 ;Set RA0 to analog
    BANKSEL ADCON0;
    MOVLW b'11000001'           ;ADC Frc clock,
    MOVWF ADCON0                ;AN0, On
    call delay                  ;Allow some time to settle
    CLRF ADRESH

adc_sample
    BSF ADCON0,GO               ;Start conversion
    BTFSC ADCON0, GO            ;Is conversion done?
    GOTO $-1                    ;No, test again
    call delay                  ;Allow some time to settle
    BANKSEL ADRESH
    MOVF ADRESH,W               ;Read high 8 bits
    MOVWF RESULTHI              ;Store in GPR space

compare_result
    clrc
    movlw VALUE
    subwf RESULTHI,w
    btfsc STATUS, Z             ;if (RESULTHI <= VALUE)
    goto led_off                ;turn led off
    btfsc STATUS, C
    goto led_on                 ;otherwise: turn led on
    goto led_off

    goto adc_sample             ;loop forever

led_on
    bsf PORTB, 0
    goto adc_sample
led_off
    bcf PORTB, 0
    goto adc_sample

delay
COUNT1 equ 0xFF
loopl0
    decfsz COUNT1,1
    goto loopl0
    return

    end
    
respondido por el Ashton H.
3

Está configurando el bit ADFM en ADCON1, que, como indican sus comentarios, justifica el resultado. Esto hace que los bits se almacenen de la siguiente manera:

    (ADRESH)  7 6 5 4 3 2 1 0     (ADRESL)  7 6 5 4 3 2 1 0
   10-bit ADC reading:    9 8               7 6 5 4 3 2 1 0

Luego lees los 8 bits bajos del resultado, ADRESL. Nunca lea el byte alto, ADRESH, que contiene los dos bits superiores del resultado. Así los estás tirando, que son los más significativos (literalmente). Cuando tu bote alcanza el punto medio, el bit superior del resultado cambia, pero nunca lo ves.

En su lugar, desea justificar a la izquierda el resultado, configurando ADFM en 0 y leer solo los 8 bits superiores (ADRESH). Tu prueba de 128 ahora es válida. No hay daño en tirar los 2 bits más bajos en ADRESL.

                (ADRESH)  7 6 5 4 3 2 1 0    (ADRESL)  7 6 5 4 3 2 1 0
   10-bit ADC reading:    9 8 7 6 5 4 3 2              1 0
    
respondido por el tcrosley
0

Hay algunos problemas serios con tu circuito:

  1. Olvidaste encender el PIC. En realidad, los pines de alimentación y de tierra ni siquiera se muestran. Obviamente algo está mal aquí.

  2. No hay nada que limite la corriente a través del LED. Los LED verdes generalmente caen alrededor de 2.1 V. Intentar expulsarlo de un voltaje más alto causará una corriente excesiva a través del LED o una corriente excesiva en el pin del puerto. Dependiendo de qué es exactamente lo que finalmente conecte para la alimentación, eso también puede hacer que se colapse la fuente de alimentación completa, posiblemente reiniciando el PIC.

    Los LED T1-3 / 4 comunes están clasificados para 20 mA, pero serán lo suficientemente brillantes en un entorno de oficina a la mitad de eso. Digamos que eventualmente alimenta el PIC desde una fuente rígida de 5 V, luego desea una resistencia que caiga 5V - 2.1V = 2.9V a 10 mA. (2,9 V) / (10 mA) = 290, por lo que el valor común de 300 debería proporcionarle un resultado claramente visible sin llevar el LED ni el PIC a sus límites.

  3. No hay límite de derivación, incluso si mágicamente existieran conexiones de alimentación en algún lugar.

Hasta que estas cosas se solucionen, no tiene sentido pensar en el firmware.

    
respondido por el Olin Lathrop

Lea otras preguntas en las etiquetas