ADS131A04的驱动代码(STM32 HAL库)

发布时间:2026/7/17 6:50:26
ADS131A04的驱动代码(STM32 HAL库) 一、硬件接线这是本项目中ADS131A04的原理图AIN1与AIN2为ADC芯片的模拟输入端AVDD、AVSS等引脚就按照典型应用连接本项目中M2接地、M1通过1k电阻接地、M0接到IOVDD高电平这三个引脚设置了SPI为异步中断模式通信一个命令字为24bit。CLKIN为芯片的工作时钟会影响采集速率与单片机相连用于SPI通信的引脚有CS、SCLK、DOUT、DIN、RADY用于硬件复位的引脚为RESETDONE引脚用于多机通信和同步通信本项目没有用到。可以看出M0、1、2不同的配置会影响命令与数据长度和通信模式二、引脚配置接下来需要配置引脚根据手册中引脚的功能配置单片机对应的IO口输入或输出比如DIN为芯片的输入单片机对应的引脚就要配置为outputDOUT为芯片的输出单片机对应的引脚就应该配置为input一般来说还需要上拉用于消除浮空不稳定状态但是在原理图中已经dout已经经过一个100k电阻上拉到iovdd了因此不需要配置单片机引脚上拉。DRDY为芯片用于通知单片机读取数据的引脚当数据准备好之后就会发出脉冲下降沿触发因此单片机对应引脚需要配置为EXIT下降沿触发。三、时钟设置根据下面三张图我们可以计算输入的时钟频率/晶振频率与ADC转换后的数字量输出频率假设使用默认的寄存器配置fDATAfMOD/400fICLK/8/400fCLKIN/8/8/400假设将CLKIN设为4.23MHz数字量转换的频率为4.23MHz/25600165Hz也就是大约每6ms会在DRDY上产生一个下降沿脉冲通知单片机进行数据接收。因此可以根据输入的时钟频率配置不同的寄存器值得到所需要的AD转换速率。四、启动流程接下来得看一下ADS131A04的启动流程可以看到要启动芯片以一定频率进行自动转换需要输入一系列的命令我们逐步来说明一下。在上电之后芯片会读取M0、1、2口的状态同时会将模拟和数字电源上电。之后你需要复位芯片你可以使用硬件时序进行复位本项目采用的方式或者使用复位指令根据下面两张图在硬件复位的时候你需要将RESET引脚拉低至少800ns然后高电平至少持续4.5ms接着你可以使用SPI协议读取到Ready状态字也就是0xff04五、通讯时序与格式对于SPI协议下面这一张图会解释它的时序简单来说先将CS拉低代表通讯开始接着SCLK控制每一个bit的读入与输出在SCLK上升沿时芯片DOUT锁存器存入新的bit供单片机读取同时单片机将缓存区bit输出至芯片的DIN因此对于外设来说每一个SCLK脉冲完成一个bit的读与写经过一定个数的SCLK上升沿后取决于字长一个字的传输完成最后以CS拉高结束。通过CSSCLKMISOMOSI四根线可以实现高速的双向数据传输前面我们说过硬件复位后可以通过SPI协议的时序读取到Ready状态字0xff04下面我们看看ADC芯片的字和帧是如何构成的我们可以看到一个字根据不同的设置可以是16,24,32bit在本项目中我们设置的是24bit也就是说需要读取一个字需要24个SCKL上升沿而一个帧的数据则是由多个字组成的。下面是ADC芯片的SPI命令字它们都是16bit的可以看到在启动流程中的所有命令都在下面用十六进制数写明了对应的还有每一个命令字的回复我们看一看Ready命令的回复是0xFFdd其中dd是设备型号ADS131A04对应的回复就是0xFF04这就是启动流程中所说的那个准备完成状态字。命令字的发送和接收相对简单对于读写寄存器操作需要增加一些前缀比如说RREG指令001a aaaa nnnn nnnnb它是以001开头其中a为寄存器地址范围是00h~14hn在读单个寄存器时为0在读多个寄存器值为需要读的寄存器数n再减1。而WREG010a aaaa nnnn nnnnb则需要以010开头a同样代表寄存器地址d代表需要写入到对应寄存器的8bit数据。还记得前面我们说过本次采用的是24bit字长可是命令字都是16位的这16位命令字在24bit字长的命令中如何分布呢可以看看下面这一张图应该说总的字长32bit如果采用24bit有效字长那么高位填0中间为16bit有效命令最右边8bit为汉明码实际上我们没有使用汉明码所以也填0。所以前面所说的0xff04在24bit字长模式下应该为0x00ff0400对应的UNLOCK命令为0x0655也就是0x00065500。这一点希望大家注意还有一点重要的是ADC芯片的响应是跨帧匹配的也就是说在SPI发送命令时接收到的数据不是当前命令的回应当前命令的回应会在下一次的读取中收到仔细看看下面的时序注意图中的箭头发送的UNLOCK命令对应着ACK在下一个帧才回复。对于这种方式如果想要收到UNLOCK命令的ACK只要在UNLOCK后发送一条NULL0x00命令即可此时读到的数据就是对应上一条的UNLOCK六、启动代码最后根据我们上面所说的一些原理编写stm32的启动代码按照流程启动后在DRDY上会出现周期性的脉冲用于通知单片机接收AD转换的结果代码附在下方根据自己的硬件接线配置一下SPI引脚就可以使用。ads131a04.c#include ads131a04.h static void delay_us(uint32_t us) { uint32_t cnt us * (SystemCoreClock / 1000000) / 12; while(cnt--); } // 功能发送 24bit 数据同时读取 24bit 响应 // 输入cmd16 16bit 命令函数内部自动左移8位变成 0x00XXYY00 格式 // 输出芯片返回的 24bit 数据格式0x00FFFFFF uint32_t resp 0; // 保存接收的24bit数据 uint32_t ADS_Send24Bit(uint16_t cmd16) { // 关键把16bit命令 → 左移8位 → 变成 24bit 格式 0x00XXYY00 // 完全匹配你说的 UNLOCK 0x00065500 格式 uint32_t cmd24 ((uint32_t)cmd16 8) 0x00FFFFFF; // CS拉低开始通信 HAL_GPIO_WritePin(ADS_CS_GPIO_Port, ADS_CS_Pin, GPIO_PIN_RESET); // 严格收发 24bit 一位发一位收同步进行 for(uint8_t i 0; i 24; i) { // 1. 输出当前最高位到 DIN if(cmd24 0x00800000) HAL_GPIO_WritePin(ADS_DIN_GPIO_Port, ADS_DIN_Pin, GPIO_PIN_SET); else HAL_GPIO_WritePin(ADS_DIN_GPIO_Port, ADS_DIN_Pin, GPIO_PIN_RESET); // 数据左移准备下一位 cmd24 1; // 2. SCLK 上升沿芯片锁存 DIN HAL_GPIO_WritePin(ADS_SCLK_GPIO_Port, ADS_SCLK_Pin, GPIO_PIN_SET); delay_us(1); // 3. 同时读取 DOUT 一位SPI标准同步收发 resp 1; if(HAL_GPIO_ReadPin(ADS_DOUT_GPIO_Port, ADS_DOUT_Pin) GPIO_PIN_SET) resp | 0x01; // 4. SCLK 下降沿 HAL_GPIO_WritePin(ADS_SCLK_GPIO_Port, ADS_SCLK_Pin, GPIO_PIN_RESET); delay_us(1); } // CS拉高结束 HAL_GPIO_WritePin(ADS_CS_GPIO_Port, ADS_CS_Pin, GPIO_PIN_SET); // 返回接收的24bit数据格式 0x00FFFFFF return resp 0x00FFFFFF; } // 24bit 读取 uint32_t ADS_Read24Bit(void) { uint32_t data 0; HAL_GPIO_WritePin(ADS_CS_GPIO_Port, ADS_CS_Pin, GPIO_PIN_RESET); for(uint8_t i0; i24; i) { data 1; HAL_GPIO_WritePin(ADS_SCLK_GPIO_Port, ADS_SCLK_Pin, GPIO_PIN_SET); delay_us(1); if(HAL_GPIO_ReadPin(ADS_DOUT_GPIO_Port, ADS_DOUT_Pin)) data | 1; HAL_GPIO_WritePin(ADS_SCLK_GPIO_Port, ADS_SCLK_Pin, GPIO_PIN_RESET); delay_us(1); } HAL_GPIO_WritePin(ADS_CS_GPIO_Port, ADS_CS_Pin, GPIO_PIN_SET); return data; } // 读单个寄存器RREG uint8_t ADS131A04_ReadReg(uint8_t addr) { // 指令格式(001a aaaa nnnn nnnn)b 读单个寄存器n0 uint16_t cmd 0x2000 | ((addr 0x1F) 8); uint32_t resp ADS_Send24Bit(cmd); return (resp 8) 0xFF; } // 写单个寄存器WREG void ADS131A04_WriteReg(uint8_t addr, uint8_t data) { // 指令格式(010a aaaa dddd dddd)b uint16_t cmd 0x4000 | ((addr 0x1F) 8) | data; ADS_Send24Bit(cmd); } // 读取数据帧 void ADS131A04_ReadDataFrame(uint8_t *buf) { HAL_GPIO_WritePin(ADS_CS_GPIO_Port, ADS_CS_Pin, GPIO_PIN_RESET); for(uint8_t i0; i13; i) { uint8_t d 0; for(uint8_t j0; j8; j) { d 1; HAL_GPIO_WritePin(ADS_SCLK_GPIO_Port, ADS_SCLK_Pin, GPIO_PIN_SET); delay_us(1); if(HAL_GPIO_ReadPin(ADS_DOUT_GPIO_Port, ADS_DOUT_Pin)) d | 1; HAL_GPIO_WritePin(ADS_SCLK_GPIO_Port, ADS_SCLK_Pin, GPIO_PIN_RESET); delay_us(1); } buf[i] d; } HAL_GPIO_WritePin(ADS_CS_GPIO_Port, ADS_CS_Pin, GPIO_PIN_SET); } uint32_t ready_copy0; // 初始化100% 正确时序 void ADS131A04_Init(void) { // 初始电平 HAL_GPIO_WritePin(ADS_CS_GPIO_Port, ADS_CS_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(ADS_SCLK_GPIO_Port, ADS_SCLK_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(ADS_RST_GPIO_Port, ADS_RST_Pin, GPIO_PIN_SET); delay_us(10); // 硬件复位 HAL_GPIO_WritePin(ADS_RST_GPIO_Port, ADS_RST_Pin, GPIO_PIN_RESET); delay_us(2); HAL_GPIO_WritePin(ADS_RST_GPIO_Port, ADS_RST_Pin, GPIO_PIN_SET); // 等待复位完成 t_d(RSSC) delay_us(7000); for(int i0;i2;i) { // 读取 READY 状态字 uint32_t ready ADS_Read24Bit(); ready_copyready; } if((ready_copy 0x00FFFF00) ! ((uint32_t)READY_RESPONSE 8)) return; // 1. 读READYUNLOCK ADS_Send24Bit(UNLOCK_CMD); ADS_Send24Bit(0x00); //跨帧应答用null指令得到上次的回复 // 2. 配置系统寄存器 ADS131A04_WriteReg(ADS_A_SYS_CFG, 0x60); // 模拟系统配置 ADS_Send24Bit(0x00); ADS131A04_WriteReg(ADS_D_SYS_CFG, 0x3C); // 数字系统配置 ADS_Send24Bit(0x00); ADS131A04_WriteReg(ADS_CLK2, 0x86); // 时钟/过采样率配置 ADS_Send24Bit(0x00); // 3. 使能ADC通道流程图要求 ADS131A04_WriteReg(ADS_ADC_ENA, 0x0F); ADS_Send24Bit(0x00); ADS131A04_ReadReg(ADS_ADC_ENA); ADS_Send24Bit(0x00); // 4. 启动转换 锁定寄存器 ADS_Send24Bit(WAKEUP_CMD); ADS_Send24Bit(0x00); ADS_Send24Bit(LOCK_CMD); ADS_Send24Bit(0x00); }ads131a04.h#ifndef __ADS131A04_H #define __ADS131A04_H #include stm32f1xx_hal.h // 引脚定义 #define ADS_DOUT_Pin GPIO_PIN_5 #define ADS_DOUT_GPIO_Port GPIOA #define ADS_CS_Pin GPIO_PIN_6 #define ADS_CS_GPIO_Port GPIOA #define ADS_DIN_Pin GPIO_PIN_7 #define ADS_DIN_GPIO_Port GPIOA #define ADS_SCLK_Pin GPIO_PIN_11 #define ADS_SCLK_GPIO_Port GPIOB #define ADS_RST_Pin GPIO_PIN_10 #define ADS_RST_GPIO_Port GPIOB // 系统命令 #define NULL_CMD 0x0000 #define RESET_CMD 0x0011 #define STANDBY_CMD 0x0022 #define WAKEUP_CMD 0x0033 #define LOCK_CMD 0x0555 #define UNLOCK_CMD 0x0655 // 响应 #define READY_RESPONSE 0xFF04 // 寄存器命令前缀 #define RREG_CMD_PREFIX 0x20 #define WREG_CMD_PREFIX 0x40 // 官方正确寄存器地址100% 匹配你发的手册 #define ADS_CONFIG1 0x01 // 配置1 #define ADS_CLK2 0x0E // 时钟配置2OSR配置 #define ADS_A_SYS_CFG 0x0B // 模拟系统配置 #define ADS_D_SYS_CFG 0x0C // 数字系统配置Fixed/CRC帧格式 #define ADS_ADC_ENA 0x0F // ADC通道使能写0x0F // 函数声明 void ADS131A04_Init(void); uint32_t ADS_Send24Bit(uint16_t cmd16); uint32_t ADS_Read24Bit(void); uint8_t ADS131A04_ReadReg(uint8_t addr); void ADS131A04_WriteReg(uint8_t addr, uint8_t data); void ADS131A04_ReadDataFrame(uint8_t *buf); #endif接收ADC信息代码在外部中断回调函数里面调用void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin GPIO_PIN_1) { uint8_t buf[13]; ADS131A04_ReadDataFrame(buf); } }