SAMC21 Xplain Pro SPI interfacing issue

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Hi,

I'm interfacing SAMC21 Xplain Pro Eval board to 24-bit ADC AD7734EBZ Eval board from Analog Devices.

I'm interfacing AD7734 using SPI, Checked Waveforms from SAMC21 and are according to the timing diagram given in AD7734 datasheet.

But i'm unable to receive data from adc.

Anyone has used AD7734 ? 

Can anyone tell me how to resolve the issue? 

 

Timing Diagram:

 

Code:

char Reset[5] = {0x00,0xFF,0xFF,0xFF,0xFF};

char ModeRegister[2] = {0x38,0x40};

char StatusRegister[1] = {0x44};

char ChlRead[1] = {0x48};

char recval[5];

uint16_t value;

uint8_t value1, value2, value3;

 

int main ( void )

{

    /* Initialize all modules */

    SYS_Initialize ( NULL );

   

    // AD7734 Reset

    SERCOM5_SPI_Initialize();

    delay(3);

    SPI_SS_GPIO_Clear();

    SERCOM5_SPI_Write(&Reset[0], 1);            // 0x00

    SERCOM5_SPI_Write(&Reset[1], 1);            // 0xFF

    SERCOM5_SPI_Write(&Reset[2], 1);            // 0xFF

    SERCOM5_SPI_Write(&Reset[3], 1);            // 0xFF

    SERCOM5_SPI_Write(&Reset[4], 1);            // 0xFF  Reset Sequence

    SPI_SS_GPIO_Set();

    delay(5);

   

    // AD7734 Mode Register

    SPI_SS_GPIO_Clear();

    SERCOM5_SPI_Write(&ModeRegister[0], 1);     // 0x38

    SPI_SS_GPIO_Set();

    delay(5);

    SPI_SS_GPIO_Clear();

    SERCOM5_SPI_Write(&ModeRegister[1], 1);     // 0x40  16-bit Single Channel

    SPI_SS_GPIO_Set();

    delay(5);

   

    while ( true )

    {  

        // AD7734 ADC Status Register

        do

        {

            delay(5);

            SPI_SS_GPIO_Clear();

            SERCOM5_SPI_Write(&StatusRegister[0], 1); // 0x44 Status Register

            SERCOM5_SPI_Read(&value1,1);

            SPI_SS_GPIO_Set();

            delay(3);

            SERCOM3_USART_Write(&value1,1);

            delay(100);

        }while(value1 != 0x00);                 // Waiting for RDYx bit to go Low

       

        // AD7734 Channel 1 Read Register

        SPI_SS_GPIO_Clear();

        SERCOM5_SPI_Write(&ChlRead[0], 1);      // 0x48  Reading Channel 1 Data

        SPI_SS_GPIO_Set();

        delay(5);

        SPI_SS_GPIO_Clear();

        SERCOM5_SPI_Write(0x00, 1);             // 0x00 Data byte 1 to Read

        SERCOM5_SPI_Read(&recval[1],1);

        SPI_SS_GPIO_Set();

        delay(5);

        SPI_SS_GPIO_Clear();

        SERCOM5_SPI_Write(0x00, 1);             // 0x00 Data byte 2 to Read

        SERCOM5_SPI_Read(&recval[2],1);

        SPI_SS_GPIO_Set();

        delay(3);

        value = recval[1];

        value = value << 16;

        value = value | recval[2];

       

        value2 = value >> 8;

        value3 = value & 0x00FF;

        SERCOM3_USART_Write(&value2,1);

        delay(3);

        SERCOM3_USART_Write(&value3,1);

        delay(3);

        

        /* Maintain state machines of all polled MPLAB Harmony modules. */

        SYS_Tasks ( );

    }

 

    /* Execution should not come here during normal operation */

 

    return ( EXIT_FAILURE );

}

 

Thanks & Regards,

Nitish

Attachment(s): 

Last Edited: Tue. Feb 1, 2022 - 05:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try to find some example code, maybe google "AD7734 arduino". I don't know the MPLAB Harmony API but I guess you have problems with reading the status. You should be sending 0x44 (probably ok) but also send a byte (0) to get the status clocked out of the AD7734.
That exact sequence is clearly shown in the datasheet, look for "Figure 16 shows the AD7734 interface read sequence for the ADC status register."
 

On the subject of sending during a read this is wrong:

        SERCOM5_SPI_Write(0x00, 1);             // 0x00 Data byte 1 to Read

Like your other SERCOM5_SPI_Write calls, send from a buffer that contains 0. Here you are actually sending whatever is at address 0. Normally, with SPI, it does not matter what you send when you actually want to read but this is bad practice (and would get you a fault with another CPU). 

 

Also, this
 

    SERCOM5_SPI_Write(&Reset[0], 1);            // 0x00
    SERCOM5_SPI_Write(&Reset[1], 1);            // 0xFF
    SERCOM5_SPI_Write(&Reset[2], 1);            // 0xFF
    SERCOM5_SPI_Write(&Reset[3], 1);            // 0xFF
    SERCOM5_SPI_Write(&Reset[4], 1);            // 0xFF  Reset Sequence

I guess can be:
 

    SERCOM5_SPI_Write(Reset, 5);

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found this 
https://github.com/ucd-squidlab/...
 

uint8_t AD7734::GetADCStatus() {
    uint8_t data_array;
    data_array = READ | ADDR_ADCSTATUS;
    SPI.transfer(_cs, data_array);
    return SPI.transfer(_cs, 0);
}

It's clear you need two transfers to get the status.
BTW, about the status, "When a conversion is complete, the corresponding channel data register is updated and the corresponding RDY bit is set to 1.", so you should not be
 

 // Waiting for RDYx bit to go Low

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, 

I've tried to read ADC status but i'm getting 0x00, I've made changes as you said.

PF Code snippet.

 

char DummyByte[] = {0x00};
char Reset[5] = {0x00,0xFF,0xFF,0xFF,0xFF};
char RevisionRegister[1] = {0x42};
char ChlSetup[2] = {0x28,0x09};
char ModeRegister[2] = {0x38,0x24};
char ChlRead[1] = {0x48};
char Ch1StatusRegister[1] = {0x60};
char StatusRegister[1] = {0x44};
char ConversionTimeRegister[2] = {0x30, 0x91};
char recval[5];
uint8_t value, value1;

 

int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    SERCOM5_SPI_Initialize();
    SERCOM3_USART_Initialize();

    SS_Clear();
    SERCOM5_SPI_Write(&Reset, 5);
    SS_Set();
    delay(3);
    do
    {
        SS_Clear();
        SERCOM5_SPI_Write(&RevisionRegister, 1);
        SS_Set();
        delay(3);
        SS_Clear();
        SERCOM5_SPI_Read(&value, 1);
        SS_Set();
        value = (value & 0x0F);
        SERCOM3_USART_Write(&value, 1);
        delay(3);
    }while((value & 0x0F) != 0x02);   
    
    SS_Clear();
    SERCOM5_SPI_Write(&ChlSetup[0], 1);     // 0x28 Setup Register Channel-1
    SS_Set();
    delay(3);  
    SS_Clear();
    SERCOM5_SPI_Write(&ChlSetup[1], 1);     // 0x09 Enable=1 & RNG0=1 #00001001
    SS_Set();
    delay(3); 
    
    SS_Clear();
    SERCOM5_SPI_Write(&ModeRegister[0], 1);     // 0x38 Mode Register channel-1
    SS_Set();
    delay(3);
    SS_Clear();
    SERCOM5_SPI_Write(&ModeRegister[1], 1);     // 0x24 16-bit Continuous Conversion Mode
    SS_Set();
    delay(3);
    
    while ( true )
    {
        SS_Clear();
        SERCOM5_SPI_Write(&ChlRead, 1); // 0x48 Channel Read Register
        SS_Set();
        delay(3);
        
        do
        {
            SS_Clear();
            SERCOM5_SPI_Write(&StatusRegister, 1); // 0x44 ADC Status Register
            SS_Set();
            delay(3);
            SS_Clear();
            SERCOM5_SPI_Write(&DummyByte, 1); // 0x00 DummyByte to read data
            SERCOM5_SPI_Read(&value1,1);
            SS_Set();
            delay(3);
            value1 = value1 & 0x0F;
        }while(value1 != 0x01);

        SERCOM3_USART_Write(&value1,1);
        SERCOM3_USART_Write("Data:",5);
        
        SS_Clear();
        SERCOM5_SPI_Write(&DummyByte, 1); // 0x00 Dummy Byte to Read Data
        SERCOM5_SPI_Read(&recval[0],1);
        SS_Set();
        SS_Clear();
        SERCOM5_SPI_Write(&DummyByte, 1); // 0x00 Dummy Byte to Read Data
        SERCOM5_SPI_Read(&recval[1],1);
        SS_Set();
        delay(3);
        SERCOM3_USART_Write(&recval,2);
        delay(3);
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}
 

Thanks & Regards,

Nitish

Last Edited: Mon. Dec 20, 2021 - 08:40 AM