ADS1256 program

ADS1256.cpp

Committer:
laserdad
Date:
2017-12-01
Revision:
0:897d3bb0accd

File content as of revision 0:897d3bb0accd:

#include "ADS1256.h"

extern Serial pc;

ADS1256::ADS1256(SPI *spi_itf, DigitalIn *nrdy_pin, DigitalOut *cs_pin)
{
    spi = spi_itf;
    cs = cs_pin;
    nrdy = nrdy_pin;
    *cs = 1;        // Assert CS high
    setSpi();
    scanMode = 1;
    gain = 0;        /* GAIN  */
    dataRate = 15;   /* DATA output  speed*/ 
    buffer_en = 1;
    channel=0;  
    getMaxWaitDelay_us();    
};

uint8_t ADS1256::getGainVal(void)
{
    return (1<<gain); //e.g. 1,2,4,8,16,32,64
}


void ADS1256::setSpi(void)
{
    spi->format(8, ADS1256_SPI_MODE);
    spi->frequency(1800000);
}



/*
*********************************************************************************************************
*   name: CfgADC
*   function: The configuration parameters of ADC gain, data rate and internal buffer;
*   parameter: gain: 0-5 (1-64)
*              dataRate:  0-16 (2.5-30000 sps)
*   The return value: NULL
*********************************************************************************************************
*/
void ADS1256::cfgADC(void)
{
    static const uint8_t s_tabDataRate[16] =
    {
        0x03,
        0x13,
        0x20,
        0x33,
        0x43,
        0x53,
        0x63,
        0x72,
        0x82,
        0x92,
        0xA1,
        0xB0,
        0xC0,
        0xD0,
        0xE0,
        0xF0       /*reset value */
    };

    waitDRDY();

    
    uint8_t buf[4];     /* Storage ads1256 register configuration parameters */

    /*Status register define
        Bits 7-4 ID3, ID2, ID1, ID0  Factory Programmed Identification Bits (Read Only)

        Bit 3 ORDER: Data Output Bit Order
            0 = Most Significant Bit First (default)
            1 = Least Significant Bit First
        Input data  is always shifted in most significant byte and bit first. Output data is always shifted out most significant
        byte first. The ORDER bit only controls the bit order of the output data within the byte.

        Bit 2 ACAL : Auto-Calibration
            0 = Auto-Calibration Disabled (default)
            1 = Auto-Calibration Enabled
        When Auto-Calibration is enabled, self-calibration begins at the completion of the WREG command that changes
        the PGA (bits 0-2 of ADCON register), DR (bits 7-0 in the DRATE register) or BUFEN (bit 1 in the STATUS register)
        values.

        Bit 1 BUFEN: Analog Input Buffer Enable
            0 = Buffer Disabled (default)
            1 = Buffer Enabled

        Bit 0 DRDY :  Data Ready (Read Only)
            This bit duplicates the state of the DRDY pin.

        ACAL=1  enable  calibration
    */
    buf[0] = (0 << 3) | (1 << 2) | ( (buffer_en & 0x01) << 1);//enable the internal buffer
//    buf[0] = (0 << 3) | (1 << 2) | (0 << 1);  // The internal buffer is prohibited

    //WriteReg(REG_STATUS, (0 << 3) | (1 << 2) | (1 << 1));

    buf[1] = 0x08;  

    /*  ADCON: A/D Control Register (Address 02h)
        Bit 7 Reserved, always 0 (Read Only)
        Bits 6-5 CLK1, CLK0 : D0/CLKOUT Clock Out Rate Setting
            00 = Clock Out OFF
            01 = Clock Out Frequency = fCLKIN (default)
            10 = Clock Out Frequency = fCLKIN/2
            11 = Clock Out Frequency = fCLKIN/4
            When not using CLKOUT, it is recommended that it be turned off. These bits can only be reset using the RESET pin.

        Bits 4-3 SDCS1, SCDS0: Sensor Detect Current Sources
            00 = Sensor Detect OFF (default)
            01 = Sensor Detect Current = 0.5 ¦Ì A
            10 = Sensor Detect Current = 2 ¦Ì A
            11 = Sensor Detect Current = 10¦Ì A
            The Sensor Detect Current Sources can be activated to verify  the integrity of an external sensor supplying a signal to the
            ADS1255/6. A shorted sensor produces a very small signal while an open-circuit sensor produces a very large signal.

        Bits 2-0 PGA2, PGA1, PGA0: Programmable Gain Amplifier Setting
            000 = 1 (default)
            001 = 2
            010 = 4
            011 = 8
            100 = 16
            101 = 32
            110 = 64
            111 = 64
    */
    buf[2] = (0 << 5) | (0 << 3) | ( (gain & 0x07) << 0);
    //WriteReg(REG_ADCON, (0 << 5) | (0 << 2) | (GAIN_1 << 1)); /*choose 1: gain 1 ;input 5V/
    buf[3] = s_tabDataRate[dataRate]; // DRATE_10SPS; 

    *cs = 0; /* SPICS¡ = 0 */
    spi->write(CMD_WREG | 0);    /* Write command register, send the register address */
    spi->write(0x03);            /* Register number 4,Initialize the number  -1*/

    spi->write(buf[0]);  /* Set the status register */
    spi->write(buf[1]);  /* Set the input channel parameters */
    spi->write(buf[2]);  /* Set the ADCON control register,gain */
    spi->write(buf[3]);  /* Set the output rate */

    *cs =1; /* SPI  cs = 1 */


    wait_us(50);
    getMaxWaitDelay_us();
}


/*
*********************************************************************************************************
*   name: DelayDATA
*   function: delay
*   parameter: NULL
*   The return value: NULL
*********************************************************************************************************
*/
void ADS1256::delayDATA(void)
{
    /*
        Delay from last SCLK edge for DIN to first SCLK rising edge for DOUT: RDATA, RDATAC,RREG Commands
        min  50   CLK = 50 * 0.13uS = 6.5uS
    */
    wait_us(10);    /* The minimum time delay 6.5us */
}




/*
*********************************************************************************************************
*   name: WriteReg
*   function: Write the corresponding register
*   parameter: _RegID: register  ID
*            _RegValue: register Value
*   The return value: NULL
*********************************************************************************************************
*/
void ADS1256::writeReg(uint8_t _RegID, uint8_t _RegValue)
{
    *cs = 0; /* SPI  cs  = 0 */
    spi->write(CMD_WREG | _RegID);   /*Write command register */
    spi->write(0x00);        /*Write the register number */

    spi->write(_RegValue);   /*send register value */
    *cs =1; /* SPI   cs = 1 */
}

/*
*********************************************************************************************************
*   name: ReadReg
*   function: readVal  the corresponding register
*   parameter: _RegID: register  ID
*   The return value: read register value
*********************************************************************************************************
*/
uint8_t ADS1256::readReg(uint8_t _RegID)
{
    uint8_t readVal;

    *cs = 0; /* SPI  cs  = 0 */
    spi->write(CMD_RREG | _RegID);   /* Write command register */
    spi->write(0x00);    /* Write the register number */


    delayDATA();    /*delay time */

    readVal = spi->write(0);  /* Read the register values */
    *cs =1; /* SPI   cs  = 1 */

    return readVal;
}

/*
*********************************************************************************************************
*   name: WriteCmd
*   function: Sending a single byte order
*   parameter: _cmd : command
*   The return value: NULL
*********************************************************************************************************
*/
void ADS1256::writeCmd(uint8_t _cmd)
{
    *cs = 0; /* SPI   cs = 0 */
    spi->write(_cmd);
    *cs =1; /* SPI  cs  = 1 */
}

/*
*********************************************************************************************************
*   name: ReadChipID
*   function: Read the chip ID
*   parameter: _cmd : NULL
*   The return value: four high status register
*********************************************************************************************************
*/
uint8_t ADS1256::readChipID(void)
{
    uint8_t id;

    //waitDRDY();
    id = readReg(REG_STATUS);
    #ifdef DEBUG
        pc.printf("id = %02x\r\n", id);
    #endif
    return (id >> 4);
}

/*
*********************************************************************************************************
*   name: Setchannel
*   function: Configuration channel number
*   parameter:  channel:  channel number  0--7
*   The return value: NULL
*********************************************************************************************************
*/
void ADS1256::setChannel()
{
    /*
    Bits 7-4 PSEL3, PSEL2, PSEL1, PSEL0: Positive Input channel (AINP) Select
        0000 = AIN0 (default)
        0001 = AIN1
        0010 = AIN2 (ADS1256 only)
        0011 = AIN3 (ADS1256 only)
        0100 = AIN4 (ADS1256 only)
        0101 = AIN5 (ADS1256 only)
        0110 = AIN6 (ADS1256 only)
        0111 = AIN7 (ADS1256 only)
        1xxx = AINCOM (when PSEL3 = 1, PSEL2, PSEL1, PSEL0 are ¡°don¡¯t care¡±)

        NOTE: When using an ADS1255 make sure to only select the available inputs.

    Bits 3-0 NSEL3, NSEL2, NSEL1, NSEL0: Negative Input channel (AINN)Select
        0000 = AIN0
        0001 = AIN1 (default)
        0010 = AIN2 (ADS1256 only)
        0011 = AIN3 (ADS1256 only)
        0100 = AIN4 (ADS1256 only)
        0101 = AIN5 (ADS1256 only)
        0110 = AIN6 (ADS1256 only)
        0111 = AIN7 (ADS1256 only)
        1xxx = AINCOM (when NSEL3 = 1, NSEL2, NSEL1, NSEL0 are ¡°don¡¯t care¡±)
    */
    if( channel > 15 )
    {
        return;
    }
    writeReg(REG_MUX, (channel << 4) | (1<<3)); /* Bit3 = 1, AINN connection AINCOM */
}

/*
*********************************************************************************************************
*   name: SetDiffchannel
*   function: The configuration difference channel
*   parameter:  channel:  channel number  0--3
*   The return value:  four high status register
*********************************************************************************************************
*/
void ADS1256::setDiffChannel()
{   
    /*
    Bits 7-4 PSEL3, PSEL2, PSEL1, PSEL0: Positive Input channel (AINP) Select
        0000 = AIN0 (default)
        0001 = AIN1
        0010 = AIN2 (ADS1256 only)
        0011 = AIN3 (ADS1256 only)
        0100 = AIN4 (ADS1256 only)
        0101 = AIN5 (ADS1256 only)
        0110 = AIN6 (ADS1256 only)
        0111 = AIN7 (ADS1256 only)
        1xxx = AINCOM (when PSEL3 = 1, PSEL2, PSEL1, PSEL0 are ¡°don¡¯t care¡±)

        NOTE: When using an ADS1255 make sure to only select the available inputs.

    Bits 3-0 NSEL3, NSEL2, NSEL1, NSEL0: Negative Input channel (AINN)Select
        0000 = AIN0
        0001 = AIN1 (default)
        0010 = AIN2 (ADS1256 only)
        0011 = AIN3 (ADS1256 only)
        0100 = AIN4 (ADS1256 only)
        0101 = AIN5 (ADS1256 only)
        0110 = AIN6 (ADS1256 only)
        0111 = AIN7 (ADS1256 only)
        1xxx = AINCOM (when NSEL3 = 1, NSEL2, NSEL1, NSEL0 are ¡°don¡¯t care¡±)
    */
    
    //use channel = 3 for strain gauge bridge
    //use channel = 0 for Vout2
    //use channel = 1 for Vout1
    
    if (channel == 0)
    {
        writeReg(REG_MUX, (0 << 4) | 1);    /* Diffchannel  AIN0£¬ AIN1 */
    }
    else if (channel == 1)
    {
        writeReg(REG_MUX, (2 << 4) | 3);    /*Diffchannel   AIN2£¬ AIN3 */
    }
    else if (channel == 2)
    {
        writeReg(REG_MUX, (4 << 4) | 5);    /*Diffchannel    AIN4£¬ AIN5 */
    }
    else if (channel == 3)
    {
        writeReg(REG_MUX, (6 << 4) | 7);    /*Diffchannel   AIN6£¬ AIN7 */
    }
}

/*
*********************************************************************************************************
*   name: WaitDRDY
*   function: delay time  wait for automatic calibration
*   parameter:  NULL
*   The return value:  NULL
*********************************************************************************************************
*/
void ADS1256::waitDRDY(void)
{
    while ( nrdy->read() );
}


void ADS1256::getMaxWaitDelay_us(void)
{
    if(dataRate == 0x00)
    {
        maxWaitDelay_us = getDataRateVal_us(dataRate) + 8000;
    }
    else
    {
        maxWaitDelay_us = getDataRateVal_us(dataRate-1);
    }
}

/*
***********************`**********************************************************************************
*   name: ReadData
*   function: read ADC value
*   parameter: NULL
*   The return value:  NULL
*********************************************************************************************************
*/
int32_t ADS1256::readData(void)
{
    uint32_t readVal = 0;
    static uint8_t buf[3];

    *cs = 0; /* SPI   cs = 0 */

    spi->write(CMD_RDATA);   /* read ADC command  */

    delayDATA();    /*delay time  */

    /*Read the sample results 24bit*/
    buf[0] = spi->write(0);
    buf[1] = spi->write(0);
    buf[2] = spi->write(0);

    readVal = ((uint32_t)buf[0] << 16) & 0x00FF0000;
    readVal |= ((uint32_t)buf[1] << 8);  
    readVal |= buf[2];

    *cs =1; //* CS = 1
    /* Extend a signed number*/
    if (readVal & 0x800000)
    {
        readVal |= 0xFF000000;
    }

    return (int32_t)readVal;
}


/*
*********************************************************************************************************
*   name: ADS1256::GetAdc
*   function: read ADC value
*   parameter:  channel number 0--7
*   The return value:  ADC vaule (signed number)
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*   name: ADS1256::ISR
*   function: Collection procedures
*   parameter: NULL
*   The return value:  NULL
*********************************************************************************************************
*/
void ADS1256::isr(void)
{
    if (scanMode == 0)   /*  0  Single-ended input  8 channel, 1 Differential input  4 channels */
    {
        setChannel(); /*Switch channel mode */
        wait_us(5);

        writeCmd(CMD_SYNC);
        wait_us(5);

        writeCmd(CMD_WAKEUP);
        wait_us(25);

        if (channel == 0)
        {
            adcNow[7] = readData();  
        }
        else
        {
            adcNow[channel-1] = readData();   
        }

        if (++channel >= 8)
        {
            channel = 0;
        }
    }
    else    /*Diffchannel*/
    {
        
        setDiffChannel(); /* change Diffchannel */
        wait_us(5);

        writeCmd(CMD_SYNC);
        wait_us(5);

        writeCmd(CMD_WAKEUP);
        wait_us(25);

        if (channel == 0)
        {
            adcNow[3] = readData();  
        }
        else
        {
            adcNow[channel-1] = readData();   
        }

        if (++channel >= 4)
        {
            channel = 0;
        }
    }
}

/*
*********************************************************************************************************
*   name: ADS1256::Scan
*   function: 
*   parameter:NULL
*   The return value:  1
*********************************************************************************************************
*/
uint8_t ADS1256::scan(void)
{
    if (!(cs->read()))
    {
        isr();
        return 1;
    }

    return 0;
}

/*
*********************************************************************************************************
*   name: Voltage_Convert
*   function:  Voltage value conversion function
*   parameter: Vref : The reference voltage 3.3V or 5V
*              voltage : output DAC value 
*   The return value:  NULL
*********************************************************************************************************
*/
uint16_t ADS1256::voltageConvert(float Vref, float voltage)
{
    uint16_t _D_;
    _D_ = (uint16_t)(65536 * voltage / Vref);
    
    return _D_;
}

void ADS1256::readDiffChannel(uint8_t nextChannel)
{
    waitDRDY();
    prevChannel = channel;
    channel = nextChannel;
    if(channel != prevChannel)
    {
        setDiffChannel(); /*Switch channel mode to next channel to get it started*/
        wait_us(5);
    
        writeCmd(CMD_SYNC);
        wait_us(5);
    
        writeCmd(CMD_WAKEUP);
        wait_us(25);
    }
    adcNow[prevChannel] = readData(); //get data from prev channel while new channel is integrating
//    pc.printf(" adcNow = %d\r\n", adcNow[prevChannel]); 
}

uint32_t ADS1256::getDataRateVal_us(uint8_t dataRateIndex)
{
    static const uint32_t tabDataRateVal_us[16] =
    {
        400000,
        200000,
        100000,
        66667,
        40000,
        33334,
        16667,
        16667,
        10000,
        2000,
        1000,
        500,
        267,
        134,
        34,
        7
      /*reset the default values  */
    };   
    return tabDataRateVal_us[dataRateIndex];
}

void ADS1256::waitNDRDY(void)
{
    while(!nrdy->read());    
}

void ADS1256::resync(void)
{
        waitDRDY();
        wait_us(2);

        writeCmd(CMD_SYNC);
        wait_us(5);
    
        writeCmd(CMD_WAKEUP);
}