STM32F系列使用SPI驱动ADS1256实现高精度数据采集

STM32F系列微控制器通过SPI接口驱动ADS1256 24位ADC的方案

硬件连接

首先,确保STM32F与ADS1256的正确硬件连接:

STM32F引脚 ADS1256引脚 功能描述
PA5 SCLK SPI时钟
PA6 MISO SPI数据输出
PA7 MOSI SPI数据输入
PA4 CS 片选信号
PB0 DRDY 数据就绪信号
PB1 RESET 复位信号
3.3V DVDD 数字电源
GND DGND 数字地
5V AVDD 模拟电源
GND AGND 模拟地

软件实现

1. 头文件定义 (ads1256.h)

#ifndef __ADS1256_H
#define __ADS1256_H

#include "stm32f1xx_hal.h"
#include "main.h"

// ADS1256寄存器定义
#define REG_STATUS  0x00
#define REG_MUX     0x01
#define REG_ADCON   0x02
#define REG_DRATE   0x03
#define REG_IO      0x04
#define REG_OFC0    0x05
#define REG_OFC1    0x06
#define REG_OFC2    0x07
#define REG_FSC0    0x08
#define REG_FSC1    0x09
#define REG_FSC2    0x0A

// ADS1256命令定义
#define CMD_WAKEUP  0x00    // 结束待机模式
#define CMD_RDATA   0x01    // 读取数据
#define CMD_RDATAC  0x03    // 连续读取数据
#define CMD_SDATAC  0x0F    // 停止连续读取
#define CMD_RREG    0x10    // 读取寄存器
#define CMD_WREG    0x50    // 写入寄存器
#define CMD_SELFCAL 0xF0    // 自校准
#define CMD_SELFOCAL 0xF1   // 偏移量校准
#define CMD_SELFGCAL 0xF2   // 增益校准
#define CMD_SYSOCAL 0xF3    // 系统偏移量校准
#define CMD_SYSGCAL 0xF4    // 系统增益校准
#define CMD_SYNC    0xFC    // 同步
#define CMD_STANDBY 0xFD    // 进入待机模式
#define CMD_RESET   0xFE    // 复位

// 采样率设置
#define DRATE_30000 0xF0    // 30,000SPS
#define DRATE_15000 0xE0    // 15,000SPS
#define DRATE_7500  0xD0    // 7,500SPS
#define DRATE_3750  0xC0    // 3,750SPS
#define DRATE_2000  0xB0    // 2,000SPS
#define DRATE_1000  0xA1    // 1,000SPS
#define DRATE_500   0x92    // 500SPS
#define DRATE_100   0x82    // 100SPS
#define DRATE_60    0x72    // 60SPS
#define DRATE_50    0x63    // 50SPS
#define DRATE_30    0x53    // 30SPS
#define DRATE_25    0x43    // 25SPS
#define DRATE_15    0x33    // 15SPS
#define DRATE_10    0x23    // 10SPS
#define DRATE_5     0x13    // 5SPS
#define DRATE_2_5   0x03    // 2.5SPS

// 增益设置
#define GAIN_1      0x00    // 增益1
#define GAIN_2      0x01    // 增益2
#define GAIN_4      0x02    // 增益4
#define GAIN_8      0x03    // 增益8
#define GAIN_16     0x04    // 增益16
#define GAIN_32     0x05    // 增益32
#define GAIN_64     0x06    // 增益64

// 通道选择
#define AIN0        0x08
#define AIN1        0x18
#define AIN2        0x28
#define AIN3        0x38
#define AIN4        0x48
#define AIN5        0x58
#define AIN6        0x68
#define AIN7        0x78

// 函数声明
void ADS1256_Init(void);
void ADS1256_Reset(void);
void ADS1256_WriteReg(uint8_t reg, uint8_t data);
uint8_t ADS1256_ReadReg(uint8_t reg);
void ADS1256_SendCmd(uint8_t cmd);
void ADS1256_SetChannel(uint8_t channel);
int32_t ADS1256_ReadData(void);
float ADS1256_GetVoltage(int32_t adc_value);
void ADS1256_WaitDRDY(void);

extern SPI_HandleTypeDef hspi1;

#endif

2. 源文件实现 (ads1256.c)

#include "ads1256.h"
#include "stdio.h"

// SPI句柄
extern SPI_HandleTypeDef hspi1;

// GPIO定义
#define ADS1256_CS_PIN     GPIO_PIN_4
#define ADS1256_CS_PORT    GPIOA
#define ADS1256_DRDY_PIN   GPIO_PIN_0
#define ADS1256_DRDY_PORT  GPIOB
#define ADS1256_RST_PIN    GPIO_PIN_1
#define ADS1256_RST_PORT   GPIOB

// CS控制宏
#define ADS1256_CS_LOW()   HAL_GPIO_WritePin(ADS1256_CS_PORT, ADS1256_CS_PIN, GPIO_PIN_RESET)
#define ADS1256_CS_HIGH()  HAL_GPIO_WritePin(ADS1256_CS_PORT, ADS1256_CS_PIN, GPIO_PIN_SET)

// 复位控制宏
#define ADS1256_RST_LOW()  HAL_GPIO_WritePin(ADS1256_RST_PORT, ADS1256_RST_PIN, GPIO_PIN_RESET)
#define ADS1256_RST_HIGH() HAL_GPIO_WritePin(ADS1256_RST_PORT, ADS1256_RST_PIN, GPIO_PIN_SET)

// 等待DRDY信号就绪
void ADS1256_WaitDRDY(void)
{
    while(HAL_GPIO_ReadPin(ADS1256_DRDY_PORT, ADS1256_DRDY_PIN) == GPIO_PIN_SET)
    {
        // 等待DRDY变低
    }
}

// 初始化ADS1256
void ADS1256_Init(void)
{
    // 初始化GPIO
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 配置CS引脚
    GPIO_InitStruct.Pin = ADS1256_CS_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(ADS1256_CS_PORT, &GPIO_InitStruct);
    
    // 配置DRDY引脚
    GPIO_InitStruct.Pin = ADS1256_DRDY_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(ADS1256_DRDY_PORT, &GPIO_InitStruct);
    
    // 配置RST引脚
    GPIO_InitStruct.Pin = ADS1256_RST_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(ADS1256_RST_PORT, &GPIO_InitStruct);
    
    // 拉高CS
    ADS1256_CS_HIGH();
    
    // 硬件复位
    ADS1256_Reset();
    
    // 等待DRDY变低
    ADS1256_WaitDRDY();
    
    // 发送同步命令
    ADS1256_SendCmd(CMD_SYNC);
    HAL_Delay(1);
    ADS1256_SendCmd(CMD_WAKEUP);
    
    // 配置ADS1256寄存器
    // 设置状态寄存器: 自动校准使能
    ADS1256_WriteReg(REG_STATUS, 0x04);
    
    // 设置ADCON寄存器: 增益为1
    ADS1256_WriteReg(REG_ADCON, GAIN_1);
    
    // 设置数据速率: 10SPS
    ADS1256_WriteReg(REG_DRATE, DRATE_10);
    
    // 自校准
    ADS1256_SendCmd(CMD_SELFCAL);
    HAL_Delay(100); // 等待校准完成
    
    printf("ADS1256 initialized successfully.\r\n");
}

// 复位ADS1256
void ADS1256_Reset(void)
{
    ADS1256_RST_LOW();
    HAL_Delay(10);
    ADS1256_RST_HIGH();
    HAL_Delay(10);
    
    // 发送复位命令
    ADS1256_CS_LOW();
    uint8_t cmd = CMD_RESET;
    HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
    HAL_Delay(2); // 等待复位完成
    ADS1256_CS_HIGH();
}

// 写入寄存器
void ADS1256_WriteReg(uint8_t reg, uint8_t data)
{
    ADS1256_WaitDRDY();
    
    ADS1256_CS_LOW();
    
    // 发送写寄存器命令
    uint8_t tx_buf[2];
    tx_buf[0] = CMD_WREG | reg;
    tx_buf[1] = 0x00; // 写入1个寄存器
    
    HAL_SPI_Transmit(&hspi1, tx_buf, 2, 100);
    
    // 发送数据
    HAL_SPI_Transmit(&hspi1, &data, 1, 100);
    
    ADS1256_CS_HIGH();
}

// 读取寄存器
uint8_t ADS1256_ReadReg(uint8_t reg)
{
    ADS1256_WaitDRDY();
    
    ADS1256_CS_LOW();
    
    // 发送读寄存器命令
    uint8_t tx_buf[2];
    tx_buf[0] = CMD_RREG | reg;
    tx_buf[1] = 0x00; // 读取1个寄存器
    
    HAL_SPI_Transmit(&hspi1, tx_buf, 2, 100);
    
    HAL_Delay(1); // 等待t6时间
    
    // 读取数据
    uint8_t data = 0;
    HAL_SPI_Receive(&hspi1, &data, 1, 100);
    
    ADS1256_CS_HIGH();
    
    return data;
}

// 发送命令
void ADS1256_SendCmd(uint8_t cmd)
{
    ADS1256_WaitDRDY();
    
    ADS1256_CS_LOW();
    HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
    ADS1256_CS_HIGH();
}

// 设置通道
void ADS1256_SetChannel(uint8_t channel)
{
    ADS1256_WriteReg(REG_MUX, channel);
    HAL_Delay(1);
}

// 读取ADC数据
int32_t ADS1256_ReadData(void)
{
    ADS1256_WaitDRDY();
    
    ADS1256_CS_LOW();
    
    // 发送读取数据命令
    uint8_t cmd = CMD_RDATA;
    HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
    
    HAL_Delay(1); // 等待t6时间
    
    // 读取3字节数据
    uint8_t rx_buf[3] = {0};
    HAL_SPI_Receive(&hspi1, rx_buf, 3, 100);
    
    ADS1256_CS_HIGH();
    
    // 组合24位数据
    int32_t value = (rx_buf[0] << 16) | (rx_buf[1] << 8) | rx_buf[2];
    
    // 处理负数(24位有符号数转换为32位有符号数)
    if (value & 0x00800000)
    {
        value |= 0xFF000000;
    }
    
    return value;
}

// 将ADC值转换为电压值
float ADS1256_GetVoltage(int32_t adc_value)
{
    // ADS1256参考电压为2.5V,增益为1时,满量程为±2.5V
    // 24位ADC,最大值为2^23-1 = 8388607
    float voltage = (adc_value * 2.5f) / 8388607.0f;
    return voltage;
}

3. 主程序示例 (main.c)

#include "main.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
#include "ads1256.h"
#include "stdio.h"

// 重定向printf到串口
int _write(int fd, char *ptr, int len)
{
    HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, 1000);
    return len;
}

// 系统时钟配置
void SystemClock_Config(void);

int main(void)
{
    // HAL库初始化
    HAL_Init();
    
    // 系统时钟配置
    SystemClock_Config();
    
    // 外设初始化
    MX_GPIO_Init();
    MX_SPI1_Init();
    MX_USART1_UART_Init();
    
    // ADS1256初始化
    ADS1256_Init();
    
    printf("Starting ADS1256 data acquisition...\r\n");
    
    // 设置初始通道
    ADS1256_SetChannel(AIN0 | (AIN1 << 4)); // 差分模式: AIN0正, AIN1负
    
    while (1)
    {
        // 读取ADC数据
        int32_t adc_value = ADS1256_ReadData();
        
        // 转换为电压值
        float voltage = ADS1256_GetVoltage(adc_value);
        
        // 输出结果
        printf("ADC Value: %ld, Voltage: %.6f V\r\n", adc_value, voltage);
        
        // 延时1秒
        HAL_Delay(1000);
        
        // 切换通道示例 (循环切换0-7通道单端输入)
        static uint8_t channel = 0;
        uint8_t mux_config = (channel << 4) | 0x08; // 单端输入配置
        
        ADS1256_SetChannel(mux_config);
        channel = (channel + 1) % 8;
    }
}

// SPI1初始化函数 (由STM32CubeMX生成)
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 = 10;
    if (HAL_SPI_Init(&hspi1) != HAL_OK)
    {
        Error_Handler();
    }
}

4. 多通道扫描示例

// 多通道扫描采集函数
void ADS1256_MultiChannelScan(void)
{
    // 定义8个单端输入通道
    uint8_t channels[8] = {
        AIN0 | 0x08, // AIN0单端
        AIN1 | 0x08, // AIN1单端
        AIN2 | 0x08, // AIN2单端
        AIN3 | 0x08, // AIN3单端
        AIN4 | 0x08, // AIN4单端
        AIN5 | 0x08, // AIN5单端
        AIN6 | 0x08, // AIN6单端
        AIN7 | 0x08  // AIN7单端
    };
    
    float voltages[8] = {0};
    
    while (1)
    {
        // 扫描所有通道
        for (int i = 0; i < 8; i++)
        {
            // 设置通道
            ADS1256_SetChannel(channels[i]);
            
            // 等待转换完成
            HAL_Delay(10);
            
            // 读取数据
            int32_t adc_value = ADS1256_ReadData();
            
            // 转换为电压
            voltages[i] = ADS1256_GetVoltage(adc_value);
        }
        
        // 输出所有通道的电压值
        printf("Channel Voltages:\r\n");
        for (int i = 0; i < 8; i++)
        {
            printf("CH%d: %.6f V\r\n", i, voltages[i]);
        }
        printf("\r\n");
        
        HAL_Delay(1000);
    }
}

5. 高精度采集与滤波

// 高精度采集与滤波函数
float ADS1256_HighPrecisionRead(uint8_t channel, uint8_t num_samples)
{
    // 设置通道
    ADS1256_SetChannel(channel);
    
    int64_t sum = 0;
    
    // 采集多个样本并求平均
    for (int i = 0; i < num_samples; i++)
    {
        int32_t adc_value = ADS1256_ReadData();
        sum += adc_value;
        
        // 短暂延时
        HAL_Delay(1);
    }
    
    // 计算平均值
    int32_t avg_value = sum / num_samples;
    
    // 转换为电压
    return ADS1256_GetVoltage(avg_value);
}

推荐代码 STM32F使用SPI实现ADS1256驱动采集功能 www.3dddown.com/cna/51640.html

性能优化建议

  1. 使用DMA:对于高速数据采集,可以使用SPI的DMA功能
  2. 中断模式:使用DRDY引脚的中断功能而不是轮询
  3. 温度补偿:添加温度传感器并进行温度补偿
  4. 软件滤波:实现数字滤波算法(如移动平均、卡尔曼滤波)
posted @ 2025-12-16 15:39  吴逸杨  阅读(121)  评论(0)    收藏  举报