#include "ADS1256.h" #include "cmsis_os.h" #include "printf.h" /** ****************************************************************************** * @file ADS1256.c ****************************************************************************** * @attention * ADS1256模块 * +5V <------ 5.0V 5V供电 * GND ------- GND 地 * DRDY ------> PA11 准备就绪 低准备好 高未准备好 * CS <------ PB12 SPI_CS 低有效,操作完拉高 * DIN <------ PB15 SPI_MOSI * DOUT ------> PB14 SPI_MISO * SCLK <------ PB13 SPI时钟 * GND ------- GND 地 * PDWN <------ VDD 掉电控制 常高 * RST <------ PA8 复位信号 常高,拉低再拉高生效复位 * * ADS1256基本特性: * 1、模拟部分供电5V; * 2、SPI数字接口电平:3.3V * 3、PGA设置范围: 1、2、4、8、16、32、64、 * 4、参考电压2.5V (推荐缺省的,外置的) * 5、输入电压范围:PGA = 1 时, 可输入正负5V * 6. 自动校准 (当设置了PGA,BUF使能、数据采样率时,会启动自校准) * 7. 输入的缓冲器可设置启用和关闭(一般选启用) * 外部晶振频率 = 7.68MHz, * 时钟频率 tCLK = 1/7.68M = 0.13uS * 输出数据周期 tDATA = 1 / 30K = 0.033mS (按30Ksps计算) * 对SPI的时钟速度要求: (ads1256.pdf page 6) * 最快 4个tCLK = 0.52uS * 最慢 10个tDATA = 0.3mS (按 30Ksps 计算) * SCL高电平和低电平持续时间最小 200ns * RREG, WREG, RDATA 命令之后,需要延迟 4 * tCLK = 0.52uS; * RDATAC, RESET, SYNC 命令之后,需要延迟 24 * tCLK = 3.12uS; * 实际测试,在3.3V上电后, 及时不做任何配置,ADS125的DRDY 口线即开始输出脉冲信号(2.6us高,33.4低,频率30KHz) ****************************************************************************** */ extern SPI_HandleTypeDef ADS1256_SPI_HANDLE; void ADS1256_SendCommand(uint8_t cmd) { // 发送单字节命令给ADS ADS1256_CS_LOW(); for (volatile uint8_t i = 0; i < 5; i++) {} // ≈300~500ns 延迟 HAL_SPI_Transmit(&ADS1256_SPI_HANDLE, &cmd, 1, SPI_TIMEOUT); for (volatile uint8_t i = 0; i < 5; i++) {} // ≈300~500ns 延迟 ADS1256_CS_HIGH(); } void ADS1256_WriteRegister(uint8_t reg, uint8_t value) { uint8_t tx[3] = { ADS1256_CMD_WREG | (reg & 0x0F), 0x00, // 写1个寄存器 value }; ADS1256_CS_LOW(); for (volatile uint8_t i = 0; i < 5; i++) {} HAL_SPI_Transmit(&ADS1256_SPI_HANDLE, tx, 3, SPI_TIMEOUT); for (volatile uint8_t i = 0; i < 5; i++) {} ADS1256_CS_HIGH(); } uint8_t ADS1256_ReadRegister(uint8_t reg) { uint8_t tx[2] = { ADS1256_CMD_RREG | (reg & 0x0F), 0x00 }; uint8_t rx = 0; ADS1256_CS_LOW(); for (volatile uint8_t i = 0; i < 5; i++) {} HAL_SPI_Transmit(&ADS1256_SPI_HANDLE, tx, 2, SPI_TIMEOUT); for (volatile uint8_t i = 0; i < 5; i++) {} // ≈读取前延迟 HAL_SPI_Receive(&ADS1256_SPI_HANDLE, &rx, 1, SPI_TIMEOUT); for (volatile uint8_t i = 0; i < 5; i++) {} ADS1256_CS_HIGH(); return rx; } void ADS1256_Reset(void) { // 复位 ADS1256_RST_LOW(); osDelay(1); ADS1256_RST_HIGH(); osDelay(5); ADS1256_SendCommand(ADS1256_CMD_RESET); // 软件复位 osDelay(5); } void ADS1256_SetChannel(uint8_t mux) { // 设置输入通道(MUX 寄存器值) ADS1256_WriteRegister(ADS1256_REG_MUX, mux); ADS1256_SendCommand(ADS1256_CMD_SYNC); ADS1256_SendCommand(ADS1256_CMD_WAKEUP); } void ADS1256_SetGain(ADS1256_Gain_t gain) { // 设置增益 uint8_t adcon = ADS1256_ReadRegister(ADS1256_REG_ADCON); adcon &= 0xF8; adcon |= (gain & 0x07); ADS1256_WriteRegister(ADS1256_REG_ADCON, adcon); } void ADS1256_SetDataRate(ADS1256_DataRate_t dr) { // 设置采样率 ADS1256_WriteRegister(ADS1256_REG_DRATE, (uint8_t)dr); } void ADS1256_StartConversion(void) { // 启动一次转换 ADS1256_SendCommand(ADS1256_CMD_SYNC); ADS1256_SendCommand(ADS1256_CMD_WAKEUP); ADS1256_SendCommand(ADS1256_CMD_RDATA); } uint8_t ADS1256_ReadID(void) { // 读取芯片 ID(高 4 位) ID高4位应该是0x03 ADS1256_SendCommand(ADS1256_CMD_SYNC); osDelay(1); // 延迟 ≥6us,这里用1ms最保险,兼容RTOS调度延迟 ADS1256_SendCommand(ADS1256_CMD_WAKEUP); for (volatile uint8_t i = 0; i < 5; i++) {} // 补一点 CS 往后延 uint8_t status = ADS1256_ReadRegister(ADS1256_REG_STATUS); return (status >> 4) & 0x0F; } bool ADS1256_ReadData(int32_t* out) { // 读取数据(需判断 DRDY 是否为低) uint8_t rx[3]; if (HAL_GPIO_ReadPin(ADS1256_DRDY_GPIO_PORT, ADS1256_DRDY_PIN) != GPIO_PIN_RESET) { ADS_PRINTF("[ADS1256] DRDY pin not low, skipping read.\r\n"); return false; } ADS1256_CS_LOW(); HAL_SPI_Receive(&ADS1256_SPI_HANDLE, rx, 3, SPI_TIMEOUT); ADS1256_CS_HIGH(); *out = ((int32_t)rx[0] << 16) | ((int32_t)rx[1] << 8) | rx[2]; if (*out & 0x800000) *out |= 0xFF000000; // Sign extend if negative return true; } float ADS1256_ConvertToVoltage(int32_t raw, float vref, int gain) { return ((float)raw / 8388608.0f) * (vref / gain); // V = (raw / 2的23次方 —— 8388608)* (vref / gain) 单位V ,2的22次方= 4194304 } void ADS1256_SetClockSource(uint8_t useInternal) // CLK = 0:使用外部晶振 1:使用内部晶振 { if (useInternal > 1) return; uint8_t status = ADS1256_ReadRegister(ADS1256_REG_STATUS); if (useInternal) status |= (1 << 2); // CLK = 1:使用内部晶振 else status &= ~(1 << 2); // CLK = 0:使用外部晶振 ADS1256_WriteRegister(ADS1256_REG_STATUS, status); } bool ADS1256_IsUsingExternalClock(void) { uint8_t status = ADS1256_ReadRegister(ADS1256_REG_STATUS); return (status & (1 << 3)) != 0; // CLKSTAT } void ADS1256_Init(void) { // 初始化 ADS1256 // ADS1256_Reset(); // osDelay(50); // 默认外部晶振,连续采样模式 HAL_GPIO_WritePin(GPIOB, ADS_SYNC_PDWN_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, ADS_SYNC_PDWN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, ADS_SYNC_PDWN_Pin, GPIO_PIN_SET); ADS1256_SetClockSource(0); // 0使用外部晶振 1内部晶振 ADS1256_WriteRegister(ADS1256_REG_STATUS, 0x06); // 0000 0 110 自动校准开启(ACAL = 1), 输入缓冲器关闭(BUFEN = 0) ADS1256_WriteRegister(ADS1256_REG_ADCON, 0x20); // 时钟输出禁用(CLKOUT = 00), 增益为1倍(输入是几mV,增益增大至8) ADS1256_SetDataRate(ADS1256_DR_1000SPS); // ADS1256_DR_1000SPS ADS1256_SetChannel(ADS1256_MUX_AIN0_AINCOM); // AIN1 - AINCOM ADS1256_SendCommand(ADS1256_CMD_SELFCAL);// 启动自动增益和偏移校准 必须最后执行该指令 ADS1256_SendCommand(ADS1256_CMD_RDATAC); // 连续采样 }