ADS131A04硬件设计与软件调试

一、IC基本信息

ADS131A0x 双通道或四通道 24 位 128kSPS 同步采样 Δ-Σ ADC

•双通道或四通道同步采样差分输入

• 数据速率:高达 128kSPS

• 高性能: – 单通道精度:在 10,000:1 动态范围内优于 0.1% – 有效分辨率:20.6位 (8kSPS) – 总谐波失真 (THD):50Hz 和 60Hz 频率下为 -100dB

• 集成的负电荷泵 允许绝对输入电压低于接地值

• 灵活的模拟电源选项: – 采用负电荷泵:3.0V 至 3.45V – 单极电源:3.3V 至 5.5V – 双极电源:±2.5V

• 数字电源:1.65V 至 3.6V

晶振pinlv16.384MHz,fMOD = fICLK / 8 =2.048Mhz,fDATA = fMOD / 256 =8K 采样率

二、硬件电路

1、输入接口电路

R1、R2和C14形成了一个差分低通滤波器,通道1的-3dB截止频率为169.3 kHz。此外,R1和C15与R2和C16形成共模低通滤波器,截止频率-3dB为15.9 MHz。串联阻抗保持相对较低,以保持足够的总谐波失真(THD)性能。在所有输入上都存在类似的微分和通用模型低通滤波器。

M0M1M2引脚功能

手册推荐电源供电布局

官方评估开发板

SBAU353 User guide | 德州仪器 TI.com.cn

平板采用四层板设计,顶层、地层、电源层、底层,分别为以下图示

官方驱动示例代码如下,可能不能直接使用,但是可以了解大概得配置流程。

///
//
/**
 *
 * \copyright Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "ads131a04.h"



//****************************************************************************
//
// Macros
//
//****************************************************************************

// Determine number of bytes per command based on WORD_LENGTH
#define WORD_LENGTH             (WORD_LENGTH_BITS >> 3)

// Fetch the upper byte of a 16-bit word and return it as an 8-bit value
#define UPPER_BYTE(x)           ((uint8_t) ((0xFF00 & x) >> 8))

// Fetch the lower byte of a 16-bit word and return it as an 8-bit value
#define LOWER_BYTE(x)           ((uint8_t)  (0x00FF & x))

// Combine two 8-bit values into a 16-bit word
#define COMBINE_BYTES(x, y)     (((uint16_t) x << 8) | ((uint16_t) y & 0x00FF))																		   



//****************************************************************************
//
// Internal variables
//
//****************************************************************************

// Array used to recall last known values of the device's register map settings */
static uint8_t registerMap[NUM_REGISTERS];

// Flag to keep track of device's register lock status
// NOTE: The device defaults to locked
static bool registersLocked = true;

// Arrays to store RX and TX data for SPI communication
static uint8_t dataTx[6 * WORD_LENGTH] = { 0 };
static uint8_t dataRx[6 * WORD_LENGTH] = { 0 };

// Variable to keep track of the number of words in an SPI frame
#ifdef SET_FIXED
    static uint8_t cmdByteLength = 6 * WORD_LENGTH;
#else
    static uint8_t cmdByteLength = WORD_LENGTH;
#endif



//****************************************************************************
//
// Internal function prototypes
//
//****************************************************************************

#ifdef SET_CRC_EN
    static void updateCrcIn(void);
#endif



//*****************************************************************************
//
//! Getter function to access registerMap array from outside of this module.
//!
//! \fn uint16_t getRegisterValue(uint8_t address)
//!
//! NOTE: The internal registerMap arrays stores the last known register value,
//! since the last read or write operation to that register. This function
//! does not communicate with the device to retrieve the current register value.
//! For the most up-to-date register data or reading the value of a hardware
//! controlled register, it is recommend to use readSingleRegister() to read the
//! device register.
//!
//! \param address is the 8-bit address of the register value to recall.
//!
//! \return unsigned 8-bit register value.
//
//*****************************************************************************
uint8_t getRegisterValue(uint8_t address)
{
    assert(address < NUM_REGISTERS);
    return registerMap[address];
}



//*****************************************************************************
//
//! Example start up sequence for the ADS131A04.
//!
//! \fn void adcStartup(void)
//!
//! Before calling this function, the device must be powered,
//! the SPI/GPIO pins of the MCU must have already been configured,
//! and (if applicable) the external clock source should be provided to CLKIN.
//!
//! NOTE: You may want to modify this function to configure the ADC's initial
//! register settings to your application's requirements.
//!
//! \return None.
//
//*****************************************************************************
void adcStartup(void)
{
	/* (OPTIONAL) Provide additional delay time for power supply settling */
	delay_ms(50);

	/* (REQUIRED) Set nRESET pin high for ADC operation */
	setRESET(HIGH);
	
	/* (INTERNAL) Initialize internal 'registerMap' array with device default settings */
	restoreRegisterDefaults();

	/* (OPTION #1) Wait ~5ms for POR to complete */
	delay_ms(5);

	/* (OPTION #2) Wait for nDRDY falling edge for indication that POR has completed */
    //	bool interruptedOccurred = waitForDRDYinterrupt(20);
    //	if (!interruptedOccurred)
    //	{
    //	    // Error: Device appears to be unresponsive. Check the power supplies, clock,
    //	    // and GPIO pins to make sure the device is active.
    //	    assert(0);
    //	}

    /* (REQUIRED) Always send a NULL command first to establish SPI communication */
	sendCommand(OPCODE_NULL);

	/* (OPTIONAL) Verify READY response */
	uint16_t response = sendCommand(OPCODE_NULL);
	if (0xFF04 != response)
	{
	    // Error: Unexpected response
	    assert(0);
	}
	
	/* (REQUIRED) Send UNLOCK to exit 'READY' state  */
	unlockRegisters();


	//
	// Configure initial register settings here...
	//

	// Default value for D_SYS_CFG_ADDRESS register
	uint8_t regVal = D_SYS_CFG_DEFAULT;

#ifdef SET_FIXED
	regVal |= D_SYS_CFG_FIXED_MASK;     // Set FIXED bit
#endif

#ifdef SET_CRC_EN
	regVal |= D_SYS_CFG_CRC_EN_MASK;    // Set CRC_EN bit
#endif

#ifdef SET_CRC_MODE
    regVal |= D_SYS_CFG_CRC_MODE_MASK;  // Set CRC_MODE bit
#endif

	// Write to D_SYS_CFG_ADDRESS
    writeSingleRegister(D_SYS_CFG_ADDRESS, regVal);

    // Configure data rate
    writeSingleRegister(CLK1_ADDRESS, CLK1_CLK_DIV_2);
    writeSingleRegister(CLK2_ADDRESS, CLK2_ICLK_DIV_2 | CLK2_OSR_2048);

	// Enable all ADC channels
    writeSingleRegister(ADC_ENA_ADDRESS, ADC_ENA_ENA_ALL_CH_PWUP);

    /* (REQUIRED) Always send a NULL command first to establish SPI communication */
    sendCommand(OPCODE_WAKEUP);

    // Ignore the first 3-4 conversion results to allow for the
    // output buffers to fill-up and the SINC3 filter to settle
    uint8_t ignore_counter = 4;
    adc_data_struct dummy_data;
    while (ignore_counter > 0)
    {
        waitForDRDYinterrupt(1000);
        readData(&dummy_data);
        ignore_counter--;
    }
}



//*****************************************************************************
//
//! Reads the contents of a single register at the specified address.
//!
//! \fn uint8_t readSingleRegister(uint8_t address)
//!
//! \param address is the 8-bit address of the register to read.
//!
//! \return Returns the 8-bit register read result.
//
//*****************************************************************************
uint8_t readSingleRegister(uint8_t address)
{
	/* Assert(s) */
	assert(address < NUM_REGISTERS);        // Register address must be in range

	// Build TX  array
    dataTx[0] = UPPER_BYTE(OPCODE_RREG) | address;
    dataTx[1] = 0x00;

#ifdef SET_CRC_EN
    // Calculates the CRC IN word and adds it to the dataTx[] array
    updateCrcIn();
#endif

	// [FRAME 1] Send RREG command
	spiSendReceiveArrays(dataTx, dataRx, cmdByteLength);

	// [FRAME 2] Send NULL command to retrieve the register data
	uint16_t response = sendCommand(OPCODE_NULL);

	// Verify device response
	if (UPPER_BYTE(response) == OPCODE_RREG | ((uint16_t) address))
	{
	    // Update internal register array data
	    registerMap[address] = LOWER_BYTE(response);
	}

	return registerMap[address];
}



//*****************************************************************************
//
//! Writes data to a single register.
//!
//! \fn void writeSingleRegister(uint8_t address, uint8_t data)
//!
//! This command will be ignored if device registers are locked.
//!
//! NOTE: This functions also performs a NULL command frame after the register
//! write command to verify the new register value.
//!
//! \param address is the address of the register to write to.
//! \param data is the value to write.
//!
//! \return None.
//
//*****************************************************************************
void writeSingleRegister(uint8_t address, uint8_t data)
{
    /* Assert(s) */
    assert(address < NUM_REGISTERS);        // Register address must be in range

    // (OPTIONAL) Enforce certain register settings when writing to the D_SYS_CFG register
    // to avoid having to write code that supports multiple device modes. For example...
    //      if (D_SYS_CFG_ADDRESS == address)
    //      {
    //          data = data | D_SYS_CFG_FIXED_MASK | D_SYS_CFG_CRC_EN_MASK;
    //      }
	
	// Save current register value
    uint8_t oldValue = registerMap[address];

    // Build TX byte array
    dataTx[0] = UPPER_BYTE(OPCODE_WREG) | address;
    dataTx[1] = data;

#ifdef SET_CRC_EN
    // Calculates the CRC IN word and adds it to the dataTx[] array
    updateCrcIn();
#endif

    // [FRAME 1] Send WREG command
    spiSendReceiveArrays(dataTx, dataRx, cmdByteLength);
	
	// Update register map array with new value
    // NOTE: This ensures that the NULL command in the next frame is sent correctly.
    registerMap[address] = data;

    // [FRAME 2] Send NULL command to verify WREG response
    uint16_t response = sendCommand(OPCODE_NULL);

    // Verify device response
    if (UPPER_BYTE(response) == (UPPER_BYTE(OPCODE_RREG) | address))
    {
        // Update internal register array data
        registerMap[address] = LOWER_BYTE(response);
    }
    else
    {
        // Restore previous register value
        registerMap[address] = oldValue;
    }
}



//*****************************************************************************
//
//! Read ADC data
//!
//! \fn bool readData(adc_data_struct *dataStruct)
//!
//! \param dataStruct pointer to data structure where results from reading data will be placed
//!
//! NOTE: This is currently the only function in this example that verifies if the
//! CRC word on DOUT is correct.
//!
//! \return bool indicating if a CRC mismatch occurred (false = No error)
//
//*****************************************************************************
bool readData(adc_data_struct *dataStruct)
{
    // Build TX array
    dataTx[0] = 0x00;
    dataTx[1] = 0x00;

#ifdef SET_CRC_EN

    // NOTE: The following CRC words are hard-coded based on word length, fixed mode, and CRC mode...
    #if defined SET_FIXED && !defined SET_CRC_MODE // Only the command word is included in CRC calculation

        #ifdef WORD_LENGTH_24BIT
            dataTx[5*WORD_LENGTH] = 0xCC;
            dataTx[5*WORD_LENGTH + 1] = 0x9C;

        #elif WORD_LENGTH_16BIT
            dataTx[5*WORD_LENGTH] = 0x1D;
            dataTx[5*WORD_LENGTH + 1] = 0x0F;

        #elif WORD_LENGTH_32BIT
            dataTx[5*WORD_LENGTH] = 0x84;
            dataTx[5*WORD_LENGTH + 1] = 0xC0;

        #endif

    #else // FIXED = 0 OR (FIXED = 1 and CRC_MODE = 1) -> All device words are included in CRC calculation

        #ifdef WORD_LENGTH_24BIT
            dataTx[5*WORD_LENGTH] = 0x4E;
            dataTx[5*WORD_LENGTH + 1] = 0xC3;

        #elif WORD_LENGTH_16BIT
            dataTx[5*WORD_LENGTH] = 0xE1;
            dataTx[5*WORD_LENGTH + 1] = 0x39;

        #elif WORD_LENGTH_32BIT
            dataTx[5*WORD_LENGTH] = 0xF6;
            dataTx[5*WORD_LENGTH + 1] = 0xB8;

        #endif

    #endif

#endif

    /* Set the nCS pin LOW */
    setCS(LOW);

    // Send NULL word, receive response word
    int i = 0;
    while (i < 6*WORD_LENGTH)
    {
        dataRx[i] = spiSendReceiveByte(dataTx[i]);
        ++i;
    }

    dataStruct->response = COMBINE_BYTES(dataRx[0], dataRx[1]);
    dataStruct->channel1 = signExtend(&dataRx[1*WORD_LENGTH]);
    dataStruct->channel2 = signExtend(&dataRx[2*WORD_LENGTH]);
    dataStruct->channel3 = signExtend(&dataRx[3*WORD_LENGTH]);
    dataStruct->channel4 = signExtend(&dataRx[4*WORD_LENGTH]);
    dataStruct->crc = COMBINE_BYTES(dataRx[5*WORD_LENGTH], dataRx[5*WORD_LENGTH + 1]);

#ifdef CRC_EN
    uint16_t crcWordOut = calculateCRC(&dataRx[0], 6*WORD_LENGTH, 0xFFFF);
#else
    // (OPTIONAL) Ignore CRC error checking (CRC = 0x00 -> indicates a valid SPI frame)
    uint16_t crcWordOut = 0x00;
#endif

    /* Set the nCS pin HIGH */
    setCS(HIGH);

    // Returns true when a CRC error occurs (any non-zero value for crcWordOut)
    return ((bool) crcWordOut);
}



//*****************************************************************************
//
//! Sends the specified SPI command to the ADC (NULL, RESET, STANDBY, or WAKEUP).
//!
//! \fn uint16_t sendCommand(uint16_t opcode)
//!
//! \param opcode 16-bit SPI command.
//!
//! NOTE: Other ADC commands have their own dedicated functions to support
//! additional functionality. This function will raise an assert if used
//! with one of these commands (RREG, WREG, WREGS, LOCK,or  UNLOCK).
//!
//! \return uint16_t response byte (typically the STATUS byte).
//
//*****************************************************************************
uint16_t sendCommand(uint16_t opcode)
{
    /* Assert if this function is used to send any of the following opcodes */
    assert(OPCODE_RREG != opcode);      /* Use "readSingleRegister()"   */
    assert(OPCODE_WREG != opcode);      /* Use "writeSingleRegister()"  */
    assert(OPCODE_LOCK != opcode);      /* Use "lockRegisters()"        */
    assert(OPCODE_UNLOCK != opcode);    /* Use "unlockRegisters()"      */
    //assert(OPCODE_WREGS != opcode);

    // Build TX byte array
    dataTx[0] = UPPER_BYTE(opcode);
    dataTx[1] = LOWER_BYTE(opcode);

#ifdef SET_CRC_EN
    // Calculates the CRC IN word and adds it to the dataTx[] array
    updateCrcIn();
#endif

    // Set the nCS pin LOW
    setCS(LOW);

    // Send the opcode (and crc word, if enabled)
    int i;
    for (i = 0; i < cmdByteLength; i++)
    {
       dataRx[i] = spiSendReceiveByte(dataTx[i]);
    }

    // Set the nCS pin HIGH
    setCS(HIGH);

    // If OPCODE_RESET, then recall default register settings
	if (OPCODE_RESET == opcode) { restoreRegisterDefaults(); }

	// Combine response bytes and return as a 16-bit word
    uint16_t response = COMBINE_BYTES(dataRx[0], dataRx[1]);
    return response;
}



//*****************************************************************************
//
//! Sends the LOCK command and then verifies that registers are locked.
//!
//! \fn bool lockRegisters(void)
//!
//! \return boolean to indicate if registers are locked (0 = unlocked; 1 = locked)
//
//*****************************************************************************
bool lockRegisters(void)
{
    // Build TX array
    dataTx[0] = UPPER_BYTE(OPCODE_LOCK);
    dataTx[1] = LOWER_BYTE(OPCODE_LOCK);

#ifdef SET_CRC_EN
    // Calculates the CRC IN word and adds it to the dataTx[] array
    updateCrcIn();
#endif

    // [FRAME 1] Send WREG command
    spiSendReceiveArrays(dataTx, dataRx, cmdByteLength);

    // [FRAME 2] Send NULL command to verify response
    uint16_t response = sendCommand(OPCODE_NULL);

    // Verify device response and update internal flag
    if (OPCODE_LOCK == response) { registersLocked = true; }

    return registersLocked;
}



//*****************************************************************************
//
//! Sends the UNLOCK command and then verifies that registers are unlocked
//!
//! \fn bool unlockRegisters(void)
//!
//! \return boolean to indicate if registers are locked (0 = unlocked; 1 = locked)
//
//*****************************************************************************
bool unlockRegisters(void)
{
    // Build TX array
    dataTx[0] = UPPER_BYTE(OPCODE_UNLOCK);
    dataTx[1] = LOWER_BYTE(OPCODE_UNLOCK);

#ifdef SET_CRC_EN
    // Calculates the CRC IN word and adds it to the dataTx[] array
    updateCrcIn();
#endif

    // [FRAME 1] Send WREG command
    spiSendReceiveArrays(dataTx, dataRx, cmdByteLength);

    // [FRAME 2] Send NULL command to verify response
    uint16_t response = sendCommand(OPCODE_NULL);

    // Verify device response and update internal flag
    if (OPCODE_UNLOCK == response) { registersLocked = false; }

    // Return lock status
    return registersLocked;
}



//*****************************************************************************
//
//! Calculates the 16-bit CRC for the selected CRC polynomial.
//!
//! \fn uint16_t calculateCRC(const uint8_t dataBytes[], uint8_t numberBytes, uint16_t initialValue)
//!
//! \param dataBytes[] pointer to first element in the data byte array
//! \param numberBytes length of data byte array to include in the CRC calculation
//! \param initialValue the seed value (or partial crc calculation), use 0xFFFF when beginning a new CRC computation
//!
//! NOTE: This calculation is shown as an example and has not been optimized for speed.
//!
//! \return uint16_t calculated CRC word. When performing a partial CRC computation, provide this
//! value as the input to initialValue to resume computing the CRC for additional input bytes.
//
//*****************************************************************************
uint16_t calculateCRC(const uint8_t dataBytes[], uint8_t numberBytes, uint16_t initialValue)
{
	/* Assert(s) */
	assert(dataBytes != 0x00);		// "dataBytes" must not be a NULL pointer 
	assert(numberBytes != 0x00);	// "numberBytes" must be greater than zero

	int bitIndex, byteIndex;
	bool dataMSb;					// Most significant bit of data byte
	bool crcMSb;					// Most significant bit of crc byte
	
	// Initial value of crc register
    uint16_t crc = initialValue;

    // CRC16-CCITT polynomial
    // NOTE: The polynomial's MSB is generally assumed to be high (and is handled by
    // the "dataMSb ^ crcMSb" operation below) and so it is excluded from this value.
    const uint16_t poly = 0x1021;

    //
    // CRC algorithm...
    //

    // Loop through all bytes in the dataBytes[] array
	for (byteIndex = 0; byteIndex < numberBytes; byteIndex++)
	{
	    // Point to MSb in byte
	    bitIndex = 0x80u;

	    // Loop through all bits in the current byte
	    while (bitIndex > 0)
	    {
	        // Check MSB's of data and crc
	        dataMSb = (bool) (dataBytes[byteIndex] & bitIndex);
	        crcMSb  = (bool) (crc & 0x8000u);

			// Left-shift CRC register
	        crc <<= 1;

	        // Check if XOR operation of MSBs results in additional XOR operations
	        if (dataMSb ^ crcMSb)
	        {
	            // XOR crc with polynomial
				crc ^= poly;
	        }

	        // Shift MSb pointer to the next data bit
	        bitIndex >>= 1;
	    }
	}

	return crc;
}



#ifdef SET_CRC_EN
//*****************************************************************************
//
//! Calculates the 16-bit CRC word for dataTx[] array
//!
//! \fn static void updateCrcIn(void)
//!
//! \return none - the resulting CRC value is added to the dataTx[] array
//
//*****************************************************************************
static void updateCrcIn(void)
{
    // Calculate CRC word
    // NOTE: To save time, use a lookup table instead of calculating the CRC value each time this function is called.
    uint16_t crcWordIn = calculateCRC(dataTx, ((FIXED & !CRC_MODE) ? 1 : 5) * WORD_LENGTH, 0xFFFF);
    dataTx[5*WORD_LENGTH] = UPPER_BYTE(crcWordIn);
    dataTx[5*WORD_LENGTH + 1] = LOWER_BYTE(crcWordIn);
}
#endif



//*****************************************************************************
//
//! Updates the registerMap[] array to its default values.
//!
//! \fn void restoreRegisterDefaults(void)
//!
//! NOTES:
//! - If the MCU keeps a copy of the ADC's register settings in memory,
//! then it is important to ensure that these values remain in sync with the
//! actual hardware settings. In order to help facilitate this, this function
//! should be called after powering up or resetting the device (either by
//! hardware pin control or SPI software command), as is shown in this example.
//!
//! \return None.
//
//*****************************************************************************
void restoreRegisterDefaults(void)
{
    registerMap[ID_MSB_ADDRESS]         =   ID_MSB_NU_CH_4;               /* NOTE: This a read-only register */
    registerMap[ID_LSB_ADDRESS]         =   0x00;                         /* NOTE: REV_ID value is unknown until read */
    registerMap[STAT_1_ADDRESS]         =   STAT_1_DEFAULT;
    registerMap[STAT_P_ADDRESS]         =   STAT_P_DEFAULT;
    registerMap[STAT_N_ADDRESS]         =   STAT_N_DEFAULT;
    registerMap[STAT_S_ADDRESS]         =   STAT_S_DEFAULT;
    registerMap[ERROR_CNT_ADDRESS]      =   ERROR_CNT_DEFAULT;
    registerMap[STAT_M2_ADDRESS]        =   STAT_M2_DEFAULT & STAT_M2_DEFAULT_MASK;
    registerMap[A_SYS_CFG_ADDRESS]      =   A_SYS_CFG_DEFAULT;
    registerMap[D_SYS_CFG_ADDRESS]      =   D_SYS_CFG_DEFAULT;
    registerMap[CLK1_ADDRESS]           =   CLK1_DEFAULT;
    registerMap[CLK2_ADDRESS]           =   CLK2_DEFAULT;
    registerMap[ADC_ENA_ADDRESS]        =   ADC_ENA_DEFAULT;
    registerMap[ADC1_ADDRESS]           =   ADC1_DEFAULT;
    registerMap[ADC2_ADDRESS]           =   ADC2_DEFAULT;
    registerMap[ADC3_ADDRESS]           =   ADC3_DEFAULT;
    registerMap[ADC4_ADDRESS]           =   ADC4_DEFAULT;
}



//****************************************************************************
//
// Helper functions
//
//****************************************************************************


//*****************************************************************************
//
//! Internal function used by readData() to convert ADC data from multiple unsigned
//! bytes into a single signed 32-bit word.
//!
//! \fn int32_t signExtend(const uint8_t dataBytes[])
//!
//! \param dataBytes is a pointer to uint8_t[] where the first element is the MSB.
//!
//! \return Returns the signed-extend 32-bit result.
//
//*****************************************************************************
int32_t signExtend(const uint8_t dataBytes[])
{
#ifdef WORD_LENGTH_24BIT

    int32_t upperByte   = ((int32_t) dataBytes[0] << 24);
    int32_t middleByte  = ((int32_t) dataBytes[1] << 16);
    int32_t lowerByte   = ((int32_t) dataBytes[2] << 8);

    // NOTE: This right-shift operation on signed data maintains the signed bit,
    // and provides for the sign-extension from 24 to 32 bits.
    return (((int32_t) (upperByte | middleByte | lowerByte)) >> 8);

#elif defined WORD_LENGTH_32BIT_SIGN_EXTEND

    int32_t signByte    = ((int32_t) dataBytes[0] << 24);
    int32_t upperByte   = ((int32_t) dataBytes[1] << 16);
    int32_t middleByte  = ((int32_t) dataBytes[2] << 8);
    int32_t lowerByte   = ((int32_t) dataBytes[3] << 0);

    return (signByte | upperByte | middleByte | lowerByte);

#elif defined WORD_LENGTH_32BIT_ZERO_PADDED

    int32_t upperByte   = ((int32_t) dataBytes[0] << 24);
    int32_t middleByte  = ((int32_t) dataBytes[1] << 16);
    int32_t lowerByte   = ((int32_t) dataBytes[2] << 8);

    // NOTE: This right-shift operation on signed data maintains the signed bit,
    // and provides for the sign-extension from 24 to 32 bits.
    return (((int32_t) (upperByte | middleByte | lowerByte)) >> 8);     // Right-shift of signed data maintains signed bit

#elif defined WORD_LENGTH_16BIT_TRUNCATED

    int32_t upperByte   = ((int32_t) dataBytes[0] << 24);
    int32_t lowerByte   = ((int32_t) dataBytes[1] << 16);

    // NOTE: This right-shift operation on signed data maintains the signed bit,
    // and provides for the sign-extension from 16 to 32 bits.
    return (((int32_t) (upperByte | lowerByte)) >> 16);

#endif
}
/**/
/**
 *
 * \copyright Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef ADS131A04_H_
#define ADS131A04_H_


// Standard libraries
#include <assert.h>
#include <stdint.h>
#include <stdbool.h>

// Custom libraries
#include "hal.h"


//
// Configure Register settings - NOTE: These values can be change, but FIXED mode is recommended!
//

    // Fixed SPI Frame Mode - NOTE: Dynamic frame mode requires additional logic
    // (not provided in this example code) to prevent the F_SPI error flag.
    #define SET_FIXED

    // CRC Enable - NOTE: In this example enabling CRC will increase the amount
    // of time it takes the MCU to construct and send an SPI frame!
    //#define SET_CRC_EN

    // CRC Mode - Selects which SPI words get included in the CRC computation
    //#define SET_CRC_MODE


//
// Pin settings - NOTE: These values are NOT configurable in this example!
// This example code is only targeted at asynchronous slave mode with hamming validation turned off.
//

    // M0 -> Tied to IOVDD
    #define ASYNC_SLAVE_MODE

    // M1 -> Tied to GND
    #define WORD_LENGTH_BITS        ((uint8_t) 24)
    #define WORD_LENGTH_24BIT
    //#define WORD_LENGTH_16BIT
    //#define WORD_LENGTH_32BIT

    // M2 -> Tied to GND
    //#define HAMMING_ENABLED


//****************************************************************************
//
// Channel data structure
//
//****************************************************************************

typedef struct
{
    int32_t channel1;
    int32_t channel2;
    int32_t channel3;
    int32_t channel4;
    uint16_t response;
    uint16_t crc;

} adc_data_struct;



//**********************************************************************************
//
// Function prototypes
//
//**********************************************************************************

uint8_t     getRegisterValue(uint8_t address);
void        adcStartup(void);
uint8_t     readSingleRegister(uint8_t address);
void        writeSingleRegister(uint8_t address, uint8_t data);
bool        readData(adc_data_struct *dataStruct);
uint16_t    sendCommand(uint16_t opcode);
bool        lockRegisters(void);
bool        unlockRegisters(void);
uint16_t    calculateCRC(const uint8_t dataBytes[], uint8_t numberBytes, uint16_t initialValue);

// Helper functions
void        restoreRegisterDefaults(void);
int32_t     signExtend(const uint8_t dataBytes[]);



//**********************************************************************************
//
// Device commands
//
//**********************************************************************************

#define OPCODE_NULL                             ((uint16_t) 0x0000)
#define OPCODE_RESET                            ((uint16_t) 0x0011)
#define OPCODE_STANDBY                          ((uint16_t) 0x0022)
#define OPCODE_WAKEUP                           ((uint16_t) 0x0033)
#define OPCODE_LOCK                             ((uint16_t) 0x0555)
#define OPCODE_UNLOCK                           ((uint16_t) 0x0655)
#define OPCODE_RREG                             ((uint16_t) 0x2000)
#define OPCODE_WREG                             ((uint16_t) 0x4000)

// NOTE: The following command(s) are not implemented in this example...
//#define OPCODE_WREGS                            ((uint16_t) 0x6000)



//**********************************************************************************
//
// Register definitions
//
//**********************************************************************************

#define NUM_REGISTERS           ((uint8_t) 21)


/* Register 0x00 (ID_MSB) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |                                           NU_CH[7:0]                                          |
 * -------------------------------------------------------------------------------------------------
 */

    /* ID_MSB register address */
    #define ID_MSB_ADDRESS													((uint8_t) 0x00)

    /* ID_MSB register field masks */
    #define ID_MSB_NU_CH_MASK												((uint8_t) 0xFF)

    /* NU_CH field values */
    #define ID_MSB_NU_CH_2													((uint8_t) 0x02)
    #define ID_MSB_NU_CH_4													((uint8_t) 0x04)



/* Register 0x01 (ID_LSB) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |                                          REV_ID[7:0]                                          |
 * -------------------------------------------------------------------------------------------------
 */

    /* ID_LSB register address */
    #define ID_LSB_ADDRESS													((uint8_t) 0x01)

    /* ID_LSB register field masks */
    #define ID_LSB_REV_ID_MASK												((uint8_t) 0xFF)



/* Register 0x02 (STAT_1) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |   F_OPC   |   F_SPI   |  F_ADCIN  |   F_WDT   |  F_RESYNC |   F_DRDY  |  F_CHECK  |
 * -------------------------------------------------------------------------------------------------
 */

    /* STAT_1 register address */
    #define STAT_1_ADDRESS													((uint8_t) 0x02)

    /* STAT_1 default (reset) value */
    #define STAT_1_DEFAULT													((uint8_t) 0x00)

    /* STAT_1 register field masks */
    #define STAT_1_F_OPC_MASK												((uint8_t) 0x40)
    #define STAT_1_F_SPI_MASK												((uint8_t) 0x20)
    #define STAT_1_F_ADCIN_MASK												((uint8_t) 0x10)
    #define STAT_1_F_WDT_MASK												((uint8_t) 0x08)
    #define STAT_1_F_RESYNC_MASK											((uint8_t) 0x04)
    #define STAT_1_F_DRDY_MASK												((uint8_t) 0x02)
    #define STAT_1_F_CHECK_MASK												((uint8_t) 0x01)



/* Register 0x03 (STAT_P) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |   F_IN4P  |   F_IN3P  |   F_IN2P  |   F_IN1P  |
 * -------------------------------------------------------------------------------------------------
 */

    /* STAT_P register address */
    #define STAT_P_ADDRESS													((uint8_t) 0x03)

    /* STAT_P default (reset) value */
    #define STAT_P_DEFAULT													((uint8_t) 0x00)

    /* STAT_P register field masks */
    #define STAT_P_F_IN4P_MASK												((uint8_t) 0x08)
    #define STAT_P_F_IN3P_MASK												((uint8_t) 0x04)
    #define STAT_P_F_IN2P_MASK												((uint8_t) 0x02)
    #define STAT_P_F_IN1P_MASK												((uint8_t) 0x01)



/* Register 0x04 (STAT_N) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |   F_IN4N  |   F_IN3N  |   F_IN2N  |   F_IN1N  |
 * -------------------------------------------------------------------------------------------------
 */

    /* STAT_N register address */
    #define STAT_N_ADDRESS													((uint8_t) 0x04)

    /* STAT_N default (reset) value */
    #define STAT_N_DEFAULT													((uint8_t) 0x00)

    /* STAT_N register field masks */
    #define STAT_N_F_IN4N_MASK												((uint8_t) 0x08)
    #define STAT_N_F_IN3N_MASK												((uint8_t) 0x04)
    #define STAT_N_F_IN2N_MASK												((uint8_t) 0x02)
    #define STAT_N_F_IN1N_MASK												((uint8_t) 0x01)



/* Register 0x05 (STAT_S) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |     0     | F_STARTUP |    F_CS   |  F_FRAME  |
 * -------------------------------------------------------------------------------------------------
 */

    /* STAT_S register address */
    #define STAT_S_ADDRESS													((uint8_t) 0x05)

    /* STAT_S default (reset) value */
    #define STAT_S_DEFAULT													((uint8_t) 0x00)

    /* STAT_S register field masks */
    #define STAT_S_F_STARTUP_MASK											((uint8_t) 0x04)
    #define STAT_S_F_CS_MASK												((uint8_t) 0x02)
    #define STAT_S_F_FRAME_MASK												((uint8_t) 0x01)



/* Register 0x06 (ERROR_CNT) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |                                            ER[7:0]                                            |
 * -------------------------------------------------------------------------------------------------
 */

    /* ERROR_CNT register address */
    #define ERROR_CNT_ADDRESS												((uint8_t) 0x06)

    /* ERROR_CNT default (reset) value */
    #define ERROR_CNT_DEFAULT												((uint8_t) 0x00)

    /* ERROR_CNT register field masks */
    #define ERROR_CNT_ER_MASK												((uint8_t) 0xFF)



/* Register 0x07 (STAT_M2) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |       M2PIN[1:0]      |       M1PIN[1:0]      |       M0PIN[1:0]      |
 * -------------------------------------------------------------------------------------------------
 */

    /* STAT_M2 register address */
    #define STAT_M2_ADDRESS													((uint8_t) 0x07)

    /* STAT_M2 default (reset) value */
    #define STAT_M2_DEFAULT													((uint8_t) 0x00)
    #define STAT_M2_DEFAULT_MASK											((uint8_t) 0xC0)

    /* STAT_M2 register field masks */
    #define STAT_M2_M2PIN_MASK												((uint8_t) 0x30)
    #define STAT_M2_M1PIN_MASK												((uint8_t) 0x0C)
    #define STAT_M2_M0PIN_MASK												((uint8_t) 0x03)

    /* M2PIN field values */
    #define STAT_M2_M2PIN_M2_HAMMING_OFF									((uint8_t) 0x00)
    #define STAT_M2_M2PIN_M2_HAMMING_ON										((uint8_t) 0x10)
    #define STAT_M2_M2PIN_M2_NC												((uint8_t) 0x20)

    /* M1PIN field values */
    #define STAT_M2_M1PIN_M1_24BIT											((uint8_t) 0x00)
    #define STAT_M2_M1PIN_M1_32BIT											((uint8_t) 0x04)
    #define STAT_M2_M1PIN_M1_16BIT											((uint8_t) 0x08)

    /* M0PIN field values */
    #define STAT_M2_M0PIN_M0_SYNC_MASTER									((uint8_t) 0x00)
    #define STAT_M2_M0PIN_M0_ASYNC_SLAVE									((uint8_t) 0x01)
    #define STAT_M2_M0PIN_M0_SYNC_SLAVE										((uint8_t) 0x02)



/* Register 0x08 (RESERVED0) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |     0     |     0     |     0     |     0     |
 * -------------------------------------------------------------------------------------------------
 */



/* Register 0x09 (RESERVED1) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |     0     |     0     |     0     |     0     |
 * -------------------------------------------------------------------------------------------------
 */



/* Register 0x0A (RESERVED2) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |     0     |     0     |     0     |     0     |
 * -------------------------------------------------------------------------------------------------
 */



/* Register 0x0B (A_SYS_CFG) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |   VNCPEN  |    HRM    |     0     |  VREF_4V  | INT_REFEN |            COMP_TH[2:0]           |
 * -------------------------------------------------------------------------------------------------
 */

    /* A_SYS_CFG register address */
    #define A_SYS_CFG_ADDRESS												((uint8_t) 0x0B)

    /* A_SYS_CFG default (reset) value */
    #define A_SYS_CFG_DEFAULT												((uint8_t) 0x60)

    /* A_SYS_CFG register field masks */
    #define A_SYS_CFG_VNCPEN_MASK											((uint8_t) 0x80)
    #define A_SYS_CFG_HRM_MASK												((uint8_t) 0x40)
    #define A_SYS_CFG_VREF_4V_MASK											((uint8_t) 0x10)
    #define A_SYS_CFG_INT_REFEN_MASK										((uint8_t) 0x08)
    #define A_SYS_CFG_COMP_TH_MASK											((uint8_t) 0x07)

    /* COMP_TH field values */
    #define A_SYS_CFG_COMP_TH_HIGH_95_LOW_5									((uint8_t) 0x00)
    #define A_SYS_CFG_COMP_TH_HIGH_92p5_LOW_7p5								((uint8_t) 0x01)
    #define A_SYS_CFG_COMP_TH_HIGH_90_LOW_10								((uint8_t) 0x02)
    #define A_SYS_CFG_COMP_TH_HIGH_87p5_LOW_12p5							((uint8_t) 0x03)
    #define A_SYS_CFG_COMP_TH_HIGH_85_LOW_15								((uint8_t) 0x04)
    #define A_SYS_CFG_COMP_TH_HIGH_80_LOW_20								((uint8_t) 0x05)
    #define A_SYS_CFG_COMP_TH_HIGH_75_LOW_25								((uint8_t) 0x06)
    #define A_SYS_CFG_COMP_TH_HIGH_70_LOW_30								((uint8_t) 0x07)



/* Register 0x0C (D_SYS_CFG) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |   WDT_EN  |  CRC_MODE |       DNDLY[1:0]      |      HIZDLY[1:0]      |   FIXED   |   CRC_EN  |
 * -------------------------------------------------------------------------------------------------
 */

    /* D_SYS_CFG register address */
    #define D_SYS_CFG_ADDRESS												((uint8_t) 0x0C)

    /* D_SYS_CFG default (reset) value */
    #define D_SYS_CFG_DEFAULT												((uint8_t) 0x3C)

    /* D_SYS_CFG register field masks */
    #define D_SYS_CFG_WDT_EN_MASK											((uint8_t) 0x80)
    #define D_SYS_CFG_CRC_MODE_MASK											((uint8_t) 0x40)
    #define D_SYS_CFG_DNDLY_MASK											((uint8_t) 0x30)
    #define D_SYS_CFG_HIZDLY_MASK											((uint8_t) 0x0C)
    #define D_SYS_CFG_FIXED_MASK											((uint8_t) 0x02)
    #define D_SYS_CFG_CRC_EN_MASK											((uint8_t) 0x01)

    /* DNDLY field values */
    #define D_SYS_CFG_DNDLY_6ns												((uint8_t) 0x00)
    #define D_SYS_CFG_DNDLY_8ns												((uint8_t) 0x10)
    #define D_SYS_CFG_DNDLY_10ns											((uint8_t) 0x20)
    #define D_SYS_CFG_DNDLY_12ns											((uint8_t) 0x30)

    /* HIZDLY field values */
    #define D_SYS_CFG_HIZDLY_6ns											((uint8_t) 0x00)
    #define D_SYS_CFG_HIZDLY_8ns											((uint8_t) 0x04)
    #define D_SYS_CFG_HIZDLY_10ns											((uint8_t) 0x08)
    #define D_SYS_CFG_HIZDLY_12ns											((uint8_t) 0x0C)



/* Register 0x0D (CLK1) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |   CLKSRC  |     0     |     0     |     0     |            CLK_DIV[2:0]           |     0     |
 * -------------------------------------------------------------------------------------------------
 */

    /* CLK1 register address */
    #define CLK1_ADDRESS													((uint8_t) 0x0D)

    /* CLK1 default (reset) value */
    #define CLK1_DEFAULT													((uint8_t) 0x08)

    /* CLK1 register field masks */
    #define CLK1_CLKSRC_MASK												((uint8_t) 0x80)
    #define CLK1_CLK_DIV_MASK												((uint8_t) 0x0E)

    /* CLK_DIV field values */
    #define CLK1_CLK_DIV_2													((uint8_t) 0x02)
    #define CLK1_CLK_DIV_4													((uint8_t) 0x04)
    #define CLK1_CLK_DIV_6													((uint8_t) 0x06)
    #define CLK1_CLK_DIV_8													((uint8_t) 0x08)
    #define CLK1_CLK_DIV_10													((uint8_t) 0x0A)
    #define CLK1_CLK_DIV_12													((uint8_t) 0x0C)
    #define CLK1_CLK_DIV_14													((uint8_t) 0x0E)



/* Register 0x0E (CLK2) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |           ICLK_DIV[2:0]           |     0     |                    OSR[3:0]                   |
 * -------------------------------------------------------------------------------------------------
 */

    /* CLK2 register address */
    #define CLK2_ADDRESS													((uint8_t) 0x0E)

    /* CLK2 default (reset) value */
    #define CLK2_DEFAULT													((uint8_t) 0x86)

    /* CLK2 register field masks */
    #define CLK2_ICLK_DIV_MASK												((uint8_t) 0xE0)
    #define CLK2_OSR_MASK													((uint8_t) 0x0F)

    /* ICLK_DIV field values */
    #define CLK2_ICLK_DIV_2													((uint8_t) 0x20)
    #define CLK2_ICLK_DIV_4													((uint8_t) 0x40)
    #define CLK2_ICLK_DIV_6													((uint8_t) 0x60)
    #define CLK2_ICLK_DIV_8													((uint8_t) 0x80)
    #define CLK2_ICLK_DIV_10												((uint8_t) 0xA0)
    #define CLK2_ICLK_DIV_12												((uint8_t) 0xC0)
    #define CLK2_ICLK_DIV_14												((uint8_t) 0xE0)

    /* OSR field values */
    #define CLK2_OSR_4096													((uint8_t) 0x00)
    #define CLK2_OSR_2048													((uint8_t) 0x01)
    #define CLK2_OSR_1024													((uint8_t) 0x02)
    #define CLK2_OSR_800													((uint8_t) 0x03)
    #define CLK2_OSR_768													((uint8_t) 0x04)
    #define CLK2_OSR_512													((uint8_t) 0x05)
    #define CLK2_OSR_400													((uint8_t) 0x06)
    #define CLK2_OSR_384													((uint8_t) 0x07)
    #define CLK2_OSR_256													((uint8_t) 0x08)
    #define CLK2_OSR_200													((uint8_t) 0x09)
    #define CLK2_OSR_192													((uint8_t) 0x0A)
    #define CLK2_OSR_128													((uint8_t) 0x0B)
    #define CLK2_OSR_96														((uint8_t) 0x0C)
    #define CLK2_OSR_64														((uint8_t) 0x0D)
    #define CLK2_OSR_48														((uint8_t) 0x0E)
    #define CLK2_OSR_32														((uint8_t) 0x0F)



/* Register 0x0F (ADC_ENA) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |                    ENA[3:0]                   |
 * -------------------------------------------------------------------------------------------------
 */

    /* ADC_ENA register address */
    #define ADC_ENA_ADDRESS													((uint8_t) 0x0F)

    /* ADC_ENA default (reset) value */
    #define ADC_ENA_DEFAULT													((uint8_t) 0x00)

    /* ADC_ENA register field masks */
    #define ADC_ENA_ENA_MASK												((uint8_t) 0x0F)

    /* ENA field values */
    #define ADC_ENA_ENA_ALL_CH_PWDN											((uint8_t) 0x00)
    #define ADC_ENA_ENA_ALL_CH_PWUP											((uint8_t) 0x0F)



/* Register 0x10 (RESERVED3) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |     0     |     0     |     0     |     0     |
 * -------------------------------------------------------------------------------------------------
 */



/* Register 0x11 (ADC1) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |     0     |             GAIN1[2:0]            |
 * -------------------------------------------------------------------------------------------------
 */

    /* ADC1 register address */
    #define ADC1_ADDRESS													((uint8_t) 0x11)

    /* ADC1 default (reset) value */
    #define ADC1_DEFAULT													((uint8_t) 0x00)

    /* ADC1 register field masks */
    #define ADC1_GAIN1_MASK													((uint8_t) 0x07)

    /* GAIN1 field values */
    #define ADC1_GAIN1_1													((uint8_t) 0x00)
    #define ADC1_GAIN1_2													((uint8_t) 0x01)
    #define ADC1_GAIN1_4													((uint8_t) 0x02)
    #define ADC1_GAIN1_8													((uint8_t) 0x03)
    #define ADC1_GAIN1_16													((uint8_t) 0x04)



/* Register 0x12 (ADC2) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |     0     |             GAIN2[2:0]            |
 * -------------------------------------------------------------------------------------------------
 */

    /* ADC2 register address */
    #define ADC2_ADDRESS													((uint8_t) 0x12)

    /* ADC2 default (reset) value */
    #define ADC2_DEFAULT													((uint8_t) 0x00)

    /* ADC2 register field masks */
    #define ADC2_GAIN2_MASK													((uint8_t) 0x07)

    /* GAIN2 field values */
    #define ADC2_GAIN2_1													((uint8_t) 0x00)
    #define ADC2_GAIN2_2													((uint8_t) 0x01)
    #define ADC2_GAIN2_4													((uint8_t) 0x02)
    #define ADC2_GAIN2_8													((uint8_t) 0x03)
    #define ADC2_GAIN2_16													((uint8_t) 0x04)



/* Register 0x13 (ADC3) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |     0     |             GAIN3[2:0]            |
 * -------------------------------------------------------------------------------------------------
 */

    /* ADC3 register address */
    #define ADC3_ADDRESS													((uint8_t) 0x13)

    /* ADC3 default (reset) value */
    #define ADC3_DEFAULT													((uint8_t) 0x00)

    /* ADC3 register field masks */
    #define ADC3_GAIN3_MASK													((uint8_t) 0x07)

    /* GAIN3 field values */
    #define ADC3_GAIN3_1													((uint8_t) 0x00)
    #define ADC3_GAIN3_2													((uint8_t) 0x01)
    #define ADC3_GAIN3_4													((uint8_t) 0x02)
    #define ADC3_GAIN3_8													((uint8_t) 0x03)
    #define ADC3_GAIN3_16													((uint8_t) 0x04)



/* Register 0x14 (ADC4) definition
 * -------------------------------------------------------------------------------------------------
 * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 * -------------------------------------------------------------------------------------------------
 * |     0     |     0     |     0     |     0     |     0     |             GAIN4[2:0]            |
 * -------------------------------------------------------------------------------------------------
 */

    /* ADC4 register address */
    #define ADC4_ADDRESS													((uint8_t) 0x14)

    /* ADC4 default (reset) value */
    #define ADC4_DEFAULT													((uint8_t) 0x00)

    /* ADC4 register field masks */
    #define ADC4_GAIN4_MASK													((uint8_t) 0x07)

    /* GAIN4 field values */
    #define ADC4_GAIN4_1													((uint8_t) 0x00)
    #define ADC4_GAIN4_2													((uint8_t) 0x01)
    #define ADC4_GAIN4_4													((uint8_t) 0x02)
    #define ADC4_GAIN4_8													((uint8_t) 0x03)
    #define ADC4_GAIN4_16													((uint8_t) 0x04)



//****************************************************************************
//
// Register settings macros
//
//****************************************************************************

// NOTE: These macros can be used in logical expressions for checking known register values.
// These macros will take on the value from the last register read/write operation, or the
// default register value if no register operations have occurred or the device is reset.

#define CRC_EN              ((bool) (getRegisterValue(D_SYS_CFG_ADDRESS) & D_SYS_CFG_CRC_EN_MASK))
#define CRC_MODE            ((bool) (getRegisterValue(D_SYS_CFG_ADDRESS) & D_SYS_CFG_CRC_MODE_MASK))
#define FIXED               ((bool) (getRegisterValue(D_SYS_CFG_ADDRESS) & D_SYS_CFG_FIXED_MASK))



#endif /* ADS131A04_H_ */

### 回答1: STM32F407是一款高性能的微控制器,支持32位ARM Cortex-M4内核,可用于广泛的应用领域。而ADS131A04是一款高精度模数转换器,主要用于测量各种信号,如压力、温度、速度等。 在STM32F407和ADS131A04的程序设计方面,需要先进行硬件连接,将ADS131A04的模拟输出引脚连接到STM32F407的模拟输入引脚上。然后编写相关的驱动程序,通过读取ADS131A04的模拟输出信号来实现测量和采集数据。 在代码实现方面,首先需要对ADS131A04进行初始化设置,并配置相应的时钟、增益、采样率等参数。然后利用STM32F407的ADC模块读取ADS131A04的模拟输出信号,并进行相应的处理,包括数据校准、滤波等。最后将处理后的数据传输至外设或显示出来。 要实现一个稳定、精准的STM32F407和ADS131A04程序,需要注意以下几点: 1. 硬件连接要正确,避免接口松动或接错引脚。 2. 在程序设计中,需要对异常情况进行处理,如ADC转换失败等。 3. 数据的处理需要充分考虑精度和稳定性,可利用滤波算法等手段提高数据的质量。 4. 在程序的开发测试过程中,需要进行充分的测试和调试,并记录测试结果,以便后续的改进。 综上所述,STM32F407和ADS131A04程序的设计需要仔细考虑硬件连接、编写相关驱动程序和对数据进行处理等方面,保证程序的稳定性和精确度。只有有了稳定性和精确度,才能更好地应用于各种实际应用领域中,得到更好的效果。 ### 回答2: STM32F407是一款高性能的ARM Cortex-M4微控制器,具备高速运算能力和多种通信接口,适合嵌入式系统应用。ADS131A04是一款高精度、低功耗的多通道模数转换器(ADC),能够采集多个模拟信号并将其转换为数字信号。 在使用STM32F407和ADS131A04开发嵌入式应用程序时,需要先熟悉两者的各种硬件接口和软件功能。首先需要了解ADS131A04的通信协议和数据格式,以便STM32F407能够正确地接收和解析采集到的数据。可以通过硬件接口(如SPI或I2C)或者模拟信号输入来采集数据,并将其存储在STM32F407的内存中。 然后,需要编写代码来控制ADS131A04和STM32F407之间的通信,并实现数据的采集、转换和处理。可采用STM32CubeMX或Keil等开发工具来编写和调试程序,使其能够快速、准确地采集和处理信号。 最后,需要对程序进行测试,并根据实际情况对其进行优化和调整,以满足特定应用场景的需求。在程序开发和调试过程中,需要注意硬件和软件接口的兼容性、可靠性和稳定性,并遵循相关的编码规范和标准,确保程序的正确性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值