ADS1256 program

Files at this revision

API Documentation at this revision

Comitter:
laserdad
Date:
Fri Dec 01 21:31:48 2017 +0000
Commit message:
last known version;

Changed in this revision

ADS1256.cpp Show annotated file Show diff for this revision Revisions of this file
ADS1256.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADS1256.cpp	Fri Dec 01 21:31:48 2017 +0000
@@ -0,0 +1,582 @@
+#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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADS1256.h	Fri Dec 01 21:31:48 2017 +0000
@@ -0,0 +1,141 @@
+#ifndef __ADS1256_H__
+#define __ADS1256_H__
+
+#include "mbed.h"
+
+#define ADS1256_SPI_MODE 1
+#define DRATE_MAX 16
+#define DEBUG
+
+#define ADS1256_GAIN_1 0 /* GAIN   1 */
+#define ADS1256_GAIN_2 1  /*GAIN   2 */
+#define ADS1256_GAIN_4 2  /*GAIN   4 */
+#define ADS1256_GAIN_8 3  /*GAIN   8 */
+#define ADS1256_GAIN_16 4  /* GAIN  16 */
+#define ADS1256_GAIN_32 5  /*GAIN    32 */
+#define ADS1256_GAIN_64 6  /*GAIN    64 */
+
+
+#define ADS1256_30000SPS 15
+#define ADS1256_15000SPS 14
+#define ADS1256_7500SPS 13
+#define ADS1256_3750SPS 12
+#define ADS1256_2000SPS 11
+#define ADS1256_1000SPS 10
+#define ADS1256_500SPS 9
+#define ADS1256_100SPS 8
+#define ADS1256_60SPS 7
+#define ADS1256_50SPS 6
+#define ADS1256_30SPS 5
+#define ADS1256_25SPS 4
+#define ADS1256_15SPS 3
+#define ADS1256_10SPS 2
+#define ADS1256_5SPS 1
+#define ADS1256_2d5SPS 0
+
+
+class ADS1256
+{
+    SPI *spi;
+    DigitalOut *cs;
+    DigitalIn *nrdy;
+    
+    public:
+    ADS1256(SPI *, DigitalIn *, DigitalOut *);
+    uint8_t gain;
+    uint8_t dataRate;
+    int32_t adcNow[8];          /* ADC  Conversion value */
+    uint8_t channel;            /* The current channel*/
+    uint8_t prevChannel;        /* The previous channel --when muxing */
+    uint8_t scanMode;   /*Scanning mode,   0 = Single-ended input  8 channel; 1= Differential input  4 channels*/
+    uint8_t buffer_en;
+    uint32_t maxWaitDelay_us;
+        /* gain channelî */
+
+    
+    /* Sampling speed choice*/
+    /* 
+        11110000 = 30,000SPS (default)
+        11100000 = 15,000SPS
+        11010000 = 7,500SPS
+        11000000 = 3,750SPS
+        10110000 = 2,000SPS
+        10100001 = 1,000SPS
+        10010010 = 500SPS
+        10000010 = 100SPS
+        01110010 = 60SPS
+        01100011 = 50SPS
+        01010011 = 30SPS
+        01000011 = 25SPS
+        00110011 = 15SPS
+        00100011 = 10SPS
+        00010011 = 5SPS
+        00000011 = 2.5SPS
+    */
+
+    
+    /*Register definitions Table 23. Register Map --- ADS1256 datasheet Page 30*/
+    enum
+    {
+        /*Register address, followed by reset the default values */
+        REG_STATUS = 0, // x1H
+        REG_MUX    = 1, // 01H
+        REG_ADCON  = 2, // 20H
+        REG_DRATE  = 3, // F0H
+        REG_IO     = 4, // E0H
+        REG_OFC0   = 5, // xxH
+        REG_OFC1   = 6, // xxH
+        REG_OFC2   = 7, // xxH
+        REG_FSC0   = 8, // xxH
+        REG_FSC1   = 9, // xxH
+        REG_FSC2   = 10, // xxH
+    };
+    
+    /* Command definition£º TTable 24. Command Definitions --- ADS1256 datasheet Page 34 */
+    enum
+    {
+        CMD_WAKEUP  = 0x00, // Completes SYNC and Exits Standby Mode 0000  0000 (00h)
+        CMD_RDATA   = 0x01, // Read Data 0000  0001 (01h)
+        CMD_RDATAC  = 0x03, // Read Data Continuously 0000   0011 (03h)
+        CMD_SDATAC  = 0x0F, // Stop Read Data Continuously 0000   1111 (0Fh)
+        CMD_RREG    = 0x10, // Read from REG rrr 0001 rrrr (1xh)
+        CMD_WREG    = 0x50, // Write to REG rrr 0101 rrrr (5xh)
+        CMD_SELFCAL = 0xF0, // Offset and Gain Self-Calibration 1111    0000 (F0h)
+        CMD_SELFOCAL= 0xF1, // Offset Self-Calibration 1111    0001 (F1h)
+        CMD_SELFGCAL= 0xF2, // Gain Self-Calibration 1111    0010 (F2h)
+        CMD_SYSOCAL = 0xF3, // System Offset Calibration 1111   0011 (F3h)
+        CMD_SYSGCAL = 0xF4, // System Gain Calibration 1111    0100 (F4h)
+        CMD_SYNC    = 0xFC, // Synchronize the A/D Conversion 1111   1100 (FCh)
+        CMD_STANDBY = 0xFD, // Begin Standby Mode 1111   1101 (FDh)
+        CMD_RESET   = 0xFE, // Reset to Power-Up Values 1111   1110 (FEh)
+    };
+
+    
+
+
+    
+    //declare functions
+    void setSpi(void);
+    void cfgADC(void);
+    void delayDATA(void);
+    void writeReg(uint8_t _RegID, uint8_t _RegValue);
+    uint8_t readReg(uint8_t _RegID);
+    void writeCmd(uint8_t _cmd);
+    uint8_t readChipID(void);
+    void setChannel();
+    void setDiffChannel();
+    void waitDRDY(void);
+    void waitNDRDY(void);
+    int32_t readData(void);
+    uint8_t getGainVal(void);
+    void isr(void);
+    uint8_t scan(void);
+    uint16_t voltageConvert(float Vref, float voltage);
+    void readDiffChannel(uint8_t);
+    uint32_t getDataRateVal_us(uint8_t);
+    void getMaxWaitDelay_us(void);
+    void resync(void);
+
+};
+
+#endif
\ No newline at end of file