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).