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.

CCS/ADC124S101: ADC124S101 Multi Channel Reading

Part Number: ADC124S101
Other Parts Discussed in Thread: CC3220SF,

Tool/software: Code Composer Studio

Hi,

I develop code at CCS (TI-RTOS) for CC3220SF IC. I tried to read all channels (1-4) after I activaded (Power Up) ADC124S101 with CS* Falling Edge but I couldn't read multi channel. On the other hand after I read Channel-1, I deactivate ADC124S101 with Rising Edge of CS*. At next step I activate (Power Up) ADC124S101 with CS* Falling Edge and Thus I can read Channel-2. And after deactived and activated ADC124S101 chip again I can read Channel-3 and Channel-4. So, to read Multi-Channel, should we deactivate and activate the ADC124S101 chip again and again ?

Also, When I activaded chip again, at first time I read last Channel voltage because of the Track and Hold issue. For examle, I read Channel-1, Channel-2, Channel-3, Channel-4 respectively and when I tried to read Channel-2 I get Channel-1 values. Bacause of this issue I read channel values 2 times and I use second measeurement value. My code I developed with this way is at attachment. You can check it.So, to solve this issue what is your suggestion? Before measurement can I discharge capacitor controlling SW1 or SW2?

Also it is a section from Datasheet of ADC124S101 (Page 17). And can you explain bold sentences more clear giving examples? Also this section is related with my first question top.

During the first 3 cycles of SCLK, the ADC is in the track mode, acquiring the input voltage. For the next 13SCLK cycles the conversion is accomplished and the data is clocked out, MSB first, starting on the 5th clock. If there is more than one conversion in a frame, the ADC will re-enter the track mode on the falling edge of SCLKafter the N*16th rising edge of SCLK, and re-enter the hold/convert mode on the N*16+4th falling edge of SCLK,where "N" is an integer.

Thanks for your support.

spimaster.c
/*
 * Copyright (c) 2018-2019, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  ======== spimaster.c ========
 */
#include <stddef.h>
#include <stdint.h>
#include <string.h>

/* POSIX Header files */
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SPI.h>
#include <ti/display/Display.h>

/* Example/Board Header files */
#include "Board.h"

#define THREADSTACKSIZE (1024)

#define SPI_MSG_LENGTH  (1)
uint16_t MASTER_MSG[4]= {0x0000,0x0800,0x1000,0x1800};

#define MAX_LOOP        (10)

SPI_Handle      masterSpi;
SPI_Params      spiParams;
SPI_Transaction transaction;
bool            transferOK;
int32_t         status;
uint16_t        RX_Buffer_1,RX_Buffer_2,RX_Buffer_3,RX_Buffer_4,i,j;

static Display_Handle display;

uint16_t masterRxBuffer[1];
uint16_t masterTxBuffer[1];

/* Semaphore to block master until slave is ready for transfer */
sem_t masterSem;

void read_adc_channels();

/*
 *  ======== slaveReadyFxn ========
 *  Callback function for the GPIO interrupt on Board_SPI_SLAVE_READY.
 */
//void slaveReadyFxn(uint_least8_t index)
//{
//    sem_post(&masterSem);
//}

/*
 *  ======== masterThread ========
 *  Master SPI sends a message to slave while simultaneously receiving a
 *  message from the slave.
 */
void *masterThread(void *arg0)
{
    /*
     * Board_SPI_MASTER_READY & Board_SPI_SLAVE_READY are GPIO pins connected
     * between the master & slave.  These pins are used to synchronize
     * the master & slave applications via a small 'handshake'.  The pins
     * are later used to synchronize transfers & ensure the master will not
     * start a transfer until the slave is ready.  These pins behave
     * differently between spimaster & spislave examples:
     *
     * spimaster example:
     *     * Board_SPI_MASTER_READY is configured as an output pin.  During the
     *       'handshake' this pin is changed from low to high output.  This
     *       notifies the slave the master is ready to run the application.
     *       Afterwards, the pin is used by the master to notify the slave it
     *       has opened Board_SPI_MASTER.  When Board_SPI_MASTER is opened, this
     *       pin will be pulled low.
     *
     *     * Board_SPI_SLAVE_READY is configured as an input pin. During the
     *       'handshake' this pin is read & a high value will indicate the slave
     *       ready to run the application.  Afterwards, a falling edge interrupt
     *       will be configured on this pin.  When the slave is ready to perform
     *       a transfer, it will pull this pin low.
     *
     * Below we set Board_SPI_MASTER_READY & Board_SPI_SLAVE_READY initial
     * conditions for the 'handshake'.
     */
//    GPIO_setConfig(Board_SPI_MASTER_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
//    GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_INPUT);

    /*
     * Handshake - Set Board_SPI_MASTER_READY high to indicate master is ready
     * to run.  Wait Board_SPI_SLAVE_READY to be high.
     */
    //GPIO_write(Board_SPI_MASTER_READY, 1);
    //while (GPIO_read(Board_SPI_SLAVE_READY) == 0) {}

    /* Handshake complete; now configure interrupt on Board_SPI_SLAVE_READY */
//    GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
//    GPIO_setCallback(Board_SPI_SLAVE_READY, slaveReadyFxn);
//    GPIO_enableInt(Board_SPI_SLAVE_READY);

    /*
     * Create synchronization semaphore; the master will wait on this semaphore
     * until the slave is ready.
     */
//    status = sem_init(&masterSem, 0, 0);
//    if (status != 0) {
//        Display_printf(display, 0, 0, "Error creating masterSem\n");
//
//        while(1);
//    }

    /* Open SPI as master (default) */
    SPI_Params_init(&spiParams);
    spiParams.frameFormat = SPI_POL0_PHA0;
    spiParams.dataSize = 16;
    spiParams.bitRate = 100000;
    //masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
    Display_printf(display, 0, 0, "Master SPI initialized\n");

    /*
     * Master has opened Board_SPI_MASTER; set Board_SPI_MASTER_READY high to
     * inform the slave.
     */
    //GPIO_write(Board_SPI_MASTER_READY, 0);

    while(1){
        read_adc_channels();
        usleep(500000);
    }

    /* Example complete - set pins to a known state */
    //GPIO_disableInt(Board_SPI_SLAVE_READY);
    //GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
    //GPIO_write(Board_SPI_MASTER_READY, 0);
}

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    pthread_t           thread0;
    pthread_attr_t      attrs;
    struct sched_param  priParam;
    int                 retc;
    int                 detachState;

    /* Call driver init functions. */
    Display_init();
    GPIO_init();
    SPI_init();

    /* Configure the LED pins */
    GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

    /* Open the display for output */
    display = Display_open(Display_Type_UART, NULL);
    if (display == NULL) {
        /* Failed to open display driver */
        while (1);
    }

    /* Turn on user LED */
    GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);

    Display_printf(display, 0, 0, "Starting the SPI master example");
    Display_printf(display, 0, 0, "This example requires external wires to be "
        "connected to the header pins. Please see the Board.html for details.\n");

    /* Create application threads */
    pthread_attr_init(&attrs);

    detachState = PTHREAD_CREATE_DETACHED;
    /* Set priority and stack size attributes */
    retc = pthread_attr_setdetachstate(&attrs, detachState);
    if (retc != 0) {
        /* pthread_attr_setdetachstate() failed */
        while (1);
    }

    retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
    if (retc != 0) {
        /* pthread_attr_setstacksize() failed */
        while (1);
    }

    /* Create master thread */
    priParam.sched_priority = 1;
    pthread_attr_setschedparam(&attrs, &priParam);

    retc = pthread_create(&thread0, &attrs, masterThread, NULL);
    if (retc != 0) {
        /* pthread_create() failed */
        while (1);
    }

    return (NULL);
}

void read_adc_channels()
{
    for (i = 0; i < 2; i++) {
        masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
        /* Copy message to transmit buffer */
        masterTxBuffer[0] = MASTER_MSG[0];
        transaction.count = 1;
        transaction.txBuf = (void *) masterTxBuffer;
        transaction.rxBuf = (void *) masterRxBuffer;

        GPIO_toggle(Board_GPIO_LED1);

        /* Perform SPI transfer */
        transferOK = SPI_transfer(masterSpi, &transaction);
        if (transferOK) {
            RX_Buffer_1 = masterRxBuffer[0] & 0x0FFF;
        }
        else {
            Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
        }
        SPI_close(masterSpi);
    }
    //*******************************************************//

    //*******************************************************//
    for (i = 0; i < 2; i++) {
        masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
        /* Copy message to transmit buffer */
        masterTxBuffer[0] = MASTER_MSG[1];
        transaction.count = 1;
        transaction.txBuf = (void *) masterTxBuffer;
        transaction.rxBuf = (void *) masterRxBuffer;

        GPIO_toggle(Board_GPIO_LED1);

        /* Perform SPI transfer */
        transferOK = SPI_transfer(masterSpi, &transaction);
        if (transferOK) {
            RX_Buffer_2 = masterRxBuffer[0] & 0x0FFF;
        }
        else {
            Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
        }
        SPI_close(masterSpi);
    }
    //*******************************************************//

    //*******************************************************//
    for (i = 0; i < 2; i++) {
        masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
        /* Copy message to transmit buffer */
        masterTxBuffer[0] = MASTER_MSG[2];
        transaction.count = 1;
        transaction.txBuf = (void *) masterTxBuffer;
        transaction.rxBuf = (void *) masterRxBuffer;

        GPIO_toggle(Board_GPIO_LED1);

        /* Perform SPI transfer */
        transferOK = SPI_transfer(masterSpi, &transaction);
        if (transferOK) {
            RX_Buffer_3 = masterRxBuffer[0] & 0x0FFF;
        }
        else {
            Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
        }
        SPI_close(masterSpi);
    }
    //*******************************************************//

    //*******************************************************//
    for (i = 0; i < 2; i++) {
        masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
        /* Copy message to transmit buffer */
        masterTxBuffer[0] = MASTER_MSG[3];
        transaction.count = 1;
        transaction.txBuf = (void *) masterTxBuffer;
        transaction.rxBuf = (void *) masterRxBuffer;

        GPIO_toggle(Board_GPIO_LED1);

        /* Perform SPI transfer */
        transferOK = SPI_transfer(masterSpi, &transaction);
        if (transferOK) {
            RX_Buffer_4 = masterRxBuffer[0] & 0x0FFF;
        }
        else {
            Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
        }
        SPI_close(masterSpi);
    }
    //*******************************************************//

    Display_printf(display, 0, 0, "ADC Channels: %lu -- %lu -- %lu -- %lu", RX_Buffer_1, RX_Buffer_2, RX_Buffer_3, RX_Buffer_4);
}

  • Hello,

    You should be able to read different channels without CS changing state. I predict that the timing for the SDI control registers is incorrect if you cannot do this. When you keep CS low, and try to read different channels, what do you get? please refer to datasheet page 17, to table 2 to 4 for control register information to change channels.

    During debugging, I suggest setting each input to different known DC value, example, Ch0 =GND, Ch1 =1V and so one, within the analog full scale though.

    Please include a scope shot of the digital communications, including CS, SDO, SDI, SCLK of 2 conversion cycles. this will help provide a visual to check timing as well as to confirm that what the code is actually doing vs what is meant to do.

    As for the bold statement you asked about. When CS is kept low and sclk pulses are still present, the device automatically start a new conversion cycle.

    One conversion cycle take 16 SCLK. within these 16 pulses, the first 4 are the acquisition phase, and the other 12 are the conversion phase. This get repeated for every set of 16SCLK provided.

    Regards, Cynthia

  • Hi,

    I Updated my code as reading multi channel without CS changing state. But my read values are seem as shifted. For example I see Channel-4 Value at Channel-1. I am sending my code and signals at below. Please check and suggest me what I should do.

    Real Voltage Values on Board is this: IN1 (0V; Decimal:0) - IN2 (3V3; Decimal: 4096) - IN3 (3V3; Decimal: 4096) - IN4 (27°C; Decimal: 1120)

    NOT: IN4 is connected Temp. Senson on ADC124S101EVM Board.

    But I got this Debug messages as you see also from signals: 1123 (IN1) -- 2 (IN2) -- 4059 (IN3) -- 4061 (IN4) !!!!!!!!!!!!!!!!!!!!!

    I Think ı moved with right way but why I got different values ı don't understand. Can you check situation and suggest me right way.

    MY CODE:

    /*
    * ======== stc3100.c ========
    */
    #include <stddef.h>
    #include <stdint.h>
    #include <string.h>

    /* POSIX Header files */
    #include <pthread.h>
    #include <semaphore.h>
    #include <unistd.h>

    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/SPI.h>
    #include <ti/display/Display.h>

    /* Example/Board Header files */
    #include "SKB_Board.h"

    #define THREADSTACKSIZE (1024)

    uint16_t MASTER_MSG[4]= {0x0000,0x0800,0x1000,0x1800};

    SPI_Handle masterSpi;
    SPI_Params spiParams;
    SPI_Transaction transaction;
    bool transferOK;
    int32_t status;
    uint16_t RX_Buffer_1,RX_Buffer_2,RX_Buffer_3,RX_Buffer_4,i,j;

    static Display_Handle display;

    uint16_t masterRxBuffer[4];
    uint16_t masterTxBuffer[4];

    void read_adc_channels();

    /*
    * ======== mainThread ========
    */
    void *mainThread(void *arg0)
    {
    /* Call driver init functions. */
    Display_init();
    GPIO_init();
    SPI_init();

    /* Configure the LED pins */
    GPIO_setConfig(Output1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

    /* Open the display for output */
    display = Display_open(Display_Type_UART, NULL);
    if (display == NULL) {
    /* Failed to open display driver */
    while (1);
    }

    /* Turn on user LED */
    GPIO_write(Output1, Board_GPIO_ON);

    Display_printf(display, 0, 0, "Starting the SPI master example");
    /* Open SPI as master (default) */
    SPI_Params_init(&spiParams);
    spiParams.frameFormat = SPI_POL0_PHA0;
    spiParams.dataSize = 16;
    spiParams.bitRate = 100000;
    masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
    Display_printf(display, 0, 0, "Master SPI initialized\n");

    /*
    * Master has opened Board_SPI_MASTER; set Board_SPI_MASTER_READY high to
    * inform the slave.
    */
    //GPIO_write(Board_SPI_MASTER_READY, 0);

    while(1)
    {
    read_adc_channels();
    usleep(500000);
    }
    }

    void read_adc_channels()
    {
    /* Copy message to transmit buffer */
    masterTxBuffer[0] = MASTER_MSG[0];
    masterTxBuffer[1] = MASTER_MSG[1];
    masterTxBuffer[2] = MASTER_MSG[2];
    masterTxBuffer[3] = MASTER_MSG[3];
    transaction.count = 4;
    transaction.txBuf = (void *) masterTxBuffer;
    transaction.rxBuf = (void *) masterRxBuffer;

    /* Perform SPI transfer */
    transferOK = SPI_transfer(masterSpi, &transaction);
    if (transferOK) {
    RX_Buffer_1 = masterRxBuffer[0] & 0x0FFF;
    RX_Buffer_2 = masterRxBuffer[1] & 0x0FFF;
    RX_Buffer_3 = masterRxBuffer[2] & 0x0FFF;
    RX_Buffer_4 = masterRxBuffer[3] & 0x0FFF;
    }
    else {
    Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
    }
    //*******************************************************//

    Display_printf(display, 0, 0, "ADC Channels: %lu -- %lu -- %lu -- %lu", RX_Buffer_1, RX_Buffer_2, RX_Buffer_3, RX_Buffer_4);
    GPIO_toggle(Output1);
    }

  • Hello,

    this device does not output the data for the selected channel in the same frame, but in the frame after. There is a one frame delay. Note that during the acquisition time is when the input voltage is sampled, this ends before the SDI data is completely sent for selecting which channel, so it is impossible to have same channel data for selected channel in one frame

    Example

    During Cycle N:

        SDI= select ch1

        SDO = data from cycle N-1

    During Cycle N+1:

        SDI= Select ch2

        SDO= Data from cycle N which is Ch1 data

    Regards, Cynthia