This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS131A04: Reducing communication time between ADS131A04 and STM32F7 while sending dataframe

Part Number: ADS131A04


Hello,

in my project I use an 595-ADS131A04IPBSR to perform analog to digital conversion and the data is read by a STM32F7 microcontroller. The ADC work in asynchronous interrupt mode because the electrical designer made an hard connection of the pin M2 to Vdd. The ADC is set to send words of 24 bits and the time required by the microcontroller to read each data frame is more than 40 us, with peaks up to 50 us. 

Due to new requirements, I would like to reduce this time to about 35 us, but I am not sure about the best strategy, thus I would be very grateful if someone could help me.

I attached the code for the ADC initialization and ADC read.

I thank you in advance.

Best regards,

Giovanni

//The following code is actually written in the header filelength//----------ADC24bit Definitions----------//
extern SPI_HandleTypeDef hspi1;



//----------ADC24bit Definitions----------//
#define ADC24_SPI_READY 	0xFF04
#define ADC24_A_SYS_CFG		0b01101000 		 //Bit representation of the desired A_SYS_CFG register
#define ADC24_D_SYS_CFG		0b00111100 		 //Bit representation of the desired D_SYS_CFG register
#define ADC24_CLK1_CFG		0b00000010 		 //After 0b, CLK1_CFG register. Change bit 1 to 3 for changing Fin/Ficlk ratio
#define ADC24_CLK2_CFG		0b00101001 		 //After 0b, CLK2_CFG register. Change bit 5 to 7 for changing Ficlk/Fmod ratio. Change bit 3 to 0 to change OSR
#define ADC24_ENA			0b00001111 		 //Bit representation of the Enable register
#define ADC24_V14_SCALE		1.4446e-4 		 // voltage amplified in the analog circuit: 	0.36115e-4= Vref/2^23 /(2*(1+10k/inf)) (x1000 to make it in mV)
#define ADC24_V23_SCALE		0.122406e-4 	 //// voltage amplified in the analog circuit: 	0.058154e-4= Vref/2^23 /(2*(1+9.9k/909)) (x1000 to make it in mV)
#define ADC24_I14_SCALE		1.458462e-6		 //is amplified in the analog circuit :			1.458462e-5= 1/4 * Vref/2^23 (x10 uA/0.499V): result in uA
//#define ADC24_V14_SCALE		0.36115e-4 		 // voltage amplified in the analog circuit: 	0.36115e-4= Vref/2^23 /(2*(1+10k/3.3k)) (x1000 to make it in mV)
//#define ADC24_V23_SCALE		0.079767E-04 	 //// voltage amplified in the analog circuit: 	0.058154e-4= Vref/2^23 /(2*(1+9.9k/574)) (x1000 to make it in mV)
//#define ADC24_V23_SCALE		0.058154e-4 	 //// voltage amplified in the analog circuit: 	0.058154e-4= Vref/2^23 /(2*(1+9.9k/412)) (x1000 to make it in mV)
//#define ADC24_I14_SCALE		1.458462e-5		 //is amplified in the analog circuit :			1.458462e-5= 1/4 * Vref/2^23 (x100 uA/0.499V): result in uA
#define ADC24_Iph_SCALE		-2.599188e-4 	 //is amplified in the analog circuit 			Scale= -1/2 * Vref/2^23 /(560k)(x1e9): result in nA



//-----------ADC24bit VARIABLES---------//
//Standard Types
extern uint8_t TxBUFF[15], RxBUFF[15];						// 1Word length = 24bits = 3Bytes when M1=0
extern uint16_t ADC24_RESPNS; 								// Read the Status Report form the ADC131A04
extern int32_t ADC_DATA1, ADC_DATA2, ADC_DATA3, ADC_DATA4; 	// ADC data in bits, directly from the Buffer
extern float Iph, V23, V14, I14;							// ADC data in float format
extern float ADC_MAX_COST, ADC_COST;



//----------ADC24bit Structures----------//
// ADS131A04 Commands structure (pp.48 Data-sheet)
typedef struct ADC24_CMD_struct
{
	uint16_t  CNULL, RESET, STANDBY, WAKEUP, LOCK, UNLOCK;
	uint16_t  RREG, RREGS, WREG, WREGS;
} ADC24_CMD_struct;
/* null command
 * software reset command
 * enter standby mode
 * wake up from standby mode
 * lock command
 * unlock command
 * read a single register
 * read multiple registers
 * write single register (data in command)
 * write multiple registers */

// ADS131A04 Register Addresses structure (pp.55 Data-sheet). Read Only ID Registers
typedef struct ID_REG_ADRR_struct
{
	uint8_t  MSB, LSB;
} ID_REG_ADRR_struct;
/* id msb register address
 * id lsb register address */

//Status Registers
typedef struct ST_REG_ADRR_struct
{
	uint8_t  ONE, P, N, S, ER_CNT, M2;
} ST_REG_ADRR_struct;
/*status info
 * positive threshold exceeded
 * negative threshold exceeded
 * SPI status
 * CRC and hamming error counter
 * status of hardware pin M0,M1,M2 */

//Configuration Registers
typedef struct CFG_REG_ADRR_struct
{
	uint8_t  A_SYS, D_SYS, CLK1, CLK2, ADC_EN, GADC1, GADC2, GADC3, GADC4;
} CFG_REG_ADRR_struct;
/* Analog  Configuration Register
 * Digital Configuration Register
 * Clock Configuration Register 1
 * Clock configuration Register 2
 * Analog Channel enable
 * Channel 1 gain selection
 * Channel 2 gain selection
 * Channel 3 gain selection
 * Channel 4 gain selection */

typedef struct STAT1_struct
{
	uint8_t  FOPC, FSPI, FADCIN, FWDT, FRESYNC, FDRDY, FCHECK;
} STAT1_struct;
/*  Status_1 Register Fault Checks
 *	OPC	: a received command is not recognized
 *	SPI	: t one of the status bits in the STAT_S register is set
 *	ADCIN	: STAT_P or STAT_N register is set
 *	WDT		: the watchdog timer times out
 *	RESYNC	: This fault is only possible in synchronous slave mode
 *  DRDY	: data shifted out from the previous result are not complete by the time new ADC data are ready
 *  CHECK	: Uncorrectable hamming error or CRC check word on DIN fails.
 */

typedef struct STAT_S_struct
{
	uint8_t  FSTARTUP, FCS, FFRAME;
} STAT_S_struct;
/*  Status_S SPI Fault Checks
 *	STARTUP	: an error was detected during power-up
 *	CS		: CS is asserted or deasserted when SCLK is high
 *	FRAME	: Not enough SCLKs are sent per frame
 */


//Structures
extern ADC24_CMD_struct 	ADC24_CMD;				// ADS131A04 Commands
extern ST_REG_ADRR_struct 	ADC24_STAT;				// Status Register Address
extern ID_REG_ADRR_struct 	ADC24_ID; 				// ID read only Register Address
extern CFG_REG_ADRR_struct 	ADC24_CFG_ADRR; 		// Configuration Registers
extern STAT1_struct 		ADC24_STAT1; 			// Status_1 Register Read
extern STAT_S_struct 		ADC24_STATS; 			// Status_S Register Read

//End of the header code


//Beginning of the c file
//Structures
ADC24_CMD_struct 	ADC24_CMD 	=   {0x0000, 0x0011, 0x0022, 0x0033, 0x0555, 0x0655,// 	{uint16_t RNULL, RESET, STANDBY, WAKEUP, LOCK, UNLOCK;
								 	 0x2000, 0x2000, 0x4000, 0x6000};				//	 uint16_t  RREG, RREGS, WREG, WREGS;

ST_REG_ADRR_struct 	ADC24_STAT	=	 {0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; 			//	{uint8_t  ONE, P, N, S, ER_CNT, M2}
ID_REG_ADRR_struct 	ADC24_ID	=	 {0x00, 0x01}; 									//	{uint8_t  MSB, LSB}
CFG_REG_ADRR_struct ADC24_CFG_ADRR = {0x0B, 0x0C, 0x0D, 0x0E, 0x0F,					//	{uint8_t  A_SYS, D_SYS, CLK1, CLK2, ADC_ENA;
								 	  0x11, 0x12, 0x13, 0x14};						//	 uint8_t  ADC1, ADC2, ADC3, ADC4;}
STAT1_struct 		ADC24_STAT1={0}; 												// {FOPC, FSPI, FADCIN, FWDT, FRESYNC, FDRDY, FCHECK}
STAT_S_struct 		ADC24_STATS={0}; 													// {FSTARTUP, FCS, FFRAME}


//Standard Types
uint8_t TxBUFF[15]; 			// 1Word length = 24bits = 3Bytes when M1=0
uint8_t RxBUFF[15]; 			// --->>----
uint16_t ADC24_RESPNS=0; 	// Read the Status Report form the ADC131A04
int32_t ADC_DATA1=0, ADC_DATA2=0, ADC_DATA3=0, ADC_DATA4=0;

//-----------ADC24bit FUNCTIONS---------//

void ADC24_Init(void)
{
	/* This function performs the Initialization Set Up of ADS131A04, as described
	 * in pp.79 of the data-sheet. The initialization takes place at system reboot
	 * either due to power reset or only code reset
	 *
	 * Here are the steps:
	 * 1. Set M0 Pin while system is powered -off. (M0=1 in this prototype=>Asynchronous Interrupt mode)
	 * 2. Power up system
	 * 3. Set nRST=1. Here we can first pull-down the nRST pin and then pull it back high to
	 *    ensure software reset, if power reset is not performed (e.g. debug mode),
	 *    resetting all user registers to the default states.  It can take up to 4.5ms (pp.35 Data-shet)!
	 * 4. Receive READY status word (0xFF04)
	 *    In the READY state, the device transmits only one word, allowing a 1-word command to be received.
	 *    After Power-on-Reset, the ADS131A0x powers up in dynamic-frame mode (pp.36 of Data-sheet) and with CRS disabled,
	 *    Only 1 word is transmitted. 1Word =24bits = 3Bytes when M1=0.
	 *    1st goes is always the Command Word in the 16 MSB (TxBUFF[0] and TxBUFF[1]), while is always TxBUFF[2]=0.
	 * 	  Only 1 word is received: The status word: It is the first device word in every DOUT data frame.
	 * 	  The status word is always the 16 MSbits with the remaining LSBs set to zeroes depending on the device word length;
	 * 5. Unlock the ADC by sending the UNLOCK command: 0x0655
	 * 	  At the next SPI transfer make sure that the Status Word = AKG = 0x0655  (same as command address)
	 * 	  Make sure to always transmit 18 bytes after Unlock!
	 * 	  otherwise an SPI Fault will be shown in STAT_1 Reg
	 * 6. Configure Analog Register: [VNCPEN HRM 1 VREF_4V INT_REFEN COMP_TH[2:0] ] (pp.61 of Data-sheet)
	 *	  VNCPEN=0		: Disable negative charge pump
	 *	  HRM=1			: Enable High Resolution Mode
	 *	  Reserved=1
	 *	  VREF_4V=0		: Vref=2.442
	 *	  INT_REFEN=1	: Enable internal reference voltage
	 *	  COMP_TH=000	: Set the comparator thresholds to max values: AVDD,AVSS
	 *	  Use the WREG command to write to the register
	 * 7. Configure Digital Register: [WDT_EN CRC_MODE DNDLY[1:0] HIZDLY[1:0] FIXED CRC_EN] (pp.62 of Data-sheet)
	 *    WDT_EN=0  	: Watchdog disabled
	 *    CRC_MODE=0	: CRC is valid on only the device words being sent and received
	 *    DNDLY= [1 1]	: ≥ 12-ns delay before the device asserts nDONE (not useful)
	 *    HIZDLY=[1 1]	: ≥ 12-ns of delay before the device asserts Hi-Z on DOUT after the LSB of the data frame is shifted out
	 *    FIXED=0		: not Fixed six device words per frame
	 *    CRC_EN=0		: Cyclic redundancy check (CRC) disabled
	 * 8. Configure the CLK1 Register: [CLKSRC Reserved[2:0] CLK_DIV[2:0] Reserved]
	 *    CLKSRC=0 		: XTAL1/CLKIN and XTAL2 pins
	 *    Reserved=000
	 *    CLK_DIV=001	:  fICLK = fCLKIN / 2 = 8 MHz
	 *    Reserved=0
	 *
	 * 9. Configure the CLK2 Register: [ICLK_DIV[2:0] Reserved OSR[3:0]]
	 *    ICLK_DIV=001	: fMOD = fICLK / 2 = 4 MHz
	 *    Reserved=0
	 *    OSR=1001		: fDATA = fMOD / 200 = 20KS/s
	 *
	 *10. Configure the ADC gain for all 4 chanels.
	 *	  No need to take any actions. The gain is by default 1 Reg: [0 0 0]
	 *
	 *11. Enable ADCs.  Write 0x0F to the ADC_ENA register to enable ADCs [Reserved [7:4] ENA[3:0] ]
	 *    Reserved=0
	 *    ENA[3:0]=1111 : All ADC channels powered up
	 *
	 *12. Send Wake up Command.
	 *
	 *13. Lock Registers.
	 */

	//----------------------------------------------------------------------------
	// Step 0. Dissable the External interrupt so We don't reed non-configured SPI values
	HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
	HAL_Delay(20); // wait 20ms after POR

	//----------------------------------------------------------------------------
	// Step 3. Perform a system reset
	// nRST=0 for Tmin=800ns then nRST=1 for Tmin=4.5ms (pp.12,35 of Data-sheet)
	HAL_GPIO_WritePin(ADC24_nRST_GPIO_Port, ADC24_nRST_Pin, GPIO_PIN_RESET);
	HAL_Delay(10); // 10 ms after a reset command
	HAL_GPIO_WritePin(ADC24_nRST_GPIO_Port, ADC24_nRST_Pin, GPIO_PIN_SET);
	HAL_Delay(20); // 20 ms after a reset command


	//----------------------------------------------------------------------------
	// Step 4. Read REDY Status Word
	TxBUFF[0] = (ADC24_CMD.CNULL >> 8); 	// Take the MSB by shifting the CMD by 8 bits right
	TxBUFF[1] = (ADC24_CMD.CNULL & 0x00FF);	// Take the LSB. Although it is an assignment from 16bit to 8 bit (the LSB will be assigned)
											// we multiplying all other bits with 0 for safety.
	TxBUFF[2] = 0;							// Fill with 0
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 3, 10);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);

	//repeat to get the response to the previous null command
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 3, 10);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);
	// Read the ADC24 response after 2 successive Null commands;
	ADC24_RESPNS = ((RxBUFF [0] <<8 ) | RxBUFF [1]); // Recombine Bytes
	if (ADC24_RESPNS!=ADC24_SPI_READY)	FaultCode=ADC24_nREADY;


	//----------------------------------------------------------------------------
	// Step 5. Unlock Device
	TxBUFF[0] = ADC24_CMD.UNLOCK >> 8;
	TxBUFF[1] = ADC24_CMD.UNLOCK & 0x00FF;
	TxBUFF[2] = 0;
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 3, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);


	//----------------------------------------------------------------------------
	// Step 6. Configure the  ANALOG register
	TxBUFF[0] = (ADC24_CMD.WREG >>8 | ADC24_CFG_ADRR.A_SYS); // Combine the 8MSbits of CMD.WREG with the 8bit ADRR.A_SYS
	TxBUFF[1] =  ADC24_A_SYS_CFG;							 // Continue with the value to be written
	TxBUFF[2] = 0;											 // Fill the rest with zeros
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 3, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);
	// Check the previous Response (AKG = CMD.UNLOCK?)
	ADC24_RESPNS = ((RxBUFF [0] <<8 ) | RxBUFF [1]); // Recombine Bytes
	if (ADC24_RESPNS!=ADC24_CMD.UNLOCK)	FaultCode=ADC24_UnlockERROR;


	//----------------------------------------------------------------------------
	// Step 7. Configure the  DIGITAL register
	TxBUFF[0] = (ADC24_CMD.WREG >>8 | ADC24_CFG_ADRR.D_SYS);
	TxBUFF[1] =  ADC24_D_SYS_CFG;
	TxBUFF[2] = 0;
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 3, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);

	// Check the previous Response (AKG = 0b001aaaaa dddddddd ?)
	ADC24_RESPNS = ((RxBUFF [0] <<8 ) | RxBUFF [1]); // Recombine Bytes
	if (ADC24_RESPNS!=(((0x20|ADC24_CFG_ADRR.A_SYS)<<8)|ADC24_A_SYS_CFG))	FaultCode=ADC24_WriteERROR;


	//----------------------------------------------------------------------------
	// Step 8. Configure the  CLK1 register
	TxBUFF[0] = (ADC24_CMD.WREG >>8 | ADC24_CFG_ADRR.CLK1);
	TxBUFF[1] =  ADC24_CLK1_CFG;
	TxBUFF[2] = 0;
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 3, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);

	// Check the previous Response (AKG = 0b001aaaaa dddddddd ?)
	ADC24_RESPNS = ((RxBUFF [0] <<8 ) | RxBUFF [1]); // Recombine Bytes
	if (ADC24_RESPNS!=(((0x20|ADC24_CFG_ADRR.D_SYS)<<8)|ADC24_D_SYS_CFG))	FaultCode=ADC24_WriteERROR;


	//----------------------------------------------------------------------------
	// Step 9. Configure the  CLK2 register
	TxBUFF[0] = (ADC24_CMD.WREG >>8 | ADC24_CFG_ADRR.CLK2);
	TxBUFF[1] =  ADC24_CLK2_CFG;
	TxBUFF[2] = 0;
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 3, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);

	// Check the previous Response (AKG = 0b001aaaaa dddddddd ?)
	ADC24_RESPNS = ((RxBUFF [0] <<8 ) | RxBUFF [1]); // Recombine Bytes
	if (ADC24_RESPNS!=(((0x20|ADC24_CFG_ADRR.CLK1)<<8)|ADC24_CLK1_CFG))	FaultCode=ADC24_WriteERROR;


	//----------------------------------------------------------------------------
	// Step 11. Enable ADCs
	TxBUFF[0] = (ADC24_CMD.WREG >>8 | ADC24_CFG_ADRR.ADC_EN);
	TxBUFF[1] =  ADC24_ENA;
	TxBUFF[2] = 0;
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 3, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);

	// Check the previous Response (AKG = 0b001aaaaa dddddddd ?)
	ADC24_RESPNS = ((RxBUFF [0] <<8 ) | RxBUFF [1]); // Recombine Bytes
	if (ADC24_RESPNS!=(((0x20|ADC24_CFG_ADRR.CLK2)<<8)|ADC24_CLK2_CFG))	FaultCode=ADC24_WriteERROR;


	//----------------------------------------------------------------------------
	// Step 12. Wake up Device
	TxBUFF[0] = ADC24_CMD.WAKEUP >> 8;
	TxBUFF[1] = ADC24_CMD.WAKEUP & 0x00FF;
	TxBUFF[2] = 0;
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);

	// Check the previous Response (AKG = 0b001aaaaa dddddddd ?)
	ADC24_RESPNS = ((RxBUFF [0] <<8 ) | RxBUFF [1]); // Recombine Bytes
	if (ADC24_RESPNS!=(((0x20|ADC24_CFG_ADRR.ADC_EN)<<8)|ADC24_ENA))	FaultCode=ADC24_WriteERROR;


	//----------------------------------------------------------------------------
	// Step 13. Lock Registers
	TxBUFF[0] = ADC24_CMD.LOCK >> 8;
	TxBUFF[1] = ADC24_CMD.LOCK & 0x00FF;
	TxBUFF[2] = 0;
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);


	//----------------------------------------------------------------------------
	// Step 14. Send two NULL commands and Identify any Faults
	// Read the STAT_1Reg
	TxBUFF[0] = (ADC24_CMD.CNULL >> 8);
	TxBUFF[1] = (ADC24_CMD.CNULL & 0x00FF);
	TxBUFF[2] = 0;
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);
	//repeat to get the response to the previous null command
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);

	//Identify the fault
	ADC24_RESPNS=RxBUFF[1];
	ADC24_STAT1.FOPC	=(ADC24_RESPNS>>6 & 0x01);
	ADC24_STAT1.FSPI	=(ADC24_RESPNS>>5 & 0x01);
	ADC24_STAT1.FADCIN	=(ADC24_RESPNS>>4 & 0x01);
	ADC24_STAT1.FWDT	=(ADC24_RESPNS>>3 & 0x01);
	ADC24_STAT1.FRESYNC	=(ADC24_RESPNS>>2 & 0x01);
	ADC24_STAT1.FDRDY	=(ADC24_RESPNS>>1 & 0x01);
	ADC24_STAT1.FCHECK	=(ADC24_RESPNS    & 0x01);

	if (ADC24_STAT1.FSPI==1)
	{
		//Read Stat_S register (2 times to read the right value in the response Reg
		TxBUFF[0] = (ADC24_CMD.RREG >>8 | ADC24_STAT.S);
		TxBUFF[1] = 0;
		TxBUFF[2] = 0;
		HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
		HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 5);
		HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
		HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 5);
		HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);
		// Read one more time to clear any bits
		HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
		HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 5);
		HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);
	}

	// Read again the STAT_1Reg
	TxBUFF[0] = (ADC24_CMD.CNULL >> 8);
	TxBUFF[1] = (ADC24_CMD.CNULL & 0x00FF);
	TxBUFF[2] = 0;
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);
	//repeat to get the response to the previous null command
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 5);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);

	//Identify the fault
	ADC24_RESPNS=RxBUFF[1];
	ADC24_STAT1.FOPC	=(ADC24_RESPNS>>6 & 0x01);
	ADC24_STAT1.FSPI	=(ADC24_RESPNS>>5 & 0x01);
	ADC24_STAT1.FADCIN	=(ADC24_RESPNS>>4 & 0x01);
	ADC24_STAT1.FWDT	=(ADC24_RESPNS>>3 & 0x01);
	ADC24_STAT1.FRESYNC	=(ADC24_RESPNS>>2 & 0x01);
	ADC24_STAT1.FDRDY	=(ADC24_RESPNS>>1 & 0x01);
	ADC24_STAT1.FCHECK	=(ADC24_RESPNS    & 0x01);
}

void ADC24_READ(void)
{
/* Read the values of the ADS131A04 through SPI, when they are ready (external interrupt on EXINT12)
 * Also read the response of the SPI to a NULL command = STAT_1 register and check if there is an error
 * all 18 bytes need to be read, otherwise we get an SPI error.
 */
	TxBUFF[0] = (ADC24_CMD.CNULL >> 8);
	TxBUFF[1] = (ADC24_CMD.CNULL & 0x00FF);
	TxBUFF[2] = 0;

	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxBUFF, RxBUFF, 15, 100);
	HAL_GPIO_WritePin(ADC24_nCS_GPIO_Port, ADC24_nCS_Pin, GPIO_PIN_SET);

	// Read Response
	// For NULL command this returns [Read command and STAT1 address = 001aaaaa=00100010
	// and STAT1 reg values in 2nd Byte
	ADC24_RESPNS=RxBUFF[1];
	if (ADC24_RESPNS!=0) // avoid first entry because we are reading old values
	{
		//Identify the fault
		ADC24_STAT1.FOPC	=(ADC24_RESPNS>>6 & 0x01);
		ADC24_STAT1.FSPI	=(ADC24_RESPNS>>5 & 0x01);
		ADC24_STAT1.FADCIN	=(ADC24_RESPNS>>4 & 0x01);
		ADC24_STAT1.FWDT	=(ADC24_RESPNS>>3 & 0x01);
		ADC24_STAT1.FRESYNC	=(ADC24_RESPNS>>2 & 0x01);
		ADC24_STAT1.FDRDY	=(ADC24_RESPNS>>1 & 0x01);
		ADC24_STAT1.FCHECK	=(ADC24_RESPNS    & 0x01);
	}

	ADC_DATA1= ((RxBUFF[3]  << 16) | (RxBUFF[4]  << 8) | RxBUFF[5]);
	ADC_DATA2= ((RxBUFF[6]  << 16) | (RxBUFF[7]  << 8) | RxBUFF[8]);
	ADC_DATA3= ((RxBUFF[9]  << 16) | (RxBUFF[10] << 8) | RxBUFF[11]);
	ADC_DATA4= ((RxBUFF[12] << 16) | (RxBUFF[13] << 8) | RxBUFF[14]);
}

//End of the c file

  • Hi Giovanni,

    If I understand your registers and questions correctly, the ADS131A04 is currently configured for an output data rate (ODR) of 20kSPS when fed an external clock of 8MHz, a new sample every 50us and you would like to configure the device to output a sample every 35uS instead, or 28.5kSPS. In order to do this, you will need to reduce the OSR in the OSR[3:0] bits in the CLK2 register as discussed in section 9.3.1.4 Data Rate. Changing #define ADC24_CLK2_CFG 0b00101001 to 0b00101011 should change the ODR from 20kSPS to 31.250kSPS as per table 30. You may need to increase the frequency of your SCLK pulses from the STM to accommodate for the increased ODR and keep in mind that the accuracy of the measurement will be reduced as shown in tables 1 through 4.

    Modifying the clock frequency would allow you to adjust this as well, but it doesn't sound like you're interested in a board change. Please let me know if my understanding is correct and if you have any questions. 

  • Hi Alexander, thanks for your reply. I realized that probably I have not explained correctly what I want to do.

    I would like to maintain the sampling frequency to 20 kSPS; however, I would like to know if there is a way to make the communication between the ADC and the MCU faster. I have measured the time required to execute the function ADC24_read() and it is about 45 us with peaks larger than 50us. My aim is to reduce this time since the MCU should update a DAC at the same sampling frequency, knowing that the DAC updated requires about 13.5us.

    Since yesterday, I have also been playing with the SPI clock signal that is sent to the ADC. With a baudrate of 13.5 MBit/s the required time values for the communication are those that I have reported, while with a baudrate of 54 Mbit/s, I could drop the average time to around 32 us with a peak time of 40 us. Though this is great, reading the ADC datasheet, I have seen that the maximum value of f_SCLK is 25 MHz, so it is not clear how the ADC does not crash with a serial clock of 54 Mhz. 

    Another solution might be to suppress one of the 4 channel of the ADC since I do not need it. By doing so, I hope that the communication time can be reduced; however, if I understood correctly, the channels can be or all on or all off.

    Another way, which I prefer to avoid, is that I physically cut the connection of MO to IOVDD (see figure), so I can try other SPI communications modes.

    Best regards,

    Giovanni

  • Hi Giovanni,

    Thank you for the clarification. Since /CS is being controlled with a GPIO it is difficult to fit all communication in this short time frame. 

    Using an out of spec SCLK of 54MHz won't necessarily crash the ADC, but it is out of the range of specified operation. We simply cannot guarantee how the device will behave under this condition. 

  • Hi Alexander,

    Thanks for your reply. I have tried to leave the CS active for all the time in which I need to acquire data from the ADC (the SPI bus is not shared with other peripheral during this time) and nothing changed. 

    Supposing I can redesign the circuit, what would you suggest to reach my goal?

  • Hello Giovanni,

    If you wish to speed up the communication, the simplest techniques would be:

    1. increasing the SCLK frequency (within the specified range)
    2. reduce the word size (M0 setting) to 16 bits
    3. reduce the number of words per frame. 

    The device defaults to Dynamic Frame mode. Since I see that CRC is disabled in your code, this would remove the CRC word from the frame.

    Further improvements can be achieved by using a synchronous interface. This would eliminate the timing delays associated with enabling and disabling /CS. However, these delays typically contribute 10s of ns only.

    Regards,

    Ryan

  • Hi Ryan, 

    at the end I changed a couple of things in the FW:

    • I replaced the interrupt routine with a continuous reading of the ready pin connected to the MCU,
    • I made the HAL function for SPI transmit and receive much lighter and faster.

    Despite the brute force approach, it worked fine.

    Regards,

    Giovanni