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
性能优化建议
- 使用DMA:对于高速数据采集,可以使用SPI的DMA功能
- 中断模式:使用DRDY引脚的中断功能而不是轮询
- 温度补偿:添加温度传感器并进行温度补偿
- 软件滤波:实现数字滤波算法(如移动平均、卡尔曼滤波)

浙公网安备 33010602011771号