This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1298: Issues communicating with the device via SPI

Part Number: ADS1298
Other Parts Discussed in Thread: TMS320F28377S,

Hello,

I am attempting to establish contact with the ADS1298 using a TMS320F28377S. I am using a SYSCLK of 200MHz and a SPI baud rate of 200kbps.

I was able to establish communication once by checking ID

However, I am now getting a very different result.

I am uncertain as to why it no longer works.

This is my POWER UP SEQUENCE

GPIO_setDirectionMode(ADC_CLKSEL, GPIO_DIR_MODE_OUT);
 GPIO_setDirectionMode(ADC_RESET, GPIO_DIR_MODE_OUT);
 GPIO_setDirectionMode(ADC_PDWN, GPIO_DIR_MODE_OUT);
 GPIO_setDirectionMode(ADC_DRDY, GPIO_DIR_MODE_IN);
 GPIO_setDirectionMode(ADC_START, GPIO_DIR_MODE_OUT);
 GPIO_setPinConfig(GPIO_87_GPIO87);
 GPIO_setPinConfig(GPIO_69_GPIO69);
 GPIO_setPinConfig(GPIO_66_GPIO66);
 GPIO_setPinConfig(GPIO_86_GPIO86);
 GPIO_setPinConfig(GPIO_65_GPIO65);

 GPIO_writePin(ADC_START,0);
 GPIO_writePin(ADC_PDWN,0);
 GPIO_writePin(ADC_RESET,0);
 Delay_ms(140);

 GPIO_writePin(ADC_CLKSEL,1);
 Delay_us(10);
 GPIO_writePin(ADC_PDWN,1);
 GPIO_writePin(ADC_RESET,1);
 Delay_ms(140);
 GPIO_writePin(ADC_RESET,0);
 Delay_us(10);
 GPIO_writePin(ADC_RESET,1);
 // SENDSDATAC COMMAND

Here is my code for FIgures seen above

    while(1){
 GPIO_writePin(61, 1);
 Delay_ms(10);
 GPIO_writePin(61, 0);
    Delay_us(100);
    SPI_writeDataNonBlocking(SPIA_BASE, ((SDATAC)<<8));
    uint16_t dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
    Delay_us(5);
    SPI_writeDataNonBlocking(SPIA_BASE, ((0x20)<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 Delay_us(5);
 SPI_writeDataNonBlocking(SPIA_BASE, ((0x00)<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 Delay_us(5);
 SPI_writeDataNonBlocking(SPIA_BASE, ((0x00)<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 Delay_us(100);
    };

*******************************************************************************

I can provide a copy of the circuit diagram if necessary. Please let me know if you have any suggestions. My current goal is to establish contact with the ADC by checking the ID so that I may program the ADC as desired.

*******************************************************************************

A copy of my entire code Is provided below

//********************************************
// Included Files
//********************************************
#include "driverlib.h"
#include "device.h"

//********************************************
// Defines
//********************************************
// uC pins to ADC pins
#define ADC_CLKSEL 87
#define ADC_RESET 69
#define ADC_PDWN 66
#define ADC_DRDY 86
#define ADC_START 65
// ADC Register Addresses
#define ID   0x00
#define CONFIG1  0X01
#define CONFIG2  0X02
#define CONFIG3  0X03
#define LOFF  0X04
#define CH1SET  0X05
#define CH2SET  0X06
#define CH3SET  0X07
#define CH4SET  0X08
#define CH5SET  0X09
#define CH6SET  0X0A
#define CH7SET  0X0B
#define CH8SET  0X0C
#define RLDSENSP 0X0D
#define RLDSENSN 0X0E
#define LOFFSENSP 0X0F
#define LOFFSENSN 0X10
#define LOFFFLIP 0X11
#define LOFFSTATP 0X12
#define LOFFSTATN 0X13
#define GPIO  0X14
#define PACE  0X15
#define RESP  0X16
#define CONFIG4  0X17
#define WCT1  0X18
#define WCT2  0X19
//ADC SPI Commands
#define WAKEUP  0x02
#define STANDBY  0x04
#define RESET  0x06
#define START  0x08
#define STOP  0x0A
#define RDATAC  0x10
#define SDATAC  0x11
#define RDATA  0x12
//General uC stats
#define CPU_clock 100000000
#define PER_clock  25000000

//********************************************
// Variables
//********************************************
uint16_t ADC_INIT_ADDR[] = {CONFIG3, CONFIG1, CONFIG2, LOFF, CH1SET, CH2SET, CH3SET, CH4SET, CH5SET, CH6SET, CH7SET, CH8SET,
       RLDSENSP, RLDSENSN, LOFFSENSP, LOFFSENSN, LOFFFLIP, PACE, RESP, CONFIG4};
uint16_t ADC_INIT_DATA[] = {0xCC, 0xC6, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
       0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00};
uint16_t ADC_ID[] = {0x11, 0x20, 0x00, 0x00};

//********************************************
// Function Prototypes
//********************************************
void SPI_INIT(void);
void SPI_TX_STRING();
uint16_t SPI_RX_STRING();
void SPI_TX_BYTE();
uint16_t SPI_RX_BYTE();
void SPI_TX_CMD();
void ADC_POWER_INIT();
void Delay_us();
void Delay_ms();

//********************************************
// Main
//********************************************
void main(void)
{
 // Initialize device clock and peripherals
    Device_init();
     /* Modify the system Clock
      *  Device.h -> DEVICE_SETCLOCK_CFG
      *   SYSCTL_IMULT(40)
      *   SYSCTL_FMULT_0
      *   SYSCTL_SYSDIV(4)
      *    -> 100 MHz
      *  Device.c -> line 88
      *   SYSCTL_LSPCLK_PRESCALE_4
      *    -> 25 MHz
      */
    // Disable pin locks and enable internal pullups.
    Device_initGPIO();
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    Interrupt_initModule();
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    Interrupt_initVectorTable();
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    EINT;
    ERTM;

    // Set up SPI, manual control over /CS-pin61
    SPI_INIT();

    // Begin Power up routine for ADC, requires manual control over /CS-pin61
    ADC_POWER_INIT();

//    SPI_TX_CMD(SDATAC);
//    SPI_TX_STRING(ADC_INIT_ADDR, ADC_INIT_DATA, sizeof(ADC_INIT_ADDR));
//    SPI_TX_CMD(RDATAC);
//    SPI_TX_CMD(START);

    uint16_t DOUT;
    while(1){
 GPIO_writePin(61, 1);
 Delay_ms(10);
 GPIO_writePin(61, 0);
    Delay_us(100);
    SPI_writeDataNonBlocking(SPIA_BASE, ((SDATAC)<<8));
    uint16_t dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
    Delay_us(5);
    SPI_writeDataNonBlocking(SPIA_BASE, ((0x20)<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 Delay_us(5);
 SPI_writeDataNonBlocking(SPIA_BASE, ((0x00)<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 Delay_us(5);
 SPI_writeDataNonBlocking(SPIA_BASE, ((0x00)<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 Delay_us(100);
    };
//    while(1)
//    {
//     SPI_TX_CMD(SDATAC);
//     Delay_us(10);
//     SPI_RX_BYTE(0);
//     Delay_us(10);
////  SPI_TX_BYTE(ADC_INIT_ADDR[0], ADC_INIT_DATA[0]);
////  SPI_RX_BYTE(ADC_INIT_ADDR[0]);
////  SPI_TX_CMD(RDATAC);
////  SPI_TX_CMD(START);
//    }

 if(GPIO_readPin(47)==0)
 {
  GPIO_writePin(61,1);
 }
    while(1);
}

//********************************************
// Function Declarations
//********************************************

//
// Function to configure SPI A in FIFO mode.
//
void SPI_INIT()
{
    //
    // Must put SPI into reset before configuring it
    //
    SPI_disableModule(SPIA_BASE);

    //GPIO MUX configuration
 GPIO_setDirectionMode(58, GPIO_DIR_MODE_OUT);   // SPI-A-SIMO (pin58) set as output
 GPIO_setDirectionMode(59, GPIO_DIR_MODE_IN); // SPI-A-SOMI (pin59) set as output
 GPIO_setDirectionMode(61, GPIO_DIR_MODE_OUT);   // SPI-A-CS (pin61) set as output
 GPIO_setDirectionMode(60, GPIO_DIR_MODE_OUT);   // SPI-A-CLK (pin60) set as output
 GPIO_setPinConfig(GPIO_58_SPISIMOA);            // PIN58 mux config set as SPI-A-SIMO
 GPIO_setPinConfig(GPIO_59_SPISOMIA);   // PIN59 mux config set as SPI-A-SOMI
 GPIO_setPinConfig(GPIO_61_GPIO61);              // PIN61 mux config set as SPI-A-CS
 GPIO_setPinConfig(GPIO_60_SPICLKA);             // PIN60 mux config set as SPI-A-CLK

    //
    // SPI configuration. Use a 1MHz SPICLK and 16-bit word size.
    //
    SPI_setConfig(SPIA_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL1PHA0,
                  SPI_MODE_MASTER, 200000, 8);
    SPI_enableLoopback(SPIA_BASE);
    SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_STOP_AFTER_TRANSMIT);

    //
    // Configuration complete. Enable the module.
    //
    SPI_enableModule(SPIA_BASE);
    GPIO_writePin(61, 1);
    Delay_ms(10);
    GPIO_writePin(61, 0);
}

void SPI_TX_STRING(uint16_t *addr, uint16_t *data,uint16_t size)
{
 int i = 0;
 for(i=0;i<size;i++)
 {
  SPI_TX_BYTE(addr[i], data[i]);
 }
}

uint16_t SPI_RX_STRING(uint16_t *addr, uint16_t size)
{
 int i = 0;
 for(i=0;i<size;i++)
 {
  SPI_RX_BYTE(addr[i]);
 }
}

void SPI_TX_BYTE(uint16_t addr, uint16_t BYTE)
{
 GPIO_writePin(61, 0);
 Delay_us(1);
 SPI_writeDataNonBlocking(SPIA_BASE, ((0x40 | addr)<<8));
 uint16_t dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 SPI_writeDataNonBlocking(SPIA_BASE, (0x00<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 SPI_writeDataNonBlocking(SPIA_BASE, (BYTE<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 Delay_us(1);
 GPIO_writePin(61, 1);
}

uint16_t SPI_RX_BYTE(uint16_t addr)
{
 GPIO_writePin(61, 0);
 Delay_us(1);
 SPI_writeDataNonBlocking(SPIA_BASE, ((0x20 | addr)<<8));
 uint16_t dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 SPI_writeDataNonBlocking(SPIA_BASE, (0x00<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 SPI_writeDataNonBlocking(SPIA_BASE, (0x00<<8));
 dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 Delay_us(1);
 GPIO_writePin(61, 1);
}

void SPI_TX_CMD(uint16_t CMD)
{
 GPIO_writePin(61, 0);
 Delay_us(1);
 SPI_writeDataNonBlocking(SPIA_BASE, (CMD<<8));
 uint16_t dummy = SPI_readDataBlockingNonFIFO(SPIA_BASE);
 Delay_us(1);
 GPIO_writePin(61, 1);
}

void ADC_POWER_INIT()
{
 GPIO_setDirectionMode(ADC_CLKSEL, GPIO_DIR_MODE_OUT);
 GPIO_setDirectionMode(ADC_RESET, GPIO_DIR_MODE_OUT);
 GPIO_setDirectionMode(ADC_PDWN, GPIO_DIR_MODE_OUT);
 GPIO_setDirectionMode(ADC_DRDY, GPIO_DIR_MODE_IN);
 GPIO_setDirectionMode(ADC_START, GPIO_DIR_MODE_OUT);
 GPIO_setPinConfig(GPIO_87_GPIO87);
 GPIO_setPinConfig(GPIO_69_GPIO69);
 GPIO_setPinConfig(GPIO_66_GPIO66);
 GPIO_setPinConfig(GPIO_86_GPIO86);
 GPIO_setPinConfig(GPIO_65_GPIO65);

 GPIO_writePin(ADC_START,0);
 GPIO_writePin(ADC_PDWN,0);
 GPIO_writePin(ADC_RESET,0);
 Delay_ms(140);

 GPIO_writePin(ADC_CLKSEL,1);
 Delay_us(10);
 GPIO_writePin(ADC_PDWN,1);
 GPIO_writePin(ADC_RESET,1);
 Delay_ms(140);
 GPIO_writePin(ADC_RESET,0);
 Delay_us(10);
 GPIO_writePin(ADC_RESET,1);
 // SENDSDATAC COMMAND
}

void Delay_us(uint16_t Delay)
{
 volatile uint32_t ticks;
 volatile uint32_t Dur = CPU_clock/1000000*Delay;
 for(ticks=0;ticks<=Dur;ticks++);
}

void Delay_ms(uint16_t Delay)
{
 volatile uint32_t ticks;
 volatile uint32_t Dur = CPU_clock/1000*Delay;
 for(ticks=0;ticks<=Dur;ticks++);
}

  • Here is an Altium Schematic of my current circuit

    Hopefully this helps in the debugging process.

    Note DAD CH refers to the Diligent Analog Discovery Board which I am using as an LSA.

    Note: I do not currently have a schematic file for the TMS320F28377, so uC Pin refers to pin numbers of that microcontroller.

  • Hello Seth,

    Thanks for your post.

    Are you using the correct SPI Mode? The ADS1298 uses SPI Mode 1, which means CPOL = 0 and CPHA = 1. In your logic analyzer captures, SCLK appears to idle high and lead with the falling edge. We want SCLK to idle low. The rising edge is then used to shift the data and the falling edge follows to latch the data. Please give this a try and let me know if that resolves your issue.

    https://www.totalphase.com/support/article_attachments/200063856/spi-modes.png

    Best Regards,

  • Hello,

    I apologize for taking so long to respond to this. I had to shift my focus to other aspects of this project to meet my deadlines.
    I have implemented the change recommended above and it has not fixed my error. Actually, it caused the system to stop working entirely. This remained true with/without my current fix.

    Regards,
    Seth
  • Hello,

    I finally found a solution. Basically I just needed to make the falling edge of the clock occur in the middle of the data bit.

    Basically the capacitive component of the oscilloscope impedance was causing the falling edge to be delayed such that the ADC could register the data. I confirmed this by adding a capacitor between SCLK and ground. Then finally I made this simple falling edge modification in the SPI control registers.