我正在尝试将 ads124s08与 teensy 3.6连接,以读取某些电池中的数据。 编写该代码是为了配置 ADC,使其使用 5V 单极外部参考,增益设置为1,4000 SPS,并使用微控制器的外部时钟。 A 将 Arduino IDE 用于此目的。
我正在附加逻辑分析器输出的图像,逻辑分析器输出在 SPI 通信 /resized-image/__size/320x240/__key/communityserver-discussion-components-files/73/WhatsApp-Image-2022_2D00_01_2D00_18-at-12.12.06-AM.jpeg 期间将 ADC 输出显示为全部零
我还附上了我用于此目的的代码
#include<SPI.h>
//#include <TimerOne.h>
int CS_PIN = 10;
int START_PIN = 5;
int RESET_PIN = 6;
int CKEN_PIN = 13;
int DRDY_PIN = 14;
int lastSample;
int mosi = 11;
int miso = 12;
SPISettings mySPISettings(4000000, MSBFIRST, SPI_MODE1);
#define NUM_REGISTERS 18
//rgeister map
#define ID_ADDR_MASK 0x00
#define STATUS_ADDR_MASK 0x01
#define INPMUX_ADDR_MASK 0x02
#define PGA_ADDR_MASK 0x03
#define DATARATE_ADDR_MASK 0x04
#define REF_ADDR_MASK 0x05
#define IDACMAG_ADDR_MASK 0x06
#define IDACMUX_ADDR_MASK 0x07
#define VBIAS_ADDR_MASK 0x08
#define SYS_ADDR_MASK 0x09
#define OFCAL0_ADDR_MASK 0x0A
#define OFCAL1_ADDR_MASK 0x0B
#define OFCAL2_ADDR_MASK 0x0C
#define FSCAL0_ADDR_MASK 0x0D
#define FSCAL1_ADDR_MASK 0x0E
#define FSCAL2_ADDR_MASK 0x0F
#define GPIODAT_ADDR_MASK 0x10
#define GPIOCON_ADDR_MASK 0x11
/* Opcode masks (or "Commands" if you will...) */
#define NOP_OPCODE_MASK 0x00
#define WAKE_OPCODE_MASK 0x02
#define SLEEP_OPCODE_MASK 0x04
#define RESET_OPCODE_MASK 0x06
#define START_OPCODE_MASK 0x08
#define STOP_OPCODE_MASK 0x0A
#define SFOCAL_OPCODE_MASK 0x19
#define SYOCAL_OPCODE_MASK 0x16
#define SYGCAL_OPCODE_MASK 0x17
#define RDATA_OPCODE_MASK 0x12
#define REGRD_OPCODE_MASK 0x20
#define REGWR_OPCODE_MASK 0x40
/* Define the ADC positive input channels (MUXP) */
#define ADS_P_AIN0 0x00
#define ADS_P_AIN1 0x10
#define ADS_P_AIN2 0x20
#define ADS_P_AIN3 0x30
#define ADS_P_AIN4 0x40
#define ADS_P_AIN5 0x50
#define ADS_P_AIN6 0x60
#define ADS_P_AIN7 0x70
#define ADS_P_AIN8 0x80
#define ADS_P_AIN9 0x90
#define ADS_P_AIN10 0xA0
#define ADS_P_AIN11 0xB0
#define ADS_P_AINCOM 0xC0
/* Define the ADC negative input channels (MUXN)*/
#define ADS_N_AIN0 0x00
#define ADS_N_AIN1 0x01
#define ADS_N_AIN2 0x02
#define ADS_N_AIN3 0x03
#define ADS_N_AIN4 0x04
#define ADS_N_AIN5 0x05
#define ADS_N_AIN6 0x06
#define ADS_N_AIN7 0x07
#define ADS_N_AIN8 0x08
#define ADS_N_AIN9 0x09
#define ADS_N_AIN10 0x0A
#define ADS_N_AIN11 0x0B
#define ADS_N_AINCOM 0x0C
/* Define PGA control */
#define ADS_PGA_BYPASS 0x00
#define ADS_PGA_ENABLED 0x08
/* Define Gain */
#define ADS_GAIN_1 0x00
#define ADS_GAIN_2 0x01
#define ADS_GAIN_4 0x02
#define ADS_GAIN_8 0x03
#define ADS_GAIN_16 0x04
#define ADS_GAIN_32 0x05
#define ADS_GAIN_64 0x06
#define ADS_GAIN_128 0x07
/System Control register/
#define ADS_SENDSTATUS_DISABLE 0x00
#define ADS_SENDSTATUS_ENABLE 0x01
/Reference Control register/
#define ADS_FLAG_REF_DISABLE 0x00
#define ADS_FLAG_REF_EN_L0 0x40
#define ADS_FLAG_REF_EN_BOTH 0x80
#define ADS_FLAG_REF_EN_10M 0xC0
#define ADS_REFP_BYP_DISABLE 0x20
#define ADS_REFP_BYP_ENABLE 0x00
#define ADS_REFN_BYP_DISABLE 0x10
#define ADS_REFN_BYP_ENABLE 0x00
#define ADS_REFSEL_P0 0x00
#define ADS_REFSEL_P1 0x04
#define ADS_REFSEL_INT 0x08
#define ADS_REFINT_OFF 0x00
#define ADS_REFINT_ON_PDWN 0x01
#define ADS_REFINT_ON_ALWAYS 0x02
/* Flag to signal that we are in the process of collecting data */
#define DATA_MODE_NORMAL 0x00
#define DATA_MODE_STATUS 0x01
#define DATA_MODE_CRC 0x02
class ADS124S08
{
// Device command prototypes
public:
ADS124S08(void);
void begin();
char regRead(unsigned int regnum);
void readRegs(unsigned int regnum, unsigned int count, uint8_t *data);
void regWrite(unsigned int regnum, unsigned char data);
void writeRegs(unsigned int regnum, unsigned int howmuch, unsigned char *data);
void reStart(void);
void sendCommand(uint8_t op_code);
int rData(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC);
int dataRead(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC);
void selectDeviceCSLow(void);
void releaseChipSelect(void);
void assertStart(void);
void deassertStart(void);
void assertClock(void);
void deassertClock(void);
bool converting;
uint8_t registers[NUM_REGISTERS];
private:
bool fStart;
void DRDY_int(void);
uint8_t _drdy_pin;
uint8_t _start_pin;
uint8_t _reset_pin;
}adc;
ADS124S08::ADS124S08(void) // pin config and reg map
{
pinMode( CS_PIN, OUTPUT );
pinMode( START_PIN, OUTPUT );
pinMode( RESET_PIN, OUTPUT );
pinMode( CKEN_PIN, OUTPUT );
pinMode( DRDY_PIN, INPUT );
pinMode( mosi, OUTPUT );
pinMode( miso, INPUT );
digitalWrite( START_PIN, LOW );
digitalWrite( RESET_PIN, HIGH );
digitalWrite( CKEN_PIN, LOW );
/* Default register settings */
registers[ID_ADDR_MASK] = 0x08;
registers[STATUS_ADDR_MASK] = 0x80;
registers[INPMUX_ADDR_MASK] = 0x01;
registers[PGA_ADDR_MASK] = 0x00;
registers[DATARATE_ADDR_MASK] = 0x14;
registers[REF_ADDR_MASK] = 0x10;
registers[IDACMAG_ADDR_MASK] = 0x00;
registers[IDACMUX_ADDR_MASK] = 0xFF;
registers[VBIAS_ADDR_MASK] = 0x00;
registers[SYS_ADDR_MASK] = 0x10;
registers[OFCAL0_ADDR_MASK] = 0x00;
registers[OFCAL1_ADDR_MASK] = 0x00;
registers[OFCAL2_ADDR_MASK] = 0x00;
registers[FSCAL0_ADDR_MASK] = 0x00;
registers[FSCAL1_ADDR_MASK] = 0x00;
registers[FSCAL2_ADDR_MASK] = 0x40;
registers[GPIODAT_ADDR_MASK] = 0x00;
registers[GPIOCON_ADDR_MASK] = 0x00;
fStart = false;
releaseChipSelect();
deassertStart();
}
void ADS124S08::begin() //start transaction
{
SPI.begin( );
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode( SPI_MODE1 );
SPI.setClockDivider(21); //the system clock can be divided by values from 1 to 255. The default value is 21, which sets the clock to 4 MHz like other Arduino boards.
#if defined (SPI_HAS_TRANSACTION)
mySPISettings = SPISettings(4000000, MSBFIRST, SPI_MODE1);
#endif
}
char ADS124S08::regRead(unsigned int regnum)
{
int i;
uint8_t ulDataTx[3];
uint8_t ulDataRx[3];
ulDataTx[0] = REGRD_OPCODE_MASK + (regnum & 0x1f);
ulDataTx[1] = 0x00;
ulDataTx[2] = 0x00;
selectDeviceCSLow();
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(mySPISettings);
#endif
for(i = 0; i < 3; i++)
ulDataRx[i] = SPI.transfer(ulDataTx[i]);
if(regnum < NUM_REGISTERS)
registers[regnum] = ulDataRx[2];
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
releaseChipSelect();
//Serial.println("regRead tx: %02x %02x %02x",ulDataTx[0],ulDataTx[1],ulDataTx[2]);
//Serial.println("regRead rx: %02x %02x %02x",ulDataRx[0],ulDataRx[1],ulDataRx[2]);
return ulDataRx[2];
}
void ADS124S08::readRegs(unsigned int regnum, unsigned int count, uint8_t *data)
{
int i;
uint8_t ulDataTx[2];
ulDataTx[0] = REGRD_OPCODE_MASK + (regnum & 0x1f);
ulDataTx[1] = count-1;
selectDeviceCSLow();
SPI.transfer(ulDataTx[0]);
SPI.transfer(ulDataTx[1]);
for(i = 0; i < count; i++)
{
data[i] = SPI.transfer(0);
if(regnum+i < NUM_REGISTERS)
registers[regnum+i] = data[i];
}
releaseChipSelect();
}
void ADS124S08::regWrite(unsigned int regnum, unsigned char data)
{
uint8_t ulDataTx[3];
ulDataTx[0] = REGWR_OPCODE_MASK + (regnum & 0x1f);
ulDataTx[1] = 0x00;
ulDataTx[2] = data;
selectDeviceCSLow();
SPI.transfer(ulDataTx[0]);
SPI.transfer(ulDataTx[1]);
SPI.transfer(ulDataTx[2]);
releaseChipSelect();
//Serial.println("regWrite tx: %02x %02x %02x",ulDataTx[0],ulDataTx[1],ulDataTx[2]);
return;
}
void ADS124S08::writeRegs(unsigned int regnum, unsigned int howmuch, unsigned char *data)
{
unsigned int i;
uint8_t ulDataTx[2];
ulDataTx[0] = REGWR_OPCODE_MASK + (regnum & 0x1f);
ulDataTx[1] = howmuch-1;
selectDeviceCSLow();
SPI.transfer(ulDataTx[0]);
SPI.transfer(ulDataTx[1]);
for(i=0; i < howmuch; i++)
{
SPI.transfer( data[i] );
if(regnum+i < NUM_REGISTERS)
registers[regnum+i] = data[i];
}
releaseChipSelect();
return;
}
void ADS124S08::reStart(void)
{
sendCommand(STOP_OPCODE_MASK);
sendCommand(START_OPCODE_MASK);
return;
}
void ADS124S08::sendCommand(uint8_t op_code)
{
selectDeviceCSLow();
SPI.transfer(op_code);
releaseChipSelect();
return;
}
int ADS124S08::rData(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC)
{
int result = -1;
selectDeviceCSLow();
// according to datasheet chapter 9.5.4.2 Read Data by RDATA Command
sendCommand(RDATA_OPCODE_MASK);
// if the Status byte is set - grab it
uint8_t shouldWeReceiveTheStatusByte = (registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS;
if( shouldWeReceiveTheStatusByte )
{
dStatus[0] = SPI.transfer(0x00);
//Serial.print("status: ");
//Serial.print(dStatus[0]);
}
// get the conversion data (3 bytes)
uint8_t data[3];
data[0] = SPI.transfer(0x00);
data[1] = SPI.transfer(0x00);
data[2] = SPI.transfer(0x00);
result = data[0];
result = (result<<8) + data[1];
result = (result<<8) + data[2];
//Serial.println(" 1: %02x 2: %02x, 3: %02x = %d", data[0], data[1], data[2], result);
// is CRC enabled?
uint8_t isCrcEnabled = (registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC;
if( isCrcEnabled )
{
dCRC[0] = SPI.transfer(0x00);
}
releaseChipSelect();
return result;
}
int ADS124S08::dataRead(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC)
{
uint8_t xcrc;
uint8_t xstatus;
int iData;
selectDeviceCSLow();
if((registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS)
{
xstatus = SPI.transfer(0x00);
Serial.print("0:");
Serial.print(xstatus);
dStatus[0] = (uint8_t)xstatus;
}
// get the conversion data (3 bytes)
uint8_t data[3];
data[0] = SPI.transfer(0x00);
data[1] = SPI.transfer(0x00);
data[2] = SPI.transfer(0x00);
Serial.print(" 1:");
Serial.print(data[0]);
Serial.print(" 2:");
Serial.print(data[1]);
Serial.print(" 3:");
Serial.println(data[2]);
iData = data[0];
iData = (iData<<8) + data[1];
iData = (iData<<8) + data[2];
if((registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC)
{
xcrc = SPI.transfer(0x00);
dCRC[0] = (uint8_t)xcrc;
}
releaseChipSelect();
return iData ;
}
void ADS124S08::selectDeviceCSLow(void){
digitalWrite( CS_PIN, LOW );
}
void ADS124S08::releaseChipSelect(void){
digitalWrite( CS_PIN, HIGH );
}
void ADS124S08::assertStart()
{
fStart = true;
digitalWrite(START_PIN ,HIGH);
}
void ADS124S08::deassertStart()
{
fStart = false;
digitalWrite(START_PIN, LOW);
}
void ADS124S08::assertClock()
{
digitalWrite(CKEN_PIN, 1);
}
void ADS124S08::deassertClock()
{
digitalWrite(CKEN_PIN, LOW);
}
void setup()
{
Serial.begin(9600);
delay(100);
adc.begin();
delay(100);
adc.sendCommand(RESET_OPCODE_MASK);
delay(100);
regMap();
configureAdc();
Serial.println("After config");
regMap();
}
void loop()
{
long now = millis();
//uint8_t status;
// Check if it's X seconds since last conversion
if( now - lastSample > 25 ){ //delay between two conversions taken as 25ms
//Serial.print(sampleNumber);
//Serial.print(" ");
lastSample = now;
readData();
}
}
void configureAdc()
{
// Make sure the device is awake
adc.sendCommand( WAKE_OPCODE_MASK );
// use channel 1 as positive and channel 2 as negative input
adc.regWrite( INPMUX_ADDR_MASK, ADS_P_AIN0 + ADS_N_AIN1 ); // mux selection reg: AIN0 - +ve and AIN1 - -ve (default)
// set PGA to 1x
adc.regWrite( PGA_ADDR_MASK, ADS_PGA_BYPASS + ADS_GAIN_1 ); //Gain setting reg: PGA bypassed(default), gain set to 1
// The IDAC will only work if we enable the internal reference (ref Datasheet 9.3.7)
//adc.regWrite( REF_ADDR_MASK, ADS_REFINT_ON_ALWAYS + ADS_REFSEL_P0 );
// use channel 3 as IDAC 1 (excitation current source)
//adc.regWrite( IDACMUX_ADDR_MASK, ADS_IDAC1_A2 + ADS_IDAC2_OFF ); //We are not using internal reference
// set IDAC 1 to output 500uA
//adc.regWrite( IDACMAG_ADDR_MASK, ADS_IDACMAG_500 );
// Turn on status for debugging
adc.regWrite( SYS_ADDR_MASK, ADS_SENDSTATUS_ENABLE ); //Status bit while reading data: pg no. 70 in datasheet
//Configuring external register
adc.regWrite( REF_ADDR_MASK, ADS_FLAG_REF_DISABLE + ADS_REFP_BYP_ENABLE + ADS_REFN_BYP_DISABLE + ADS_REFSEL_P0); //REFP0 and REFN0 as external reference
//Configuring the data rate register
adc.regWrite( DATARATE_ADDR_MASK, ADS_CLKSEL_EXT + ADS_FILTERTYPE_LL + ADS_DR_4000);
adc.reStart();
delay(10);
//regMap2();
}
void readData()
{
uint8_t dStatus = 0;
uint8_t dData;
uint8_t dCRC = 0;
int data = 0;
/* Read out the results */
data = adc.dataRead(&dStatus, &dData, &dCRC); //call to dataRead() - the 24 bit data stored in iData will be stored in data
/*
* Need to determine if Status and/or CRC is enabled to transmit as desired
*/
/*if((adc.registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS) //Not yet completely understood these nested if loops
{
if((adc.registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC)
{
Serial.println("Conversion Data 0x%06x with Status 0x%02x and CRC 0x%02x.", data, dStatus, dCRC);
}
else
{
//sSerial.println("Conversion Data 0x%06x with Status 0x%02x. DEC %02d", data, dStatus,data);
}
}
else if((adc.registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC)
{
Serial.println("Conversion Data 0x%06x with CRC 0x%02x.", data, dCRC);
}
else*/
//{
Serial.println(data,DEC); //This is where the raw conversion result should be available
//}
/* Set ADC back to the previous configuration */
//adc.sendCommand(STOP_OPCODE_MASK);
//adc.sendCommand(SLEEP_OPCODE_MASK);
//return dStatus;
}
void regMap(void)
{
unsigned int index;
char cTemp;
Serial.println("Register Contents");
Serial.println("---------------------");
for(index=0; index < 18 ; index++)
{
cTemp = adc.regRead(index);
Serial.println(index, cTemp);
}
}
