AD7787 not working

Hi people!

I just bought an ad7787 and I cant get it running.I have read the code you attached but Im having some troubles understanding it, probably because my knowledge about C is not that good. Anyway, I have connected the device to a atmega1281 that I have used a lot, by the SPI. I can see in my oscilloscope that when I send my commands to comm register the sclk and cs lines are correct but the data is not.

Then I try to read the data register but the value I get is 0x80 no matter what value is on the AIN2.

I attached my scheme and my code.

Cheers,

Dan.

/*

* Prueba del ADC con el mote

* Created: 30/07/2012 10:05:44

* Author: Daniel

*/

#include <avr/io.h>

#include <avr/interrupt.h>

#include <avr/power.h>

#include <util/delay.h>

#define F_CPU 4000000UL //4 MHz

#include <avr/sfr_defs.h>

//Variables globales

unsigned char data=0x3D,aux2,aux4;

int adc=0x00;

//Mis funciones

void SPI_MasterInit(void);

void _delay_ms (double __ms);

writetoreg(unsigned char data);

int readfromreg();

int main(void)

{

//Configurar puertos e inicializar

             SPI_MasterInit();

             sei();

            

       while(1)

    {

             data=0x3D; //continuous mode - ain2(single ended)

             writetoreg(data); //write to comm register

             adc = readfromreg();//read data

             }

}

void SPI_MasterInit(void)

{

/* Set MOSI,SS and SCK output, all others input */

DDRB = (1<<DDB1)|(1<<DDB2)|(1<<DDB0)|(1<<DDB4)|(1<<DDB5);

PORTB = (1<<PB0)|(1<<PB4)|(1<<PB2);//fsync disp1

/* Enable SPI, Master, set clock rate fck/16 , MSB first*/

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(0<<DORD)|(1<<CPOL)|(0<<CPHA);

}

writetoreg(unsigned char data)

{

       PORTB = (0<<PB0)|(1<<PB4)|(1<<PB5);//cs low

             // Start transmission

             SPDR = data;

             // Wait for transmission complete

             while(!(SPSR & (1<<SPIF)));

             aux2 = SPSR;

       PORTB = (1<<PB0)|(1<<PB4)|(1<<PB5);// cs high

}

int readfromreg()

{

       PORTB = (0<<PB0)|(1<<PB4)|(1<<PB5);//cs low

       // Start transmission

       while(!(SPSR & (1<<SPIF)));

       adc = SPSR;

       PORTB = (1<<PB0)|(1<<PB4)|(1<<PB5);// cs high

       return adc;

}     

  • 0
    •  Analog Employees 
    on Sep 7, 2012 6:21 PM over 8 years ago

    Hello DanTech,

    I'd like you to run some routines to properly check the part.

     

    1.       I scanned your code and found that you are doing a continuous read (from writing 0x3D in the Comms Register) of the Data Register which is fine. I suggest you disable continuous read mode while debugging your software. Continuous reads can only be used when continuously reading the data register i.e. the serial interface is dedicated to reading the data register when CREAD equals 1.

    2.       The first command in your initialization routine should be a reset. This can be done by writing 32 consecutive 1s to the part. This ensures that all registers are at their default values.

     

    3.       Try to change the output data rate and check if the DRDY changes also. You can do this by altering the FS2-FS0 bits in the Filter Register. Check Table 12 on Page 13 of the datasheet for setting the update rates. The default setting is at 16.6Hz (FS2-FS0=100).

     

    4.       Next step is to check read and write routines. Writing to one of the on-chip registers and try to read back the values that is written. Please pay attention to the R/W value in the comms register  upon reading or writing to a specified register. A 0 in this bit is intended for a write while a 1 is needed for a read in the next operation.

     

    5.       If everything works well in 1-3, you can now try to read back the conversions. It is recommended that DIN and SCLK are idled high when not used. 

     

    I have one concern about the way you do the continuous read. The communications register does not have to be written to for data reads when CRAD is set to 1. The contents of the data register are placed on the DOUT pin automatically when the SCLK pulses are applied.

                    while(1)

                     {

                    data=0x3D; //continuous mode - ain2(single ended)

                    writetoreg (data); //write to comm register

                    adc = readfromreg ();//read data

                  }

                    

     

    You have to tell the comms register only once that you are doing a continuous read. When DRDY goes low, then apply the 24 SCLK pulses and the data is placed on the DOUT line automatically. CS may need to be tied low so that you can identify when new conversions are available.

     

    Regards,

    Mary.

  • Hi again,

    I have made some changes on my code according to your notes. I have added a reset routine(image attached) and I've been trying to read the status register just to try reading register from the device. But I get stucked. I am not able to read any register or set any of them as I want.

    Im trying to recreate the figure 14 in the datasheet,keeping CS line low for both writing and readind, but the DOUT line is low during this situation(image 2 attached).

    And my new code is the following:

    /*

    * ADC.c

      * Created: 05/09/2012 17:03:49

    * Author: Daniel

    */

    #include <avr/io.h>

    #include <avr/interrupt.h>

    #include <avr/power.h>

    #include <util/delay.h>

    #define F_CPU 4000000UL //4 MHz

    #include <avr/sfr_defs.h>

    //Variables globales

    unsigned char data=0x01,data1=0x3D,aux2,adc1,adc2,adc3,todouno=0xFF;

    //Mis funciones

    void SPI_MasterInit(void);

    void writetoreg(unsigned char);

    unsigned char readdata(unsigned char data);

    void resetADC(unsigned char cDataH);

    void _delay_ms (double __ms);

    unsigned char readfromreg(unsigned char data8);

    int main(void)

    {

            //Configurar puertos e inicializar

                 SPI_MasterInit();

                 sei();

                 resetADC(todouno); // 32 cycles,with '1' for reset

           // writetoreg(0x3D); //continuos mode

                 PORTB = (0<<PB0)|(1<<PB4)|(1<<PB5);//fsync low

                 writetoreg(0b00101000); //get to see status register

                 adc1=readfromreg(todouno); //read status register

                 PORTB = (1<<PB0)|(1<<PB4)|(1<<PB5);// cs high

           while(1)

    {       

                 //

                  //read 24 bits data

                 PORTB = (0<<PB0)|(1<<PB4)|(1<<PB5);//cs low

                 adc1=readdata(0x00);

                 adc2=readdata(0x00);

                 adc3=readdata(0x00);

                 PORTB = (1<<PB0)|(1<<PB4)|(1<<PB5);//cs high//

           }

    }

    void SPI_MasterInit(void)

    {

           /* Set MOSI,SS and SCK output, all others input */

           DDRB = (1<<DDB1)|(1<<DDB2)|(1<<DDB0)|(1<<DDB4)|(1<<DDB5);

           PORTB = (1<<PB0)|(1<<PB4)|(1<<PB2);//fsync disp1

          

           /* Enable SPI, Master, set clock rate fck/16 , MSB first*/

           SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(0<<DORD)|(1<<CPOL)|(0<<CPHA);

    void writetoreg(unsigned char cDataH)

    {

                  // Start transmission

                 SPDR = cDataH;

                 // Wait for transmission complete

                 while(!(SPSR & (1<<SPIF)));

                 aux2 = SPSR;

          

    }

    unsigned char readdata(unsigned char data)

    {

           //PORTB = (0<<PB0)|(1<<PB4)|(1<<PB5);//cs low

           unsigned char adc;

           SPDR = data;

           adc = SPSR;

           // Start transmission

           while(!(SPSR & (1<<SPIF)));

           adc = SPSR;

           //PORTB = (1<<PB0)|(1<<PB4)|(1<<PB5);// cs high

           return adc;

    }

    void resetADC(unsigned char cDataH)

    {

           PORTB = (0<<PB0)|(1<<PB4)|(1<<PB5);//fsync low

          

           // Start transmission

           SPDR = cDataH;

           // Wait for transmission complete

           while(!(SPSR & (1<<SPIF)));

           aux2 = SPSR;

          

           // Start 2 transmission

           SPDR = cDataH;

           // Wait for transmission complete

           while(!(SPSR & (1<<SPIF)));

           aux2 = SPSR;

          

           // Start 3 transmission

           SPDR = cDataH;

           // Wait for transmission complete

           while(!(SPSR & (1<<SPIF)));

           aux2= SPSR;

          

           // Start 4 transmission

           SPDR = cDataH;

           // Wait for transmission complete

           while(!(SPSR & (1<<SPIF)));

           aux2 = SPSR;

          

           PORTB = (1<<PB0)|(1<<PB4)|(1<<PB5);// fsync high

          

    }

    unsigned char readfromreg(unsigned char data8)

    {

           //PORTB = (0<<PB0)|(1<<PB4)|(1<<PB5);//cs low

           unsigned char adc8;

           SPDR = data8;

           adc8 = SPSR;

           // Start transmission

           while(!(SPSR & (1<<SPIF)));

           adc8 = SPSR;

           //PORTB = (1<<PB0)|(1<<PB4)|(1<<PB5);// cs high

           return adc8;

    }

    Many thanks.

    Regards, Dan.

  • 0
    •  Analog Employees 
    on Sep 12, 2012 5:38 AM over 8 years ago

    Hi, Dan.

    You need to allow 500 us before accessing registers after a reset . In your code, you should do the following:

    • Apply reset (write 32 1s)
    • Wait 500 us
    • Read status register (write 0x04 to the ADC and then apply 8 SCLK pulses so that the status register contents are placed on the DOUT line).

    After a reset, the ADC is in continuous mode. So with CS low, you should see DOUT/RDY pulsing at 16.6 Hz. I'd like you to check this after the reset and then try to read the status register.

    Take note that the DRDY pin must be monitored when reading conversions but when reading and writing to other registers (mode, filter, etc), you do not need to monitor the DRDY pin.

    Regards,

    Jgealon

  • Hi again,

    I have checked everything you guys have told me.I apply the reset cycles, I wait and then write 0x04 to the comm register and read(by applying 8 sclk pulses), but the DOUT line is not giving anything to me.

    I have also checked the DOUT line after a reset, pulling down the cs line, and there is nothing either.

    Right now, I can see what I send is going through the line but when I need to see the response I just can see the cs line and the clock working, the dout line is 0V.

    Regards,

    Dani

  • 0
    •  Analog Employees 
    on Sep 14, 2012 1:36 PM over 8 years ago

    Hello Dani,

    after performing a reset, the output data rate is set to 16.6Hz. So, with CS tied low, you should see DRDY pulsing every 60 ms - DRDY will remain low and pulse high every 60 ms. If this is not happening, can you try another AD7787 device in case the current part is damaged.

    You idle DIN and SCLK high when they are not being used which is good.

    Can you also check your supply voltages to ensure that they are stable. What is connected to the analog inputs? What is the reference voltage?

    Regards,

    Mary.