当前位置: 首页 > news >正文

基于STM32、HAL库的ADS1256IDBR模数转换器ADC驱动程序设计

一、简介:

ADS1256IDBR是德州仪器(TI)生产的一款高精度、24位Δ-Σ模数转换器(ADC),主要特性包括:

  • 24位无丢失码分辨率

  • 最高30kSPS的数据速率

  • 低噪声:2.5μV RMS(在30SPS时)

  • 8个单端或4个差分输入通道

  • 内置可编程增益放大器(PGA):1至64V/V

  • 内置低漂移电压基准(2.5V)

  • SPI兼容接口

  • 工作电压:3.3V或5V

二、硬件接口:

ADS1256引脚STM32L4引脚功能描述
DVDD3.3V数字电源
AVDD3.3V模拟电源
DGNDGND数字地
AGNDGND模拟地
CSPA4片选(低电平有效)
DINPA7SPI数据输入(MOSI)
DOUTPA6SPI数据输出(MISO)
SCLKPA5SPI时钟
DRDYPA3数据就绪(低电平有效)
RESETPA2复位(低电平有效)

注意:模拟和数字地应在一点连接,电源引脚应加去耦电容(0.1μF)

三、头文件:

#ifndef ADS1256_H
#define ADS1256_H

#include "stm32l4xx_hal.h"

// ADS1256寄存器地址
#define ADS1256_REG_STATUS  0x00
#define ADS1256_REG_MUX     0x01
#define ADS1256_REG_ADCON   0x02
#define ADS1256_REG_DRATE   0x03
#define ADS1256_REG_IO     0x04
#define ADS1256_REG_OFC0    0x05
#define ADS1256_REG_OFC1    0x06
#define ADS1256_REG_OFC2    0x07
#define ADS1256_REG_FSC0    0x08
#define ADS1256_REG_FSC1    0x09
#define ADS1256_REG_FSC2    0x0A

// ADS1256命令
#define ADS1256_CMD_WAKEUP  0x00
#define ADS1256_CMD_RDATA   0x01
#define ADS1256_CMD_RDATAC  0x03
#define ADS1256_CMD_SDATAC  0x0F
#define ADS1256_CMD_RREG    0x10
#define ADS1256_CMD_WREG    0x50
#define ADS1256_CMD_SELFCAL 0xF0
#define ADS1256_CMD_SELFOCAL 0xF1
#define ADS1256_CMD_SELFGCAL 0xF2
#define ADS1256_CMD_SYSOCAL 0xF3
#define ADS1256_CMD_SYSGCAL 0xF4
#define ADS1256_CMD_SYNC    0xFC
#define ADS1256_CMD_STANDBY 0xFD
#define ADS1256_CMD_RESET   0xFE

// PGA增益设置
typedef enum {
    ADS1256_GAIN_1 = 0,
    ADS1256_GAIN_2,
    ADS1256_GAIN_4,
    ADS1256_GAIN_8,
    ADS1256_GAIN_16,
    ADS1256_GAIN_32,
    ADS1256_GAIN_64
} ADS1256_Gain;

// 数据速率设置
typedef enum {
    ADS1256_DRATE_30000 = 0xF0,
    ADS1256_DRATE_15000 = 0xE0,
    ADS1256_DRATE_7500  = 0xD0,
    ADS1256_DRATE_3750  = 0xC0,
    ADS1256_DRATE_2000  = 0xB0,
    ADS1256_DRATE_1000  = 0xA1,
    ADS1256_DRATE_500   = 0x92,
    ADS1256_DRATE_100   = 0x82,
    ADS1256_DRATE_60    = 0x72,
    ADS1256_DRATE_50    = 0x63,
    ADS1256_DRATE_30    = 0x53,
    ADS1256_DRATE_25    = 0x43,
    ADS1256_DRATE_15    = 0x33,
    ADS1256_DRATE_10    = 0x23,
    ADS1256_DRATE_5     = 0x13,
    ADS1256_DRATE_2_5   = 0x03
} ADS1256_DataRate;

// 输入通道选择
typedef enum {
    ADS1256_AIN0 = 0,
    ADS1256_AIN1,
    ADS1256_AIN2,
    ADS1256_AIN3,
    ADS1256_AIN4,
    ADS1256_AIN5,
    ADS1256_AIN6,
    ADS1256_AIN7,
    ADS1256_AINCOM
} ADS1256_Input;

typedef struct {
    SPI_HandleTypeDef *hspi;
    GPIO_TypeDef *cs_port;
    uint16_t cs_pin;
    GPIO_TypeDef *drdy_port;
    uint16_t drdy_pin;
    GPIO_TypeDef *reset_port;
    uint16_t reset_pin;
    ADS1256_Gain gain;
    ADS1256_DataRate data_rate;
} ADS1256_HandleTypeDef;

// 函数声明
void ADS1256_Init(ADS1256_HandleTypeDef *hadc);
void ADS1256_Reset(ADS1256_HandleTypeDef *hadc);
void ADS1256_WriteReg(ADS1256_HandleTypeDef *hadc, uint8_t reg, uint8_t data);
uint8_t ADS1256_ReadReg(ADS1256_HandleTypeDef *hadc, uint8_t reg);
void ADS1256_SendCommand(ADS1256_HandleTypeDef *hadc, uint8_t cmd);
void ADS1256_WaitDRDY(ADS1256_HandleTypeDef *hadc);
void ADS1256_SetChannel(ADS1256_HandleTypeDef *hadc, ADS1256_Input positive, ADS1256_Input negative);
int32_t ADS1256_ReadData(ADS1256_HandleTypeDef *hadc);
float ADS1256_ReadVoltage(ADS1256_HandleTypeDef *hadc);

#endif // ADS1256_H

四、源文件:

#include "ads1256.h"
#include "stm32l4xx_hal.h"
#include <string.h>

// 私有函数声明
static void ADS1256_CS_Low(ADS1256_HandleTypeDef *hadc);
static void ADS1256_CS_High(ADS1256_HandleTypeDef *hadc);
static void ADS1256_Delay(uint32_t delay);

void ADS1256_Init(ADS1256_HandleTypeDef *hadc) {
    // 硬件复位
    ADS1256_Reset(hadc);
    
    // 等待DRDY变低
    ADS1256_WaitDRDY(hadc);
    
    // 发送同步命令
    ADS1256_SendCommand(hadc, ADS1256_CMD_SYNC);
    ADS1256_Delay(10);
    ADS1256_SendCommand(hadc, ADS1256_CMD_WAKEUP);
    ADS1256_Delay(10);
    
    // 配置寄存器
    uint8_t buf[4];
    
    // 配置MUX寄存器 (AIN0和AINCOM差分输入)
    buf[0] = (ADS1256_AIN0 << 4) | ADS1256_AINCOM;
    ADS1256_WriteReg(hadc, ADS1256_REG_MUX, buf[0]);
    
    // 配置ADCON寄存器 (PGA使能,增益设置)
    buf[1] = (0 << 3) | hadc->gain; // CLKOUT关闭,增益设置
    ADS1256_WriteReg(hadc, ADS1256_REG_ADCON, buf[1]);
    
    // 配置数据速率
    ADS1256_WriteReg(hadc, ADS1256_REG_DRATE, hadc->data_rate);
    
    // 自校准
    ADS1256_SendCommand(hadc, ADS1256_CMD_SELFCAL);
    ADS1256_Delay(100); // 等待校准完成
}

void ADS1256_Reset(ADS1256_HandleTypeDef *hadc) {
    // 拉低复位引脚
    HAL_GPIO_WritePin(hadc->reset_port, hadc->reset_pin, GPIO_PIN_RESET);
    ADS1256_Delay(100);
    
    // 释放复位引脚
    HAL_GPIO_WritePin(hadc->reset_port, hadc->reset_pin, GPIO_PIN_SET);
    ADS1256_Delay(1000); // 等待复位完成
}

void ADS1256_WriteReg(ADS1256_HandleTypeDef *hadc, uint8_t reg, uint8_t data) {
    ADS1256_WaitDRDY(hadc);
    
    ADS1256_CS_Low(hadc);
    
    uint8_t txBuf[2];
    txBuf[0] = ADS1256_CMD_WREG | reg;
    txBuf[1] = 0x00; // 写入1个寄存器
    txBuf[2] = data;
    
    HAL_SPI_Transmit(hadc->hspi, txBuf, 3, HAL_MAX_DELAY);
    
    ADS1256_CS_High(hadc);
}

uint8_t ADS1256_ReadReg(ADS1256_HandleTypeDef *hadc, uint8_t reg) {
    ADS1256_WaitDRDY(hadc);
    
    ADS1256_CS_Low(hadc);
    
    uint8_t txBuf[3] = {0};
    uint8_t rxBuf[3] = {0};
    
    txBuf[0] = ADS1256_CMD_RREG | reg;
    txBuf[1] = 0x00; // 读取1个寄存器
    
    HAL_SPI_TransmitReceive(hadc->hspi, txBuf, rxBuf, 3, HAL_MAX_DELAY);
    
    ADS1256_CS_High(hadc);
    
    return rxBuf[2];
}

void ADS1256_SendCommand(ADS1256_HandleTypeDef *hadc, uint8_t cmd) {
    ADS1256_WaitDRDY(hadc);
    
    ADS1256_CS_Low(hadc);
    HAL_SPI_Transmit(hadc->hspi, &cmd, 1, HAL_MAX_DELAY);
    ADS1256_CS_High(hadc);
}

void ADS1256_WaitDRDY(ADS1256_HandleTypeDef *hadc) {
    while (HAL_GPIO_ReadPin(hadc->drdy_port, hadc->drdy_pin) == GPIO_PIN_SET) {
        // 等待DRDY变低
    }
}

void ADS1256_SetChannel(ADS1256_HandleTypeDef *hadc, ADS1256_Input positive, ADS1256_Input negative) {
    uint8_t mux = (positive << 4) | negative;
    ADS1256_WriteReg(hadc, ADS1256_REG_MUX, mux);
    
    // 发送同步和唤醒命令以应用新设置
    ADS1256_SendCommand(hadc, ADS1256_CMD_SYNC);
    ADS1256_Delay(10);
    ADS1256_SendCommand(hadc, ADS1256_CMD_WAKEUP);
    ADS1256_Delay(10);
}

int32_t ADS1256_ReadData(ADS1256_HandleTypeDef *hadc) {
    ADS1256_WaitDRDY(hadc);
    
    ADS1256_CS_Low(hadc);
    
    uint8_t txBuf[4] = {ADS1256_CMD_RDATA, 0x00, 0x00, 0x00};
    uint8_t rxBuf[4] = {0};
    
    HAL_SPI_TransmitReceive(hadc->hspi, txBuf, rxBuf, 4, HAL_MAX_DELAY);
    
    ADS1256_CS_High(hadc);
    
    // 组合24位数据
    int32_t value = (rxBuf[1] << 16) | (rxBuf[2] << 8) | rxBuf[3];
    
    // 处理符号位扩展
    if (value & 0x00800000) {
        value |= 0xFF000000;
    }
    
    return value;
}

float ADS1256_ReadVoltage(ADS1256_HandleTypeDef *hadc) {
    int32_t raw = ADS1256_ReadData(hadc);
    
    // 计算电压 (假设使用内部2.5V基准)
    float voltage = (raw * 2.5f) / (8388607.0f * (1 << hadc->gain));
    
    return voltage;
}

static void ADS1256_CS_Low(ADS1256_HandleTypeDef *hadc) {
    HAL_GPIO_WritePin(hadc->cs_port, hadc->cs_pin, GPIO_PIN_RESET);
}

static void ADS1256_CS_High(ADS1256_HandleTypeDef *hadc) {
    HAL_GPIO_WritePin(hadc->cs_port, hadc->cs_pin, GPIO_PIN_SET);
}

static void ADS1256_Delay(uint32_t delay) {
    HAL_Delay(delay);
}

五、应用:

#include "stm32l4xx_hal.h"
#include "ads1256.h"

SPI_HandleTypeDef hspi1;
ADS1256_HandleTypeDef hadc1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_SPI1_Init();
    
    // 初始化ADS1256
    hadc1.hspi = &hspi1;
    hadc1.cs_port = GPIOA;
    hadc1.cs_pin = GPIO_PIN_4;
    hadc1.drdy_port = GPIOA;
    hadc1.drdy_pin = GPIO_PIN_3;
    hadc1.reset_port = GPIOA;
    hadc1.reset_pin = GPIO_PIN_2;
    hadc1.gain = ADS1256_GAIN_1;
    hadc1.data_rate = ADS1256_DRATE_100;
    
    ADS1256_Init(&hadc1);
    
    while (1) {
        // 读取AIN0电压
        float voltage = ADS1256_ReadVoltage(&hadc1);
        
        // 可以在此处添加电压处理逻辑
        // 例如发送到串口或进行其他处理
        
        HAL_Delay(100); // 每100ms读取一次
    }
}

void SystemClock_Config(void) {
    // 系统时钟配置代码 (根据具体硬件配置)
}

static void MX_SPI1_Init(void) {
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi1.Init.NSS = SPI_NSS_SOFT;
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi1.Init.CRCPolynomial = 7;
    if (HAL_SPI_Init(&hspi1) != HAL_OK) {
        Error_Handler();
    }
}

static void MX_GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 启用时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    // DRDY引脚配置 (输入)
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // CS引脚配置 (输出)
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 初始高电平
    
    // RESET引脚配置 (输出)
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); // 初始高电平
    
    // SPI引脚配置
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

void Error_Handler(void) {
    while(1) {
        // 错误处理
    }
}

相关文章:

  • 常见的6种外挂获取执行时机方法介绍
  • 安全编排自动化与响应(SOAR):从事件响应到智能编排的技术实践
  • 常见游戏引擎介绍与对比
  • Linux的基础指令
  • Exposure Adjusted Incidence Rate (EAIR) 暴露调整发病率:精准量化疾病风险
  • 关于hbaseRegion和hbaseRowKey的一些处理
  • linux ptrace 图文详解(七) gdb、strace跟踪系统调用
  • Python解析地址中省市区街道
  • Codeforces Round 1020 (Div. 3) A-D
  • 【高频考点精讲】ES6 String的新增方法,处理字符串更方便了
  • Unreal制作角色冲锋时冲击波效果
  • 论文学习:《聚类矩阵正则化指导的层次图池化》
  • 数学基础 -- 欧拉恒等式的魅力:让复数旋转起来!
  • 通信算法之273 : 循环自相关函数和自相关函数
  • LeNet5 神经网络的参数解析和图片尺寸解析
  • uniapp 常用开发技巧与实战指南
  • unity 读取csv
  • 消息队列mq在Mlivus Cloud向量数据库中的关键配置与最佳实践
  • 全面解析 Spring 依赖注入:@Autowired、@Inject 与 @Resource 深度剖析
  • 深入解析 Linux 中动静态库的加载机制:从原理到实践
  • 网络游戏用户规模和市场销售创新高,知识产权保护面临哪些挑战?
  • 价格周报|猪价继续回暖:二次育肥热度仍存,对猪价仍有一定支撑
  • 手机号旧机主信用卡欠款、新机主被催收骚扰四年,光大银行济南分行回应
  • 一周文化讲座|“不一样的社会观察”
  • 特写|“三峡千古情”出圈,一场演出给宜昌留下更多游客
  • “仅退款”将成历史?电商平台集中调整售后规则