bucle de conversión A / D infinitamente

0

Dejé de usar un nuevo microcontrolador PIC y tengo un nuevo problema.

Estaba usando el convertidor A / D de mi PIC18F46j50 para atrapar 4 botones en 1 PIN (RB2), y funcionó bien. Pero como soldé un oscilador de 32.768 kHz para Timer1, ya no funciona.

unsigned int HAL_SWITCH_GetValADC(void){
    ADCON0bits.VCFG0 = 0;
    ADCON0bits.VCFG1 = 0;
    ADCON0bits.CHS = 0b1000;
    ADCON1bits.ADFM = 1;        // A/D Result format select bit : right justified
    ADCON1bits.ADCAL = 0;       // A/D Calibration bit
    ADCON1bits.ACQT = 0b111;    // A/D Acquisition Time 12 Tad = 12us
    ADCON1bits.ADCS = 0b001;    //Tad = 1us (Fosc/8)
    ADCON0bits.ADON = 0b01;     // A/D enable

    PIR1bits.ADIF = 0; //make sure A/D Int not set
    ADCON0bits.GO=1; //and begin A/D conv.
    while(!PIR1bits.ADIF);
    NOP();
    return (((unsigned int) ADRESH << 8) | ADRESL);
}

Al usar el punto de interrupción, determiné que el problema proviene del bucle while, cuando depuro paso a paso, funciona bien, pero el programa nunca se detiene si el punto de interrupción está en NOP ();

se produjo un error como "No se encontraron líneas de código fuente en la PC actual" + pocas direcciones, principalmente las de las instrucciones interrumpidas ... No sé si hay un enlace.

También alguien me dijo que cambiara el reloj usado por el convertidor A / D ... ¿Cómo puedo hacerlo?

Pida más código si puede ayudar.

    
pregunta Nico Balas

2 respuestas

0

ADCON1bits.ACQT = 0b111 < - eso no es 12 Tad, sino 20 Tad (según la hoja de datos), que se traduce aproximadamente a 20us. Intente usar 0b101, por el valor que está tratando de alcanzar. Intente configurar el bit 6 del registro ADCON1 (ADCAL, responsable de la calibración automática) en 1 y vuelva a ejecutar su código. También ha puesto un punto y coma después del bucle while, lo que no parece ser una buena idea en este momento. ¿No ibas por algo más como:

while(!PIR1bits.ADIF) {
NOP(); } return (((unsigned int) ADRESH << 8) | ADRESL);

EDITAR: ¿Qué es exactamente la función nop? ¿Es el uso literal de instrucciones de ensamblado nop o es una función de retardo? Otra cosa, probablemente deberías poner toda la rutina A / D guardando el resultado en un bucle, ya que es un convertidor A / D de 10 bits. La hoja de datos PIC18F46J50 sugiere algo como esto (página 400):

#include "p18cxxx.h"
#define COUNT 500 //@ 8MHz = 125uS.
#define DELAY for(i=0;i<COUNT;i++)
#define RCAL .027 //R value is 4200000 (4.2M)//scaled so that result is in//1/100th of uA
#define ADSCALE 1023 //for unsigned conversion 10 sig bits
#define ADREF 3.3 //Vdd connected to A/D Vr+
int main(void)
{
 int i;
 int j = 0; //index for loop
 unsigned int Vread = 0;
 double VTot = 0;
 float Vavg=0, Vcal=0, CTMUISrc = 0; //float values stored for calcs
//assume CTMU and A/D have been setup correctly
//see Example 25-1 for CTMU & A/D setup
setup();
CTMUCONHbits.CTMUEN = 1; //Enable the CTMU
CTMUCONLbits.EDG1STAT = 0; // Set Edge status bits to zero
CTMUCONLbits.EDG2STAT = 0;
 for(j=0;j<10;j++)
 {
 CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
 DELAY; //wait 125us
 CTMUCONHbits.IDISSEN = 0; //end drain of circuit

 CTMUCONLbits.EDG1STAT = 1; //Begin charging the circuit
 //using CTMU current source
 DELAY; //wait for 125us
 CTMUCONLbits.EDG1STAT = 0; //Stop charging circuit

 PIR1bits.ADIF = 0; //make sure A/D Int not set
 ADCON0bits.GO=1; //and begin A/D conv.
 while(!PIR1bits.ADIF); //Wait for A/D convert complete

 Vread = ADRES; //Get the value from the A/D
 PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
 VTot += Vread; //Add the reading to the total
 }

 Vavg = (float)(VTot/10.000); //Average of 10 readings
 Vcal = (float)(Vavg/ADSCALE*ADREF);
 CTMUISrc = Vcal/RCAL; //CTMUISrc is in 1/100ths of uA
}
    
respondido por el Sven
1

Una forma que conozco de reconocer si la conversión está completa es leer el bit GO / DONE de ADCON0. El bit baja cuando se completa la conversión. Así que puedes usar

ADCON0bits.GO=1;
while(ADCON0bits.GO);

Si aún desea utilizar ADIF, debe asegurarse de haber habilitado la interrupción ADC. También verifique si las clavijas del oscilador tienen algo de voltaje o si están bien soldadas. El voltaje debe estar alrededor de 2.3V a 3V, no exactamente pero es un valor estable cuando se mide con un voltímetro de CC.

Buena suerte.

    
respondido por el Rohit Biradar

Lea otras preguntas en las etiquetas