Lesen des analogen Eingangs pic18

Ich versuche, einen analogen Eingang auf einem PIC18F65J11 zu lesen, und ich habe Probleme. Ich glaube nicht, dass der Pin richtig eingerichtet ist, weil ich eine 0 für den eingelesenen Wert bekomme und der Eingang mit etwa 1 V gemessen wird (kann aber bis zu 3 V erreichen). Ich möchte Folgendes verwenden: Hier ist mein Code:

#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);
    }
}

Was mache ich falsch oder fehlt? Ich vermute, dass es der OpenADC()-Teil ist, der falsch sein könnte. Ich habe es mit Fosc / 8, Ergebnis in niedrigstwertigen Bits, 12 Tad, Kanal 0 (AN0-Pin), Interrupt aus, VDD als höchste Grenze und 0, damit alle analogen Pins analog sind.

Alle ADCs benötigen eine Referenzspannung. Ich bin mit dieser Hardware nicht vertraut, daher bin ich mir nicht sicher, ob die Referenzspannung intern ist (stellen Sie in diesem Fall sicher, dass sie aktiviert und ungleich Null ist) oder extern (stellen Sie in diesem Fall sicher, dass Sie eine geeignete Referenzspannung anlegen).
Etwas, das Sie überprüfen müssen, ist, dass Sie Avss und Avdd verbunden haben, Sie brauchen das, obwohl Sie Vdd als Referenz verwenden.
Ich hatte AVdd bereits mit 3,3 V und AVss mit GND verbunden. Hardwaretechnisch sollte es meiner Meinung nach kein Problem geben.

Antworten (1)

Ich fand heraus, dass das Problem darin bestand, dass meine Referenz in der OpenADC()-Funktion nicht richtig gesetzt war. Ich brauchte ADC_REF_VDD_VSSstatt ADC_VREFPLUS_VDD. Hier ist der richtige Weg, um einen A/D-Wert zu lesen. Dieser Teil geht in die in der Frage gezeigte While(1)-Schleife.

// 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();