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.
Ich fand heraus, dass das Problem darin bestand, dass meine Referenz in der OpenADC()-Funktion nicht richtig gesetzt war. Ich brauchte ADC_REF_VDD_VSS
statt 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();
Fred Hamilton
PeterJ
Jack