Files
motor/Common/spi/ADC_ADS1256.c
T

527 lines
15 KiB
C
Raw Normal View History

2024-09-26 22:32:20 +08:00
#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);
}