文章目錄
- 德州儀器ADS1220概述
- 資料
- 引腳&封裝
- 布線
- 寄存器
- 配置寄存器0(00h)
- 配置寄存器1(01h)
- 配置寄存器2(02h)
- 配置寄存器3(03h)
- 連續轉換流程
- 驅動源碼
- ads1220.c
- ads1220.h
德州儀器ADS1220概述
-
高性能 24 位Δ-Σ 模數轉換器(ADC)
-
支持兩個差分輸入或四個單端輸入
-
集成了低噪聲可編程增益放大器(PGA)、雙可編程激勵電流源、電壓基準、振蕩器、低側開關以及精密溫度傳感器
-
支持高達 2000 SPS 的采樣速率,并能在單周期內完成穩定轉換
-
其數字濾波器在 20SPS 采樣頻率下可同時抑制 50Hz 和 60Hz 干擾
-
內部 PGA 提供高達 128V/V 的增益,特別適用于小型傳感器信號測量
-
器件支持偽差分或全差分信號測量,并可通過配置禁用內部 PGA,在保持高輸入阻抗的同時提供最高 4V/V 增益,實現單端測量
-
在禁用 PGA 的占空比模式下,器件功耗可低至 120μA
-
ADS1220 采用 VQFN-16 或 TSSOP-16 封裝,工作溫度范圍為 -40°C 至 +125°C,適用于嚴苛環境下的精密測量應用。
資料
ADS1220 DATASHEET
引腳&封裝
布線
在AIN0和AIN1之間、AIN2和AIN3之間、REFP0和REFN0之間的外圍都是兩個電阻三個電容,其作用如下:
- 抗混疊濾波
差分電容與電阻構成一階RC濾波器,用于限制高頻噪聲和混疊效應。Δ-Σ ADC的調制器以高頻(如256kHz)采樣輸入信號,未衰減的高頻成分會混疊到通帶,導致測量誤差。 - 共模噪聲抑制
共模電容用于衰減共模噪聲。差分電容應比共模電容大10倍,以避免電容不匹配將共模噪聲轉為差分噪聲。 - 保護ADC輸入
外部濾波器電阻還限制輸入過壓時的電流,保護內部ESD二極管。
寄存器
配置寄存器0(00h)
- MUX[3:0] :輸入多路復用器配置,選擇差分/單端輸入組合或系統監測功能(如電源/基準監測)。
單端測量需禁用PGA,差分測量可啟用PGA高增益。 - GAIN[2:0] :設置PGA增益(1至128),禁用PGA時僅支持增益1/2/4。
低噪聲放大器,用于放大微小傳感器信號(如熱電偶/RTD)。 - PGA_BYPASS:禁用和旁路PGA以擴展共模電壓范圍(AVSS-0.1V至AVDD+0.1V)。
單端信號測量或需寬共模電壓時啟用。 當PGA旁路時,內部放大器被禁用,犧牲增益換取更寬輸入范圍。
配置寄存器1(01h)
- DR[2:0]:選擇數據速率(5SPS至2kSPS),隨工作模式(正常/占空比/Turbo)變化。
- MODE[1:0]:設置工作模式(正常/占空比/Turbo)。
- CM:轉換模式選擇(單次/連續)。
- TS:啟用內部溫度傳感器模式。
- BCS:控制10μA燒毀電流源,用于傳感器故障檢測。
燒毀電流源用于檢測傳感器開路(拉至滿量程)或短路(近零讀數),但會引入測量誤差,精密測量需禁用以避免干擾。
配置寄存器2(02h)
- VREF[1:0] :選擇基準源(內部2.048V/外部基準/電源)。
- 50/60[1:0] :配置FIR濾波器抑制50Hz/60Hz工頻干擾。
啟用抑制會限制數據速率(僅20SPS或5SPS下有效)。
未啟用時(50/60[1:0]=00),濾波器帶寬更寬,適合高頻信號但抗干擾能力下降。 - PSW:控制低側電源開關(AIN3/REFN1至AVSS)。
- IDAC[2:0] :設置激勵電流源輸出(10μA至1.5mA)。
典型應用是為RTD(電阻溫度檢測器)等傳感器提供精確的激勵電流,通過將IDAC1和IDAC2分別接入RTD的兩條引線,利用匹配的電流抵消引線電阻產生的壓降誤差。
IDAC合規電壓是電流源輸出端電壓需≤AVDD-0.9V,否則精度下降。
配置寄存器3(03h)
- I1MUX[2:0]:路由IDAC1至指定引腳(AINx或基準輸入)。
- I2MUX[2:0]:路由IDAC2至指定引腳(AINx或基準輸入)。
- DRDYM:選擇DRDY指示模式(僅專用引腳或復用DOUT/DRDY)。
- 保留位:固定寫0。
連續轉換流程
- 上電:延遲以允許電源穩定并完成上電復位(最小50 μs)。
- 配置
SPI
接口:將微控制器的SPI
接口配置為模式1(CPOL = 0
,CPHA = 1
)。 - 配置片選引腳:如果片選(
CS
)引腳未永久接地,將連接到CS
的微控制器GPIO
配置為輸出。 - 配置數據準備好引腳:將連接到
DRDY
引腳的微控制器GPIO
配置為下降沿觸發的中斷輸入。 - 拉低片選信號:將
CS
拉低以選中設備。 - 延遲CSSC時間:延遲至少td(
CSSC
)的時間。 - 發送復位命令:發送復位命令(06h),確保設備在上電后正確復位。
- 延遲復位時間:延遲至少50 μs + 32 * t(CLK)的時間。
- 寫入寄存器配置:使用
WREG
命令(43h, 08h, 04h, 10h, 和00h)寫入相應的寄存器配置。 - 可選配置驗證:作為可選的驗證步驟,使用RREG命令(23h)讀回所有配置寄存器。
- 啟動轉換:發送
START/SYNC
命令(08h),以連續轉換模式啟動轉換。 - 延遲SCCS時間:延遲至少td(
SCCS
)的時間。 - 釋放片選信號:將
CS
拉高以重置串行接口。 - 數據讀取循環,循環執行以下操作:
14.1 等待DRDY
引腳變為低電平。
14.2 將CS
拉低。
14.3 延遲至少td(CSSC
)的時間。
14.4 發送24個SCLK
上升沿,以從DOUT/DRDY
讀取轉換數據。
14.5 延遲至少td(SCCS
)的時間。
14.6 將CS
拉高。 - 進入待機模式
15.1 將CS
拉低。
15.2 延遲至少td(CSSC
)的時間。
15.3 發送POWERDOWN
命令(02h),停止轉換并將設備置于待機模式。
15.4 延遲至少td(SCCS
)的時間。
15.5 將CS
拉高。
注:上面的步驟14.1中,等待
DRDY
引腳變為低電平,但在一些應用中,DRDY
引腳可能沒有接入MCU。
這種情況可以等待DOUT/DRDY
引腳變為低電平,以確認ADC已經完成轉化。
但需要注意先拉低片選,再去等待DOUT/DRDY
引腳變為低電平。
.
驅動源碼
ads1220.c
/********************************************************************************* @file ads1220.c* @author zjq* @brief ads1220 bsp*******************************************************************************/
#include "ads1220.h"
#include "Gpio.h"
#include "spi.h"/* Cmd ***********************************************************************/
const uint8_t ADS1220_CMD_RESET = 0x06;
const uint8_t ADS1220_CMD_START = 0x08;
const uint8_t ADS1220_CMD_RDATA = 0x10;
const uint8_t ADS1220_CMD_PWR_DOWN = 0x02;
const uint8_t ADS1220_CMD_READ_REG = 0x20;
const uint8_t ADS1220_CMD_WRITE_REG = 0x40;/* Static Function ***********************************************************/
static ADS1220_StatusTypedef ADS1220_SPI_Write(uint8_t const *pWrite, uint8_t len);
static ADS1220_StatusTypedef ADS1220_SPI_Receive(uint8_t *pRecv, uint8_t len);
static ADS1220_StatusTypedef ADS1220_WriteRegister(uint32_t regStartAddr, uint32_t regNum, uint8_t *pData);
static ADS1220_StatusTypedef ADS1220_ReadRegister(uint32_t regStartAddr, uint32_t regNum, uint8_t *pData);/*** @brief Use SPI Write to ADS1220* @param pWrite* @param len* @retval ADS1220 Status*/
static ADS1220_StatusTypedef ADS1220_SPI_Write(uint8_t const *pWrite, uint8_t len)
{for (uint8_t i = 0; i < len; i++){if (HAL_OK != HAL_SPI_Transmit(&hspi3, &pWrite[i], 1, 10)){return ADS1220_FAIL;}}return ADS1220_OK;
}/*** @brief Use SPI Read From ADS1220* @param pRecv* @param len* @retval ADS1220 Status*/
static ADS1220_StatusTypedef ADS1220_SPI_Receive(uint8_t *pRecv, uint8_t len)
{uint8_t temp = 0xff;for (uint8_t i = 0; i < len; i++){if (HAL_OK != HAL_SPI_TransmitReceive(&hspi3, &temp, &pRecv[i], 1, 10)){return ADS1220_FAIL;}}return ADS1220_OK;
}/*** @brief Write ADS1220 Register* @param regStartAddr* @param regNum* @param pData* @retval ADS1220 Status*/
static ADS1220_StatusTypedef ADS1220_WriteRegister(uint32_t regStartAddr, uint32_t regNum, uint8_t *pData)
{ADS1220_CS_LOW();HAL_Delay(10);uint8_t temp = ((regStartAddr << 2) & 0x0c);temp |= (regNum - 1) & 0x03;temp |= ADS1220_CMD_WRITE_REG;if (ADS1220_OK != ADS1220_SPI_Write(&temp, 1)){return ADS1220_FAIL;}if (ADS1220_OK != ADS1220_SPI_Write(pData, regNum)){return ADS1220_FAIL;}ADS1220_CS_HIGH();return ADS1220_OK;
}/*** @brief Read ADS1220 Register* @param regStartAddr* @param regNum* @param pData* @retval ADS1220 Status*/
static ADS1220_StatusTypedef ADS1220_ReadRegister(uint32_t regStartAddr, uint32_t regNum, uint8_t *pData)
{ADS1220_CS_LOW();HAL_Delay(5);uint8_t temp = ((regStartAddr << 2) & 0x0c);temp |= (regNum - 1) & 0x03;temp |= ADS1220_CMD_READ_REG;if (ADS1220_OK != ADS1220_SPI_Write(&temp, 1)){return ADS1220_FAIL;}if (ADS1220_OK != ADS1220_SPI_Receive(pData, regNum)){return ADS1220_FAIL;}ADS1220_CS_HIGH();return ADS1220_OK;
}/* Global Function ***********************************************************//*** @brief Initialize ADS1220* @param void* @note* @retval void*/
void ADS1220_Init(void)
{MX_SPI3_Init();ADS1220_Reset();
}/*** @brief Select ADS1220 channel* @param chl* @note* @retval ADS1220 Status*/
ADS1220_StatusTypedef ADS1220_Channal_Sel(uint8_t chl)
{static uint8_t recvTemp[4] = {0};static uint8_t sendTemp[4] = {0};switch (chl){case ADS1220_CH0:sendTemp[0] = MUX_P_AIN0_N_AVSS;break;case ADS1220_CH1:sendTemp[0] = MUX_P_AIN1_N_AVSS;break;case ADS1220_CH2:sendTemp[0] = MUX_P_AIN2_N_AVSS;break;case ADS1220_CH3:sendTemp[0] = MUX_P_AIN3_N_AVSS;break;}sendTemp[0] |= GAIN_1 | PGA_BYPASS;sendTemp[1] = DR_45SPS | MODE_NORMAL | CM_SINGLE | TS_OFF | BCS_OFF;sendTemp[2] = VREF_EXT_REF0_PINS | FIR_50_60 | PSW_OPEN | IDAC_OFF;sendTemp[3] = I1MUX_DISABLED | I2MUX_DISABLED | DRDY_ON_DOUT_DRDY;ADS1220_WriteRegister(0x00, 4, sendTemp);HAL_Delay(5);ADS1220_ReadRegister(0x00, 4, recvTemp);for (uint8_t i = 0; i < 4; i++){if (sendTemp[i] != recvTemp[i]){return ADS1220_FAIL;}}return ADS1220_OK;
}/*** @brief Start ADS1220 ADC convert* @param void* @note* @retval ADS1220 Status*/
ADS1220_StatusTypedef ADS1220_Start(void)
{ADS1220_CS_LOW();if (ADS1220_OK != ADS1220_SPI_Write(&ADS1220_CMD_START, 1)){ADS1220_CS_HIGH();return ADS1220_FAIL;}ADS1220_CS_HIGH();return ADS1220_OK;
}/*** @brief Reset ADS1220* @param void* @note* @retval ADS1220 Status*/
ADS1220_StatusTypedef ADS1220_Reset(void)
{ADS1220_CS_LOW();if (ADS1220_OK != ADS1220_SPI_Write(&ADS1220_CMD_RESET, 1)){ADS1220_CS_HIGH();return ADS1220_FAIL;}ADS1220_CS_HIGH();return ADS1220_OK;
}/*** @brief Wait ADS1220 DRDY pin* @param timeout* @note* @retval ADS1220 Status*/
ADS1220_StatusTypedef ADS1220_Wait_DRDY(uint8_t timeout)
{uint32_t beginTime = HAL_GetTick();ADS1220_CS_LOW();HAL_Delay(5);while ((HAL_GetTick() - beginTime) < timeout){if (ADS1220_DRDY_RDY == ADS1220_DRDY_GET()){ADS1220_CS_HIGH();return ADS1220_OK;}}ADS1220_CS_HIGH();return ADS1220_FAIL;
}/*** @brief Read ADS1220 ADC convert result* @param void* @note* @retval Convert result*/
int32_t ADS1220_Read_Data(void)
{uint8_t temp[3] = {0};uint32_t returnVal = 0;ADS1220_CS_LOW();if (ADS1220_OK != ADS1220_SPI_Write(&ADS1220_CMD_RDATA, 1)){return 0;}if (ADS1220_OK != ADS1220_SPI_Receive(temp, 3)){return 0;}ADS1220_CS_HIGH();returnVal = (temp[0] << 16) | (temp[1] << 8) | (temp[2]);if (returnVal & 0x800000){returnVal |= 0xff000000;}return returnVal;
}/*** @brief ADS1220 ADC convert once and read result* @param chl* @note* @retval Convert result*/
int32_t ADS1220_ReadConvertOnce(uint8_t chl)
{ADS1220_Channal_Sel(chl);ADS1220_Start();ADS1220_Wait_DRDY(30);return ADS1220_Read_Data();
}
ads1220.h
/********************************************************************************* @file ads1220.h* @author zjq* @brief ads1220 bsp*******************************************************************************/
#ifndef __ADS_1220_H
#define __ADS_1220_H#include "stdint.h"
#include "sys.h"/* 函數返回值 */
typedef enum
{ADS1220_OK = 0x00U,ADS1220_FAIL = 0x01U,
} ADS1220_StatusTypedef;/* 通道選擇 */
#define ADS1220_CH0 (0)
#define ADS1220_CH1 (1)
#define ADS1220_CH2 (2)
#define ADS1220_CH3 (3)/* Reg0 [7:4]MUX */
#define MUX_P_AIN0_N_AIN1 (0X00U)
#define MUX_P_AIN0_N_AIN2 (0X10U)
#define MUX_P_AIN0_N_AIN3 (0X20U)
#define MUX_P_AIN1_N_AIN2 (0X30U)
#define MUX_P_AIN1_N_AIN3 (0X40U)
#define MUX_P_AIN2_N_AIN3 (0X50U)
#define MUX_P_AIN1_N_AIN0 (0X60U)
#define MUX_P_AIN3_N_AIN2 (0X70U)
#define MUX_P_AIN0_N_AVSS (0X80U)
#define MUX_P_AIN1_N_AVSS (0X90U)
#define MUX_P_AIN2_N_AVSS (0XA0U)
#define MUX_P_AIN3_N_AVSS (0XB0U)
#define MUX_P_REFP_N_REFN (0XC0U)
#define MUX_P_AVDD_N_AVSS (0XD0U)
#define MUX_PN_SHORT_HALFVDD (0XE0U)
/* Reg0 [3:1]GAIN */
#define GAIN_1 (0X00U)
#define GAIN_2 (0X02U)
#define GAIN_4 (0X04U)
#define GAIN_8 (0X06U)
#define GAIN_16 (0X08U)
#define GAIN_32 (0X0AU)
#define GAIN_64 (0X0CU)
#define GAIN_128 (0X0EU)
/* Reg0 [0]PGA_BYPASS */
#define PGA_BYPASS (0X01U)
#define PGA_AMP (0X00U)
/* Reg1 [7:5]DR */
#define DR_20SPS (0X00U)
#define DR_45SPS (0X20U)
#define DR_90SPS (0X40U)
#define DR_175SPS (0X60U)
#define DR_330SPS (0X80U)
#define DR_600SPS (0XA0U)
#define DR_1000SPS (0XC0U)
/* Reg1 [4:3]MODE */
#define MODE_NORMAL (0X00U)
#define MODE_DUTY (0X08U)
#define MODE_TURBO (0X10U)
/* Reg1 [2]CM */
#define CM_SINGLE (0X00U)
#define CM_CONTINUE (0X04U)
/* Reg1 [1]TS */
#define TS_ON (0X02U)
#define TS_OFF (0X00U)
/* Reg1 [0]BCS */
#define BCS_ON (0X01U)
#define BCS_OFF (0X00U)
/* Reg2 [7:6]VREF */
#define VREF_INTERNAL (0X00U)
#define VREF_EXT_REF0_PINS (0X40U)
#define VREF_EXT_REF1_PINS (0X80U)
#define VREF_AVDD (0XC0U)
/* Reg2 [5:4]50/60 */
#define FIR_NONE (0X00U)
#define FIR_50_60 (0X10U)
#define FIR_50 (0X20U)
#define FIR_60 (0X30U)
/* Reg2 [3]PSW */
#define PSW_OPEN (0X00U)
#define PSW_CLOSES (0X08U)
/* Reg2 [2:0]IDAC */
#define IDAC_OFF (0X00U)
#define IDAC_10uA (0X01U)
#define IDAC_50uA (0X02U)
#define IDAC_100uA (0X03U)
#define IDAC_250uA (0X04U)
#define IDAC_500uA (0X05U)
#define IDAC_1000uA (0X06U)
#define IDAC_1500uA (0X07U)
/* Reg3 [7:5]I1MUX */
#define I1MUX_DISABLED (0X00U)
#define I1MUX_AIN0 (0X20U)
#define I1MUX_AIN1 (0X40U)
#define I1MUX_AIN2 (0X60U)
#define I1MUX_AIN3 (0X80U)
#define I1MUX_REFP0 (0XA0U)
#define I1MUX_REFN0 (0XC0U)
/* Reg3 [4:2]I2MUX */
#define I2MUX_DISABLED (0X00U)
#define I2MUX_AIN0 (0X04U)
#define I2MUX_AIN1 (0X08U)
#define I2MUX_AIN2 (0X0CU)
#define I2MUX_AIN3 (0X10U)
#define I2MUX_REFP0 (0X14U)
#define I2MUX_REFN0 (0X18U)
/* Reg3 [1]DRDYM */
#define DRDY_ON_DOUT_DRDY (0X02U)
#define DRDY_ON_DRDY_ONLY (0X00U)/* Global Function ***********************************************************/
/*** @brief Initialize ADS1220* @param void* @note* @retval void*/
void ADS1220_Init(void);/*** @brief Select ADS1220 channel* @param chl* @note* @retval ADS1220 Status*/
ADS1220_StatusTypedef ADS1220_Channal_Sel(uint8_t chl);/*** @brief Start ADS1220 ADC convert* @param void* @note* @retval ADS1220 Status*/
ADS1220_StatusTypedef ADS1220_Start(void);/*** @brief Reset ADS1220* @param void* @note* @retval ADS1220 Status*/
ADS1220_StatusTypedef ADS1220_Reset(void);/*** @brief Wait ADS1220 DRDY pin* @param timeout* @note* @retval ADS1220 Status*/
ADS1220_StatusTypedef ADS1220_Wait_DRDY(uint8_t timeout);/*** @brief Read ADS1220 ADC convert result* @param void* @note* @retval Convert result*/
int32_t ADS1220_Read_Data(void);/*** @brief ADS1220 ADC convert once and read result* @param chl* @note* @retval Convert result*/
int32_t ADS1220_ReadConvertOnce(uint8_t chl);#endif