Lectura de entrada analógica pic18

3

Estoy intentando leer una entrada analógica en un PIC18F65J11, y tengo problemas. No creo que el pin esté configurado correctamente porque obtengo un 0 por el valor que leo, y la entrada se mide en aproximadamente 1 V (pero puede llegar hasta 3 V). Quiero usar Aquí está mi código:

#include "p18f65j11.h"
#include <adc.h>

/**CONFIGURATION **************************************************/
/* Device Configuration */
#pragma config XINST = OFF  // Turn off extended CPU instructions
#pragma config FOSC = HSPLL // HS oscillator will PLL that multiplies oscillator frequency by 4 (system clock is running at 16 MHz)
#pragma config FOSC2 = ON   // System clock selected by FOSC1:FOSC0 (used #config to set FOSC to HSPLL) 
#pragma config DEBUG = ON   // Background debugger enabled; RB6 and RB7 are dedicated to In-Circuit Debug.
#pragma config WDTEN = OFF  // Disable watchdog timer.
#pragma config WDTPS = 8    // Watchdog timer poscaler select bits is 1:8 (not important b/c watchdog timer disabled).
#pragma config STVREN = OFF // Reset on stack overflow/underflow disabled.
#pragma config CP0 = OFF    // Program memory is not code-protected
#pragma config IESO = ON   // Oscillator Switchover mode disabled.
#pragma config FCMEN = OFF  // Fail-Safe Clock Monitor disabled.
#pragma config CCP2MX = DEFAULT // ECCP2/P2A multiplexed with RC1 instead of RE7 pin (doesn't matter b/c not using ECCP, which is pwm output)

int myVoltage;

void main(void) 
{
    myVoltage = 0;

    // Configure clock registers (FOSC is set to HSPLL)
    OSCCONbits.SCS1 = 0;    // SCS1:SCS0 = 00 means use primary
    OSCCONbits.SCS0 = 0;    // clock source (CPU divider output) if FOSC2 is on (FOSC2 is indeed on from the #pragma config above)
    OSCCONbits.IRCF2 = 1;   // IRCF2:IRCF0 = 110 means the internal oscillator is set to 4 MHz
    OSCCONbits.IRCF1 = 1;
    OSCCONbits.IRCF0 = 1;
    OSCCONbits.IDLEN = 0;   // on SLEEP instruction, device enters sleep mode instead of idle mode
    OSCTUNEbits.PLLEN = 1;  // enable PLL (4x multiplier), so system clock is 4 * 4 MHz = 16 MHz
    // Basically, I've just set it to use primary oscillator, told it the oscillator is 
    // 4 MHz, and told it to enable PLL so that my system clock is 16 MHz.

    // Initialize Port A
    TRISA &= 0;             // set Port A as outputs
    LATA &= 0;              // all pins outputting 0
    TRISAbits.RA0 = 1;      // set pin AN0 as input to read voltage

    while(1) {
        OpenADC(ADC_FOSC_8 & ADC_RIGHT_JUST & ADC_12_TAD, ADC_CH0 & ADC_INT_OFF & ADC_VREFPLUS_VDD, 0);
        Delay10TCYx( 5 );
        ConvertADC();               // initiate conversion of sensor1 @ AN0
        while(BusyADC());           // waiting to complete conversion
        myVoltage = ReadADC();      // read the result of sensor1 @ AN0
        CloseADC();
        printf("%i volts \n\r", myVoltage);
    }
}

¿Qué estoy haciendo mal o falta? Sospecho que es la parte OpenADC () que puede estar mal. Lo tengo usando Fosc / 8, resulta en bits menos significativos, 12 Tad, canal 0 (pin AN0), interrupción desactivada, VDD como el límite más alto y 0 para que todas las patillas analógicas sean analógicas.

    
pregunta Jack

1 respuesta

1

Descubrí que el problema era que mi referencia no estaba configurada correctamente en la función OpenADC (). Necesitaba ADC_REF_VDD_VSS en lugar de ADC_VREFPLUS_VDD . Aquí está la forma correcta de leer un valor A / D. Esta parte va dentro del bucle while (1) que se muestra en la pregunta.

// Constraints: A/D acquisition time must be >= 2.4 us (data sheet p264, Equation 20-3), conversion time (Tad) must be >= 0.7 us (data sheet p385, Table 26-26)
// Given that our Fosc = 4 MHz, which means Tosc = 1/Fosc = 1/4 MHz = 0.25 us,
// we must have at least 4 * Tosc = 1 us of conversion time (Tad).
// This is why we choose ADC_FOSC_4.
// Since Tad = 1 us, and we need a minimum acquisition time of of 2.4 us,
// we choose acquisition time to be 4 * Tad, which is ADC_4_TAD
// Use channel 0 (ADC_CH0) to read AN0
OpenADC(ADC_FOSC_4 & ADC_RIGHT_JUST & ADC_4_TAD, ADC_CH0 & ADC_INT_OFF & ADC_REF_VDD_VSS, 0);
Delay10TCYx( 5 );        // allow for time to open adc (don't know if need this much)
ConvertADC();            // initiate conversion of sensor1 @ AN0
while(BusyADC());        // waiting to complete conversion
myVoltage = ReadADC();  // read A/D value. math needs to be done to convert to voltage
CloseADC();
    
respondido por el Jack

Lea otras preguntas en las etiquetas