Could someone please explain to me what am I missing when setting up the registers of an ADS1255 ADC?
The setup fails every time. When I read back from the registers (after setting the up) I get back a totally different value from the one that I set up.
STATUS register values:
Received: 11111111
ADCON register values:
Expected: 0
Received: 11111111
DRATE register values:
Expected: 11110000
Received: 11111111
MUX register values:
Expected: 1111
Received: 11111111
Code belllow:
#include <SPI.h>
//ADC hook-up lines
#define SCK 14
#define MOSI 12
#define MISO 27
#define DRDY 26
#define CS 5
//SPI bus settings
#define SPISPEED 1800000
#define CLKIN 7680000 //7.68MHz (external crystal frequency)
//ADC commands
#define WREG 0x50
#define RDATA 0x01
#define RDATAC 0x03
#define RREG 0x10
#define SDATAC 0x0F
//enable stuff
#define ENABLE_VERBOSE_OUTPUT 1
/*
According to datasheet pg.26
---------------------------------
The data input pin (DIN) is used along with SCLK to send
data to the ADS1255/6. The data output pin (DOUT) along
with SCLK is used to read data from the ADS1255/6.
Data on DIN is shifted into the part on the falling edge of SCLK
while data is shifted out on DOUT on the rising edge of SCLK.
DOUT is high impedance when not in use to allow
DIN and DOUT to be connected together and be driven by
a bi-directional bus. Note: the RDATAC command must
not be issued while DIN and DOUT are connected
together.
*/
#define SPI_DATAIN_MODE SPI_MODE0 //DIN shifted out on the falling edge of SCLK
#define SPI_DATAOUT_MODE SPI_MODE1 //DOUT shifted out on the rising edge of SCLK
//ADC related
signed long raw;
byte adcData[3];
bool ok = false;
byte register_values;
//according to datasheet of ADC pg.6 t6 should be at leas 50 time CLKIN (master clock) period
int t6 = round((float)1 / CLKIN * 50 * 1000000) + 1; //*1000000 to convert from seconds to us
void setup() {
Serial.begin(2000000);
//SPI pins
pinMode(MISO, INPUT);
pinMode(MOSI, OUTPUT);
pinMode(SCK, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(DRDY, INPUT);
//init SPI bus
delay(500);
SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
delay(500);
/*
ADC setup
*/
while (digitalRead(DRDY)) {} // wait for ready_line to go low
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
//Reset to Power-Up Values (FEh)
SPI.transfer(0xFE);
SPI.endTransaction();
delayMicroseconds(100);
while (digitalRead(DRDY)) {} // wait for ready_line to go low
statusRegister_setup();
adconRegister_setup();
drateRegister_setup();
muxRegister_setup();
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
//SYNC command 1111 1100
SPI.transfer(0xFC);
delayMicroseconds(10);
//WAKEUP 0000 0000
SPI.transfer(0x00);
delayMicroseconds(10);
SPI.endTransaction();
}
void loop() {
// put your main code here, to run repeatedly:
}
void muxRegister_setup() {
/*
MUX REGISTER SETUP
*/
byte mux_reg = 0x01; //Mux Register (Address 01h)
byte mux_data = 0B00001111;
//chose the 2 inputs for your differential signal
// 0000 1111
// 0000 - AIN0 (default)
// 1111 - AINCOM
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(WREG | mux_reg); // MUX register
SPI.transfer(0x00); // 2nd command byte, write one register only
SPI.transfer(mux_data); // write the databyte to the register
SPI.endTransaction();
delayMicroseconds(10); //allow a delay between DIN and DOUT section
if (ENABLE_VERBOSE_OUTPUT) {
Serial.println("\nMUX register values: ");
register_values = 0;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(RREG | mux_reg);
SPI.transfer(0x00); // 2nd command byte, read one register only
SPI.endTransaction();
delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
register_values = SPI.transfer(0);
SPI.endTransaction();
Serial.print("Expected: ");
Serial.println(mux_data, BIN);
Serial.print("Received: ");
Serial.println(register_values, BIN);
}
}
void drateRegister_setup() {
/*
DRATE REGISTER SETUP
*/
byte drate_reg = 0x03; //data rate register address: 0x03
byte maxSampleRate = 0B11110000;
//set data rate to max. (30000 SPS)
byte minSampleRate = 0B00000011;
//set data rate to min. (2.5SPS SPS)
byte chosenRate = maxSampleRate;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(WREG | drate_reg);
SPI.transfer(0x00); // 2nd command byte, write one register only
SPI.transfer(chosenRate); // write the databyte to the register
SPI.endTransaction();
delayMicroseconds(10); //allow a delay between DIN and DOUT section
if (ENABLE_VERBOSE_OUTPUT) {
Serial.println("\nDRATE register values: ");
register_values = 0;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(RREG | drate_reg);
SPI.transfer(0x00); // 2nd command byte, read one register only
SPI.endTransaction();
delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
register_values = SPI.transfer(0);
SPI.endTransaction();
Serial.print("Expected: ");
Serial.println(chosenRate, BIN);
Serial.print("Received: ");
Serial.println(register_values, BIN);
}
}
void adconRegister_setup() {
/*
ADCON REGISTER SETUP
*/
byte adcon_reg = 0x02; //A/D Control Register address: 0x02
byte adcon_data = 0B00000000;
// 0 00 00 000
// 0 reserved always 0
// 00 - Clock Out off
// 00 - Sensor Detec off
// 000 - PGA gain = 1
//PGA SETTING
//1 ±5V
//2 ±2.5V
//4 ±1.25V
//8 ±0.625V
//16 ±312.5mV
//32 ±156.25mV
//64 ±78.125mV
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(WREG | adcon_reg);
SPI.transfer(0x00); // 2nd command byte, write one register only
SPI.transfer(adcon_data); // write the databyte to the register
SPI.endTransaction();
delayMicroseconds(10); //allow a delay between DIN and DOUT section
if (ENABLE_VERBOSE_OUTPUT) {
Serial.println("\nADCON register values: ");
register_values = 0;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(RREG | adcon_reg);
SPI.transfer(0x00); // 2nd command byte, read one register only
SPI.endTransaction();
delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
register_values = SPI.transfer(0);
SPI.endTransaction();
Serial.print("Expected: ");
Serial.println(adcon_data, BIN);
Serial.print("Received: ");
Serial.println(register_values, BIN);
}
}
void statusRegister_setup() {
/*
STATUS REGISTER SETUP
*/
byte status_reg = 0x00; // address of status reg (datasheet p. 30)
byte status_data = 0B0000001;
//000 0 0 0 1
//000 - Factory programmed Identification Bits
//0 - set MSB transfer
//0 - Auto-Calibration Disabled
//0 - Buffer Disabled
//1 - duplicates state of DRDY pin
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(WREG | status_reg);
SPI.transfer(0x00); // 2nd command byte, write one register only
SPI.transfer(status_data); // write the databyte to the register
SPI.endTransaction();
delayMicroseconds(10); //allow a delay between DIN and DOUT section
if (ENABLE_VERBOSE_OUTPUT) {
Serial.println("\nSTATUS register values: ");
register_values = 0;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(RREG | status_reg);
SPI.transfer(0x00); // 2nd command byte, read one register only
SPI.endTransaction();
delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
register_values = SPI.transfer(0);
SPI.endTransaction();
Serial.print("Received: ");
Serial.println(register_values, BIN);
}
}