No se puede leer el valor correcto de ADC de PCF8591 usando PIC24F

1

He interconectado PCF8591P ADC IC de 8 bits en mi placa de aplicación PIC24F. Mi PIC se ejecuta a 2.8v, lo cual es suficiente para el voltaje de entrada ADC proporcionado en la hoja de datos. He conectado los sensores LM35 y LDR a los pines analógicos 0 y analógicos 1 respectivamente.

El código funciona bien, pero obtengo la salida constante 128 para todos los canales, incluso cuando cambia el nivel de salida del sensor. Por favor, ayúdame para el problema.

#include <stdio.h>
#include "p24FJ128GA202.h"
#include "uart.h"
// calculate baud rate of I2C
#define Fosc      32000000
#define Fcy       (Fosc/2)
#define Fsck      100000
#define I2C_BRG  ((Fcy/2/Fsck)-1)

int main()
{
    unsigned int Adc_pcf=0;
    InitProcessor();
    Delayms();
    while(1)
    {
        Adc_pcf = I2C_read(0x90,0x00);
        Delayms(1000);
        uart1str("ADC0=");
        uart1str(int_char(Adc_pcf));
        uart1str("\r\n");
        Adc_pcf = I2C_read(0x90,0x01);
        Delayms(1000);
        uart1str("ADC1=");
        uart1str(int_char(Adc_pcf));
        uart1str("\r\n");
    }
}

void InitProcessor(void)
{
    // Oscillator    8mhz no pll
    OSCCON = 0x0011;
    CLKDIV = 0x0000; 

    // Configure Digital pins
    ANSA = 0x0003;
    ANSB = 0x0000;

    //  Assign  IO values for Ports
    PORTA = 0x0000;
    TRISA = 0x001B;
    TRISB = 0x468f;                   // 7 as receive and 8 as transmitter
    //PORTB = 0x0000;


    // Interrupt Bits 
    INTCON1 = 0x0000;                                               // Disable  Interrupts
    INTCON2 = 0x0000;

    // Init I2C
    I2C2CONL = 0x8000;
    I2C2CONH = 0x0000;
    I2C2STAT = 0x0000;
    I2C2BRG = I2C_BRG;
    //I2C2BRG = 79;

    Delayms(1000);
    Init_rtc();
}

void Init_rtc()
{
    I2c_Write(0xde, 0x07, 0x10);
    I2c_Write(0xde, 0x06, 0x00);
    Delayms(20);
}



/* Function to Read and return a data through I2C  */
unsigned char I2C_read(unsigned char DeviceAddress,unsigned int Addr)
{   unsigned char db, ReadState=0,I2CFlag;
    ReadState = 0;
    IFS3 &= ~0x0004;                                                        // Master I2C interrupt flag
    I2CFlag = 1;
    I2C2CONL |= 0x0001;         // SEN = 1;
    I2cTimer = 0;
    while(I2CFlag){
        if(I2cTimer > 30){                                              // Exit routine
            I2CFlag = 0;
        }
        //uart1tx('r');
        if(IFS3 & 0x0004)
        {       
            I2cTimer = 0;
            IFS3 &= ~0x0004;
            if(ReadState == 0)
            {
                I2C2TRN = (DeviceAddress & 0xfe);
                if(DeviceAddress == 0x90)
                    ReadState = 1;
            }
            else if(ReadState == 1)
                I2C2TRN = Addr >> 8;
            else if(ReadState == 2)
                I2C2TRN = Addr & 0xff;
            else if(ReadState == 3)I2C2CONL |= 0x0002;  
            else if(ReadState == 4)I2C2TRN = (DeviceAddress | 0x01);
            else if(ReadState == 5){
                I2C2CONL |= 0x0008;                             // RCEN = 1, Enable data receive
                db = I2C2RCV;
            }
            else if(ReadState == 6){
                db = I2C2RCV;                                                       // Read Data
                I2C2CONL |= 0x0020;                                                 // ACKDT = 1, Set Acknowledge bit (No Acknowledge)
                Delayms(5);
                I2C2CONL |= 0x0010;                                                 // ACKEN = 1
            }
            else if(ReadState == 7)I2C2CONL |= 0x04;                                // PEN = 1, Stop enable bit forI2C
            else{ReadState = 100; I2CFlag = 0;}                                     
            ReadState++;
        }
    }
    if(db)
        return db;
    else
        return 0;
}

Pero estoy recibiendo la o / p como:
ADC0 = 128
ADC1 = 128

Configuración de pin de ADC a PIC:
adc0 - sensor de temperatura
adc1 - LDR
adc2 - izquierda
adc3 - izquierda
A0 - suelo
A1 - tierra
A2 - suelo
VSS - tierra y amp; Suelo PIC
SDA - PIC SDA
SCL - PIC SCL
OSC - suelo
EXT - dejado abierto
agnd - suelo
vref - 2.8V
aout - dejado abierto
VDD - Suministro de 2.8V desde la fuente de poder PIC

Actualización:despuésdelasugerenciadeSamGibsonparaelciclodelecturadeadc,heactualizadolafuncióndelectura

unsignedcharpcfwrite(unsignedcharDeviceAddress,unsignedintAddr){unsignedchardb,ReadState=0,I2CFlag;ReadState=0;IFS3&=~0x0004;//MasterI2CinterruptflagI2CFlag=1;I2C2CONL|=0x0001;//SEN=1;I2cTimer=0;while(I2CFlag){if(I2cTimer>30){//ExitroutineI2CFlag=0;Error=25;}if(IFS3&0x0004){I2cTimer=0;IFS3&=~0x0004;if(ReadState==0){I2C2TRN=DeviceAddress;//Deviceaddress}elseif(ReadState==1){I2C2TRN=Addr;//controlbyte}elseif(ReadState==2){I2C2CONL|=0x0002;//PEN=1,RestartforI2C}elseif(ReadState==3){I2C2CONL|=0x0008;//RCEN=1,Enabledatareceivedb=I2C2RCV;//dummyreadwhichwillbelastadcwrittenvalue}elseif(ReadState==4){db=I2C2RCV;Delayms(5);I2C2CONL|=0x0010;//ACKEN=1}elseif(ReadState==5)I2C2CONL|=0x04;//PEN=1,Stopenablebitelse{ReadState=100;I2CFlag=0;uart1str("I2c stopped\r\n");
            }                                       
            ReadState++;
        }
    }
    if(db)
        return db;
    else
        return 0;
}
    
pregunta Pradeep kumark

3 respuestas

3
  

Obtengo la salida constante 128 para todos los canales

Es probable que se deba a la forma en que ha conectado el PCF8591 ADC.

Aunque no ha incluido ese ADC en el esquema, según mi interpretación de sus palabras, el pin EXT no está conectado y el pin OSC está conectado a tierra.

Ese es un mal plan y podría haber dañado el ADC, ya que OSC es un pin de salida, si el oscilador interno intenta ejecutarse. :-( Sin embargo, dejó EXT flotante / desconectado, ¡así que no sabemos si eso se verá como una lógica baja o una lógica alta!

En su lugar, suponiendo que desea utilizar el oscilador interno ADC, deja OSC desconectado y conecta EXT a tierra.

El valor de inicio en la salida del ADC es 128, por lo que hasta que el ADC realmente realice un ciclo de conversión, entonces 128 es el valor que recibirá. Por lo tanto, recibir el valor 128 continuamente le dice que el ADC no está realizando ninguna conversión.

Actualización: Como dijo anteriormente que "el Código funciona bien", confié en que el código fue probado y confirmado como correcto. Sin embargo, después de sus comentarios recientes, he mirado el código y también he encontrado problemas allí, además del problema de hardware que expliqué anteriormente.

No uso el PIC24F, por lo que no puedo verificar si su función I2C_read() es correcta o no, sin embargo, el procedimiento de nivel superior para leer del ADC definitivamente no es correcto. Debería ser similar a la pregunta en tu comentario, donde dijiste:

  

Inicio - > write (0x91) - > write (0x00) - > i2crestart- > i2cread- > i2cread- > i2‌ c_stop

Para leer el valor actual de ADC0:

  • Escriba 0x00 en la dirección I2C 0x90 (este valor, llamado "Byte de control", selecciona ADC0, no hay incremento automático, entrada de un solo extremo; otras opciones se describen en la hoja de datos)
  • Luego lea 2 bytes de la dirección I2C 0x90 (en el bus I2C, este será el byte de dirección 0x91, por supuesto).
  • Ignore el primero de los 2 bytes leídos (que será el valor ADC anterior y será 0x80 después de un encendido). El valor actual de ADC es el 2do de los dos bytes leídos.
respondido por el SamGibson
1

Primero, parece que has mezclado las conexiones a los pines EXT y OSC. Si desea utilizar el oscilador interno, coloque EXT en Vss y deje abierto el OSC.

Consulte la página 10 (8.6) de la hoja de datos de PCF8591. enlace

    
respondido por el Janka
1

Estaba enfrentando el mismo problema y pude solucionarlo simplemente quitando el puente del PCF8591. El puente conectó AIN0 del PCF8591 a Vcc (3.3V) en mi caso.

    
respondido por el Elie

Lea otras preguntas en las etiquetas