PIC - ADC - ¿Valor negativo? - ¿Configuraciones erróneas?

2

Estoy intentando leer una entrada analógica con mi PIC18F66K22 utilizando ADC. Pero el valor supuestamente de 10 bits a menudo llega a valores como 63.241. Descubrí que un valor negativo (imprimir como no firmado) produce el mismo comportamiento.

Creo que podría haber algún problema con la configuración de mi ADC. Mi PIC está cronometrado por defecto (8Mhz). El rango de ADC debe ser de 0v a 2,5v, pero no tiene que ser tan preciso.

Parece que no puedo encontrar la configuración ADC correcta, creo. Estoy usando el compilador XC8 con la biblioteca adc.h que estaba en MPLAB X IDE.

A continuación se muestra el código (hice un nuevo proyecto tot test, con código simplificado). Primero, el adc.c, creo que la configuración es incorrecta y un error en la lectura debería ser fácil de ver.

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

void adcSetup()
{
   OpenADC (
           ADC_FOSC_8          &
           ADC_RIGHT_JUST       &
           ADC_20_TAD,
           ADC_CH4              &
           ADC_INT_OFF          &
           ADC_REF_VDD_VDD      &
           ADC_REF_VDD_VSS,
           ADC_CH4
           );
   ENABLE_AN4_ANA();
   SetChanADC(ADC_CH4);
}

//TODO ADC with interrupts

unsigned int adcGet(void)
{
   ConvertADC();
   while(BusyADC()){}
   return ReadADC();
}

también mi main.c, los otros archivos xport no son tan interesantes y parecen funcionar bien. No estoy seguro de mi conversión de uint a 'c-string' en la función void buttonHandle(void)

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <p18f66k22.h>
#include <delays.h>
#include <usart.h>

#include "defines.h"
#include "configuration-bits.h"
#include "xport.h"
#include "adc.h"

#define __delay_us(x) _delay((unsigned long)((x)*(8000000/4000000UL)))
#define __delay_ms(x) _delay((unsigned long)((x)*(8000000/4000UL)))

volatile char RxBuf[] = "                                        ";
volatile int RxI = 0;
volatile bool RxMessage = false;
volatile bool ButtonPressed = false;

void SetupRegisters(void);
void SetupInterrupts(void);
void interrupt HighISR(void);
void interrupt low_priority LowISR(void);
void delay_ms(unsigned int x);
void buttonHandle(void);
void messageHandle(void);

void SetupInterrupts(void)
{   
    INTCONbits.GIE  = 1;                //Global interrupt enable
    RCONbits.IPEN   = 1;                //Enable priority interrupts
    INTCONbits.GIEH = 1;                //Global interrupt enable High
    INTCONbits.GIEL = 1;                //Global interrupt enable Low
    INTCONbits.PEIE = 1;                //Peripheral Interrupt Enable bit
    INTCONbits.PEIE_GIEL = 1;           //Peripheral Interrupt Enable?

    INTCON3 =   0b00000000;             //Clear intcon. INT1 and INT2 are now low priority
    INTCON3bits.INT1E = 1;              //Enable int1 (BUTTON)
}

void SetupRegisters(void)
{
            //76543210
    TRISA = 0b10101110;     //7:RFID en2 6:x 5:POWER_LEVEL(analog) 4:PWRKEY 3:SW_CHRG 2:SW_FAULT 1:EXT_INP
    TRISBbits.TRISB1 = 1;   //BUTTON INPUT
    TRISEbits.TRISE3 = 0;   //XPort RESET
    TRISGbits.TRISG3 = 1;   //LDO pwrgd (input)
    TRISGbits.TRISG4 = 0;   //LDO shdn  (ldo to toggle xport)
}

/* Main */
int main() {
    //---Set up Registers/interrupts of PIC---
    //See defines.h for al macros for LED_IN and other pin-renames.
    SetupRegisters();       //Registers...
    SetupInterrupts();      //Interrupts (button/uart)
    adcSetup();             //ADC for power-detection (POWER-LEVEL)

    //---Set up peripherals---
    xportSetup();           //Using xport as debugging help.
    xportEnable();          //Switch ldo to enable it.

   while(true){
        if(RxMessage){
            messageHandle();
        }else if(ButtonPressed){
            buttonHandle();
            ButtonPressed = false;
        }
    }
   return 0;
}


void interrupt high_priority HighIsr(void)    //High priority interrupt
{
    if(PIR3bits.RC2IF){//USART INTERRUPT
        RxBuf[RxI] = RCREG2;
        if(RxBuf[RxI] == ';'){//TODO or full
            RxMessage = true;
        }
        RxI++;
    }else{
        xportSendText("High - unhandled interrupt");
    }
}

void interrupt low_priority LowIsr(void)    //Low priority interrupt
{
    if(INT1IF){                 //Button interrupt
        ButtonPressed = true;   //Set flag (handled in main)
        INT1IF = false;         //clear interrupt flag afterwards  to avoid hardware bounce re-interrupt
    }else{                      //Warning for unhandled interrupt
        xportSendText("[ERROR] Low - unhandled interrupt!");
    }
}

void delay_ms(unsigned int xc)
{
    do
    {
        xc--;
        __delay_ms(1);
    }
    while(xc  > 0);
}

void buttonHandle(void){
    delay_ms(100);
    if(!BUTTON){
    xportSendText("Button pressed");

    //ADC DEBUG
    char buffer[] = "                   ";
    sprintf (buffer, "ADC: %u", adcGet());
    xportSendText(buffer);

    //RX DEBUG
    xportSendText("RxBuf: ");
    xportSendText(RxBuf);

    //XPORT debug
    xportDebug();
    }
}

void messageHandle(void){
    xportSendText(RxBuf);                                           //Send/Handle the buffer
    strcpy(RxBuf, "                                        ");      //Empty the buffer!
    RxI = 0;                                                        //Start buffer at pos 0 again;
    RxMessage = false;                                              //Reset the flag
}

Básicamente estoy recibiendo texto de uart en una interrupción. E imprimiendo debug / adc cuando se haya establecido un indicador de botón (por la interrupción del botón)

Esta es mi salida después de presionar el botón algunas veces: Como puedes ver, el adc no es muy persistente. Aunque lo tenía conectado a la fuente de alimentación (que no debería (y no debe) dejar caer tanto).

    
pregunta Paul

2 respuestas

1

Sé que los ejemplos y las bibliotecas existen para intentar guardar el trabajo, pero a menudo me resulta útil no usarlas al principio mientras verifico que mi comprensión y la hoja de datos son correctas y que el chip no está roto. (Por lo general, el problema es mi comprensión).

Entonces, sin usar la biblioteca:

  • Establezca todos los registros de ADC y puerto en lo que se supone que son según la hoja de datos de acuerdo con lo que quiere hacer
  • Asegúrate de que funcione
  • Luego depura la biblioteca

Probablemente encontrará que la biblioteca es correcta y le falta algo que se hace obvio en ese momento, pero de vez en cuando, hay una biblioteca que está mal o al menos mal escrita / documentada.

    
respondido por el AaronD
0

Todavía no entiendo por qué no funcionó en primer lugar ... Podría haber sido la forma en que lo imprimí. Podría haber sido la biblioteca.

Aunque lo hice configurando los registros manualmente, esto funciona (mejor) para mí.

static unsigned int result = 0;
ANCON0bits.ANSEL4 = 1;      //AN4 to analog channel.
ADCON2 = 0b10111110;        //Select channel
ADCON1 = 0b00110000;
ADCON0 = 0b00010011;        //Start AN4 conversion

while(ADCON0 & 2){}         //ADC busy

result = ADRESH;
result = result<<8;
result = result | ADRESL;
ADCON0 &= 0b11111110;       // Turn converter off
return (result/85);
    
respondido por el Paul

Lea otras preguntas en las etiquetas