#include "ADC_ADS1256.h" /* 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¡êo 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 static void cfgADC(ADC_ADS1256_t *adc); static void delayDATA(ADC_ADS1256_t *adc); static void writeReg(ADC_ADS1256_t *adc, uint8_t _RegID, uint8_t _RegValue); static uint8_t readReg(ADC_ADS1256_t *adc, uint8_t _RegID); static void writeCmd(ADC_ADS1256_t *adc, uint8_t _cmd); static uint8_t readChipID(ADC_ADS1256_t *adc); static void setChannel(ADC_ADS1256_t *adc); static void setDiffChannel(ADC_ADS1256_t *adc); static void waitDRDY(ADC_ADS1256_t *adc); static int32_t readData(ADC_ADS1256_t *adc); static uint8_t getGainVal(ADC_ADS1256_t *adc); static void isr(ADC_ADS1256_t *adc); static uint8_t scan(ADC_ADS1256_t *adc); static uint16_t voltageConvert(ADC_ADS1256_t *adc, float Vref, float voltage); static void readDiffChannel(ADC_ADS1256_t *adc, uint8_t); static uint32_t getDataRateVal_us(ADC_ADS1256_t *adc, uint8_t); static void getMaxWaitDelay_us(ADC_ADS1256_t *adc); static void resync(ADC_ADS1256_t *adc); bool ADC_ADS1256_init(ADC_ADS1256_t *adc, const char *name, SPI_DEV_t* dev, GPIO_TypeDef* drdy, uint16_t drdy_Pin) { adc->_dev = dev; adc->_drdy = drdy; adc->_drdy_Pin = drdy_Pin; adc->name = name; adc->scanMode = 0; adc->gain = 0; /* GAIN */ adc->dataRate = 7; /* DATA output speed*/ adc->buffer_en = 1; adc->channel=0; writeCmd(adc, CMD_WAKEUP); wait_us(25); if (readChipID(adc) != 0x03) { return false; } cfgADC(adc); uint8_t mux = readReg(adc, REG_MUX); if (mux != 0x08) { return false; } return true; }; uint8_t getGainVal(ADC_ADS1256_t *adc) { return (1<< adc->gain); //e.g. 1,2,4,8,16,32,64 } void cfgADC(ADC_ADS1256_t *adc) { 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(adc); uint8_t buf[6]; /* 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[2] = (0 << 3) | (1 << 2) | ( (adc->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[3] = 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[4] = (0 << 5) | (0 << 3) | ( (adc->gain & 0x07) << 0); //WriteReg(REG_ADCON, (0 << 5) | (0 << 2) | (GAIN_1 << 1)); /*choose 1: gain 1 ;input 5V/ buf[5] = s_tabDataRate[adc->dataRate]; // DRATE_100SPS; SPI_DEV_select(adc->_dev); /* SPICS? = 0 */ buf[0] = (CMD_WREG | 0); /* Write command register, send the register address */ buf[1] = (0x03); /* Register number 4,Initialize the number -1*/ SPI_DEV_transfer(adc->_dev, buf, sizeof(buf), NULL, 0, 1); SPI_DEV_unselect(adc->_dev); /* SPI cs = 1 */ } extern unsigned long getRunTimeCounterValue(void); void wait_us(unsigned long dt) { unsigned long t0 = getRunTimeCounterValue(); unsigned long t1 = t0 + dt; while (getRunTimeCounterValue() < t1) { ; } } void delayDATA(ADC_ADS1256_t *adc) { /* 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 */ } void writeReg(ADC_ADS1256_t *adc, uint8_t _RegID, uint8_t _RegValue) { SPI_DEV_select(adc->_dev); /* SPI cs = 0 */ uint8_t buf[3]; buf[0] = (CMD_WREG | _RegID); /*Write command register */ buf[1] = (0x00); /*Write the register number */ buf[2] = (_RegValue); /*send register value */ SPI_DEV_transfer(adc->_dev, buf, sizeof(buf), NULL, 0, 1); SPI_DEV_unselect(adc->_dev); /* SPI cs = 1 */ } uint8_t readReg(ADC_ADS1256_t *adc, uint8_t _RegID) { SPI_DEV_select(adc->_dev); /* SPI cs = 0 */ uint8_t buf[2]; buf[0] = (CMD_RREG | _RegID); /* Write command register */ buf[1] = (0x00); /* Write the register number */ SPI_DEV_transfer(adc->_dev, buf, 2, NULL, 0, 1); delayDATA(adc); /*delay time */ SPI_DEV_transfer(adc->_dev, NULL, 0, buf, 1, 1); SPI_DEV_unselect(adc->_dev); /* SPI cs = 1 */ return buf[0]; } void writeCmd(ADC_ADS1256_t *adc, uint8_t _cmd) { SPI_DEV_select(adc->_dev); /* SPI cs = 0 */ uint8_t buf[1]; buf[0] = _cmd; SPI_DEV_transfer(adc->_dev, buf, 1, NULL, 0, 1); SPI_DEV_unselect(adc->_dev); /* SPI cs = 1 */ } uint8_t readChipID(ADC_ADS1256_t *adc) { uint8_t id; waitDRDY(adc); id = readReg(adc, REG_STATUS); #ifdef DEBUG printf("ADC id = %02x\r\n", id); #endif return (id >> 4); } void setChannel(ADC_ADS1256_t *adc) { /* 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( adc->channel > 15 ) { return; } writeReg(adc, REG_MUX, (adc->channel << 4) | (1<<3)); /* Bit3 = 1, AINN connection AINCOM */ } void setDiffChannel(ADC_ADS1256_t *adc) { /* 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 (adc->channel == 0) { writeReg(adc, REG_MUX, (0 << 4) | 1); /* Diffchannel AIN0¡ê? AIN1 */ } else if (adc->channel == 1) { writeReg(adc, REG_MUX, (2 << 4) | 3); /*Diffchannel AIN2¡ê? AIN3 */ } else if (adc->channel == 2) { writeReg(adc, REG_MUX, (4 << 4) | 5); /*Diffchannel AIN4¡ê? AIN5 */ } else if (adc->channel == 3) { writeReg(adc, REG_MUX, (6 << 4) | 7); /*Diffchannel AIN6¡ê? AIN7 */ } } void waitDRDY(ADC_ADS1256_t *adc) { while ( HAL_GPIO_ReadPin(adc->_drdy, adc->_drdy_Pin) ); } int32_t readData(ADC_ADS1256_t *adc) { uint32_t readVal = 0; static uint8_t buf[3]; SPI_DEV_select(adc->_dev); /* SPI cs = 0 */ /* read ADC command */ buf[0] = CMD_RDATA; SPI_DEV_transfer(adc->_dev, buf, 1, NULL, 0, 1); delayDATA(adc); /*delay time */ /*Read the sample results 24bit*/ SPI_DEV_transfer(adc->_dev, NULL, 0, buf, 3, 1); readVal = ((uint32_t)buf[0] << 16) & 0x00FF0000; readVal |= ((uint32_t)buf[1] << 8); readVal |= buf[2]; SPI_DEV_unselect(adc->_dev); //* CS = 1 /* Extend a signed number*/ if (readVal & 0x800000) { readVal |= 0xFF000000; } return (int32_t)readVal; } void ADC_ADS1256_update(ADC_ADS1256_t *adc) { if (adc->scanMode == 0) /* 0 Single-ended input 8 channel, 1 Differential input 4 channels */ { setChannel(adc); /*Switch channel mode */ wait_us(5); writeCmd(adc, CMD_SYNC); wait_us(5); writeCmd(adc, CMD_WAKEUP); wait_us(25); if (adc->channel == 0) { adc->adcNow[7] = readData(adc); } else { adc->adcNow[adc->channel-1] = readData(adc); } if (++adc->channel >= 8) { adc->channel = 0; } } else /*Diffchannel*/ { setDiffChannel(adc); /* change Diffchannel */ wait_us(5); writeCmd(adc, CMD_SYNC); wait_us(5); writeCmd(adc, CMD_WAKEUP); wait_us(25); if (adc->channel == 0) { adc->adcNow[3] = readData(adc); } else { adc->adcNow[adc->channel-1] = readData(adc); } if (++adc->channel >= 4) { adc->channel = 0; } } } uint16_t voltageConvert(ADC_ADS1256_t *adc, float Vref, float voltage) { uint16_t _D_; _D_ = (uint16_t)(65536 * voltage / Vref); return _D_; } void readDiffChannel(ADC_ADS1256_t *adc, uint8_t nextChannel) { waitDRDY(adc); adc->prevChannel = adc->channel; adc->channel = nextChannel; if(adc->channel != adc->prevChannel) { setDiffChannel(adc); /*Switch channel mode to next channel to get it started*/ wait_us(5); writeCmd(adc, CMD_SYNC); wait_us(5); writeCmd(adc, CMD_WAKEUP); wait_us(25); } adc->adcNow[adc->prevChannel] = readData(adc); //get data from prev channel while new channel is integrating // pc.printf(" adcNow = %d\r\n", adcNow[prevChannel]); } uint32_t getDataRateVal_us(ADC_ADS1256_t *adc, 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 resync(ADC_ADS1256_t *adc) { waitDRDY(adc); wait_us(2); writeCmd(adc, CMD_SYNC); wait_us(5); writeCmd(adc, CMD_WAKEUP); }