这个芯片搞起来确实麻烦,主要是时序理解和各种注意事项,100多页的手册坑很多,官方的驱动理解起来困难,适配自己的工程很麻烦,如果第一次搞这个芯片,全按手册一点点开发不知道得猴年马月;网上搜了很多资料,总体来说很杂乱,我也是找了很多资料,最后可算是跑起来了。

我使用的是STM32L431RCT6,主频5.5296MHz,使用LL库。

比较重要的几个引脚:

CS     ------  PA15 (手动控制)
    START/SYNC ------  PB6
    SCLK   ------  PB3/SPI3_SCK
    DIN    ------  PB5/SPI3_MOSI
    DOUT   ------  PB4/SPI3_MISO
    DRDY   ------  PD2(很重要)

我使用命令读取数据格式,也就是发一次命令读取返回一次

当前读取流程

SPI全双工通信(发送与接收同时进行)

CS拉低 → 发送5字节 → 同时接收5字节 → CS拉高

具体时序:

发送(MOSI):

  1. 0x12 = RDATA命令(读取转换数据)
  1. 0x00 = 第一个NOP(用于时钟输出MSB)
  1. 0x00 = 第二个NOP(用于时钟输出中间字节)
  1. 0x00 = 第三个NOP(用于时钟输出LSB)
  1. 0x00 = 第四个NOP(用于完成传输,强制拉高DOUT)

同时接收(MISO):

  1. 0x00 = RDATA命令的响应(STATUS禁用时为0)
  1. 0x00 = 24位数据的MSB(高位字节)
  1. 0x26 = 24位数据的中间字节
  1. 0x72 = 24位数据的LSB(低位字节)
  1. 0x00 = 最后一个NOP的响应

 SEGGER_RTT_printf打印效果:

ADS124S06.C

 
#include "ads124s06.h"
#include "main.h"
#include "spi.h"
/*
	ADS124S06模块 - STM32L431RCT6 SPI3配置:
    模拟电源
	AVDD   ------  AVCC_3V3
	AVSS   ------  AGND
    数字电源
    DVDD   ------  VDD_3V3
	DGND   ------  DGND
	CS     ------  PA15 (手动控制)
    START/SYNC ------  PB6
	SCLK   ------  PB3/SPI3_SCK
	DIN    ------  PB5/SPI3_MOSI
	DOUT   ------  PB4/SPI3_MISO
    DRDY   ------  PD2
    RST    ------  PC12
	ADS124S06基本特性:
	1、模拟电源:单极(2.7V 到 5.25V)或双极 (±2.5V)
       数字电源:2.7V 到 3.6V
	2、参考电压2.5V,使用内部参考
	SCLK下降沿写入数据, 每次传送24bit数据, 高位先传
    转换或寄存器数据在 SCLK 上升沿通过 DOUT/DRDY 移出
*/
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_WriteCmd
*	功能说明: 写命令,命令是独立的,即单字节
*	形    参: Cmd:写入ADS的命令
*	返 回 值: 无
**********************************************************************************************************/
void ADS124S08_WriteCmd(uint8_t Cmd)
{
    // 确保SPI3已使能
    if (!LL_SPI_IsEnabled(SPI3)) {
        LL_SPI_Enable(SPI3);
    }
    
    AD_nCS_LOW;		//拉低片选线,使能SPI通信
    for (volatile uint32_t d = 0; d < 10; d++) { __NOP(); }  // 短暂延时
 
    // 等待TXE就绪并发送数据
    while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
    LL_SPI_TransmitData8(SPI3, Cmd);
    // 等待RXNE并读取(必须读取才能清空RXFIFO)
    while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
    (void)LL_SPI_ReceiveData8(SPI3);
    // 等待传输完成
    while (LL_SPI_IsActiveFlag_BSY(SPI3)) {}
    
    for (volatile uint32_t d = 0; d < 10; d++) { __NOP(); }  // 短暂延时
    AD_nCS_HIGH;		//通信结束,拉高片选
 
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_ReadReg
*	功能说明: 读单个或多个寄存器
*	形    参: RegAddr:所要读取的寄存器地址
*	         Length:所要读取的寄存器数量
*	返 回 值: 无
**********************************************************************************************************/
void ADS124S08_ReadReg(uint8_t RegAddr,uint8_t *Buffer,uint8_t Length)
{
    uint8_t Cmd[2];     //存放要发送的数据
    uint8_t dummy;
    (void)dummy;  // 消除未使用变量警告
 
    // 确保SPI3已使能
    if (!LL_SPI_IsEnabled(SPI3)) {
        LL_SPI_Enable(SPI3);
    }
    
    AD_nCS_LOW;
    for (volatile uint32_t d = 0; d < 2000; d++) { __NOP(); }  // ~4us延时
    AD_START_HIGH;		//在写寄存器时,需要将START拉高(不让其进入睡眠模式)
    for (volatile uint32_t d = 0; d < 5000; d++) { __NOP(); }  // ~10us延时
 
    Cmd[0]=ADC_CMD_RREG|RegAddr;    //读命令加上寄存器地址
    Cmd[1]=Length-1;                //读寄存器数量减一
 
    // 发送读命令
    while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
    LL_SPI_TransmitData8(SPI3, Cmd[0]);
    while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
    dummy = LL_SPI_ReceiveData8(SPI3);
    
    // 发送寄存器数量
    while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
    LL_SPI_TransmitData8(SPI3, Cmd[1]);
    while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
    dummy = LL_SPI_ReceiveData8(SPI3);
 
    // 接收寄存器数据
    for (uint8_t i = 0; i < Length; i++) {
        while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
        LL_SPI_TransmitData8(SPI3, ADC_CMD_NOP);  // 发送NOP获取数据
        while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
        Buffer[i] = LL_SPI_ReceiveData8(SPI3);
    }
    
    // 最后发送一个NOP,强制拉高DOUT
    while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
    LL_SPI_TransmitData8(SPI3, ADC_CMD_NOP);
    while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
    dummy = LL_SPI_ReceiveData8(SPI3);
    
    while (LL_SPI_IsActiveFlag_BSY(SPI3)) {}
    for (volatile uint32_t d = 0; d < 5000; d++) { __NOP(); }  // ~10us延时
 
    AD_nCS_HIGH;
 
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_WriteReg
*	功能说明: 写寄存器
*	形    参: RegAddr:所要写的寄存器地址
*	         Length:所要写的寄存器数量
*	返 回 值: 无
**********************************************************************************************************/
void ADS124S08_WriteReg(uint8_t RegAddr,uint8_t *Buffer,uint8_t Length)
{
    uint8_t Cmd[2];
    uint8_t dummy;
    (void)dummy;  // 消除未使用变量警告
 
    // 确保SPI3已使能
    if (!LL_SPI_IsEnabled(SPI3)) {
        LL_SPI_Enable(SPI3);
    }
    
    AD_nCS_LOW;
    for (volatile uint32_t d = 0; d < 2500; d++) { __NOP(); }  // ~5us延时
    AD_START_HIGH;		//在写寄存器时,需要将START拉高(不让其进入睡眠模式),使器件开始转换
    for (volatile uint32_t d = 0; d < 5000; d++) { __NOP(); }  // ~10us延时
 
    Cmd[0]=ADC_CMD_WREG|RegAddr;
    Cmd[1]=Length-1;
 
    // 发送写命令
    while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
    LL_SPI_TransmitData8(SPI3, Cmd[0]);
    while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
    dummy = LL_SPI_ReceiveData8(SPI3);
    
    // 发送寄存器数量
    while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
    LL_SPI_TransmitData8(SPI3, Cmd[1]);
    while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
    dummy = LL_SPI_ReceiveData8(SPI3);
    
    // 发送数据字节
    for (uint8_t i = 0; i < Length; i++) {
        while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
        LL_SPI_TransmitData8(SPI3, Buffer[i]);
        while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
        dummy = LL_SPI_ReceiveData8(SPI3);
    }
    
    while (LL_SPI_IsActiveFlag_BSY(SPI3)) {}
    for (volatile uint32_t d = 0; d < 5000; d++) { __NOP(); }  // ~10us延时
 
    AD_nCS_HIGH;
    AD_START_LOW;
 
}
/**********************************************************************************************************
*	函 数 名: ADS124S08_WaitBusy
*	功能说明: 判断忙状态(等待DRDY变为低电平)
*	形    参: Timeout:超时时间 单位ms
*	返 回 值: 1:处于忙状态并超时
*            0:处于空闲状态(数据就绪)
**********************************************************************************************************/
uint8_t ADS124S08_WaitBusy(uint32_t Timeout)
{
    uint32_t i = 0;
    // DRDY低电平表示数据就绪,高电平表示忙
    while(nAD_DRDY_STATE != 0)  // 等待DRDY变为低电平
    {
        for (volatile uint32_t d = 0; d < 500; d++) { __NOP(); }  // ~1ms延时
        i++;
        if(i > Timeout)
            return 1;
 
    }
 
    return 0;
 
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_Reset
*	功能说明: 复位ADS124S06,通过引脚复位,重置数字滤波器并将所有配置寄存器值设置为默认设置,还将设备置于待机模式。
*	         通过将 RESET 引脚置于低电平至少 4·tCLK·周期(约1ns),然后将引脚返回高电平来复位 ADC。
*	形    参: 无
*	返 回 值: 无
**********************************************************************************************************/
void ADS124S08_Reset()
{
    LL_GPIO_ResetOutputPin(AD_nRST_GPIO_Port, AD_nRST_Pin);
    for (volatile uint32_t d = 0; d < 100; d++) { __NOP(); }  // 最小4tCLK
    LL_GPIO_SetOutputPin(AD_nRST_GPIO_Port, AD_nRST_Pin);
    for (volatile uint32_t d = 0; d < 2000; d++) { __NOP(); }  // 最小4096tCLK,等待复位完成
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_Chg_Channel
*	功能说明: ADS124S06输入通道选择(AIN0/AIN1)
*	形    参: channel:输入组数:0-5组(0对应AIN0/AIN1)
*	返 回 值: 无
**********************************************************************************************************/
void ADS124S08_Chg_Channel(uint8_t channel)
{
    uint8_t Cmd;
    switch (channel)
    {
        case 0:
            Cmd = (POSI_AIN(0)|NEGA_AIN(1));  // AIN0正极,AIN1负极
            ADS124S08_WriteReg(ADC_REG_INPMUX,&Cmd,1);
            break;
        case 1:
            Cmd = (POSI_AIN(2)|NEGA_AIN(3));
            ADS124S08_WriteReg(ADC_REG_INPMUX,&Cmd,1);
            break;
        case 2:
            Cmd = (POSI_AIN(4)|NEGA_AIN(5));
            ADS124S08_WriteReg(ADC_REG_INPMUX,&Cmd,1);
            break;
        case 3:
            Cmd = (POSI_AIN(6)|NEGA_AIN(7));
            ADS124S08_WriteReg(ADC_REG_INPMUX,&Cmd,1);
            break;
        case 4:
            Cmd = (POSI_AIN(8)|NEGA_AIN(9));
            ADS124S08_WriteReg(ADC_REG_INPMUX,&Cmd,1);
            break;
        case 5:
            Cmd = (POSI_AIN(10)|NEGA_AIN(11));
            ADS124S08_WriteReg(ADC_REG_INPMUX,&Cmd,1);
            break;
        default:break;
    }
 
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_Calibrate
*	功能说明: ADS124S08系统校准  校准顺序为:自偏移校准->偏移校准->增益校准
*	        校准命令不能在设备处于待机模式时使用(当START/SYNC引脚低,或当停止命令发出时)。
*	形    参: 无
*	返 回 值: 无
*	注:此函数为静态函数,当前未使用,保留以备将来校准功能使用
**********************************************************************************************************/
__attribute__((unused)) static uint8_t ADS124S08_Calibrate(uint8_t Gain)
{
    uint8_t R=0;
    uint8_t Cmd;
//    ADS124S08_WriteReg(ADC_REG_PGA,&Gain,1);      // 设置增益值、ADC输出数据率
 
    Cmd=0x10;  	//采样8次,失能CRC和STATUS byte
    ADS124S08_WriteReg(ADC_REG_SYS,&Cmd,1);       // 设置系统监测为自偏移测量
    ADS124S08_WriteCmd(ADC_CMD_SELFOCAL);          // 自偏移校准
    R |= ADS124S08_WaitBusy(500);    							 // 等待校准完成
 
 
//		Cmd=0x21;   //001 00 001
//		ADS124S08_WriteReg(ADC_REG_SYS,&Cmd,1);       // 设置系统监测为偏移测量
//		ADS124S08_WriteCmd(ADC_CMD_SYSOCAL);           // 系统偏移校准
//		R |= ADS124S08_WaitBusy(500);   						  // 等待校准完成
//
//
//		Cmd=0x22;   //001 00 010
//		ADS124S08_WriteReg(ADC_REG_SYS,&Cmd,1);       // 设置系统监测为增益测量
//		ADS124S08_WriteCmd(ADC_CMD_SYSGCAL);           // 系统增益校准
//		R |= ADS124S08_WaitBusy(500);    							 // 等待校准完成
 
    return R;
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_Init
*	功能说明: ADS124S08初始化包括校准
*	形    参: 无
*	返 回 值: 无
**********************************************************************************************************/
void ADS124S08_Init(void)
{
    uint8_t status;
    uint8_t Cmd;
    uint8_t Gain;               //PGA增益
 
    ADS124S08_Reset();  		//系统复位
 
    // 等待复位完成
    for (volatile uint32_t d = 0; d < 50000; d++) { __NOP(); }  // ~100ms延时等待复位稳定
    
    ADS124S08_ReadReg( ADC_REG_STATUS, &status, 1);
    // 检查POR标志位和nRDY位
    if ( (status & ADS_FL_POR_MASK) ) {
        // POR标志位已设置,清除它
        Cmd = status & ~ADS_FL_POR_MASK;  // 清除POR标志位
        ADS124S08_WriteReg(ADC_REG_STATUS, &Cmd, 1);
    }
    
    // 等待设备就绪(nRDY = 0表示就绪)
    uint32_t timeout = 0;
    do {
        ADS124S08_ReadReg( ADC_REG_STATUS, &status, 1);
        timeout++;
        if(timeout > 1000) {
            // 超时,设备可能未就绪
            return;
        }
        for (volatile uint32_t d = 0; d < 500; d++) { __NOP(); }  // 短暂延时
    } while ( (status & ADS_nRDY_MASK) != 0 );  // 等待nRDY变为0(就绪)
 
    //初始化输入多路复用器寄存器,选择AIN0/AIN1差分输入
    Cmd = (POSI_AIN(0)|NEGA_AIN(1));  // AIN0正极,AIN1负极
    ADS124S08_WriteReg(ADC_REG_INPMUX,&Cmd,1);
 
    //设置增益值、ADC输出数据率
    // PGA寄存器:低3位设置增益,bit 3可能控制PGA使能
    // 0x00 = 增益1 (PGA可能禁用)
    // 0x08可能不是有效的增益值,使用0x00(增益1)
    Gain = ADC_GAIN_1;  // 0x00 = 增益1
    ADS124S08_WriteReg(ADC_REG_PGA,&Gain,1);
 
    Cmd=0x10|ADC_SPS_100 ;//关闭斩波模式,选择内部时钟,单次转换,低延迟滤波,5k采样,50hz有陷波 0X10连续转换
    ADS124S08_WriteReg(ADC_REG_DATARATE,&Cmd,1);
    //校准时Data Rate Register将被重新赋值,因此这里可以不用对其进行赋值
 
    Cmd = 0x3A;    //0011 1010 内部参考始终打开即使在掉电模式下,禁用参考缓冲器
    ADS124S08_WriteReg(ADC_REG_REF,&Cmd,1);
 
    Cmd=0x10;  	//采样8次,失能CRC和STATUS byte 00010000即为默认值
    ADS124S08_WriteReg(ADC_REG_SYS,&Cmd,1);
 
//        Cmd=0x07 ;//0000 0111	设置极大恒流源电流值1500uA(1.5mA)使用 IDAC,则必须打开内部基准电源
//		ADS124S08_WriteReg(ADC_REG_IDACMAG,&Cmd,1);
//
//		Cmd=0x17 ;//0010 0111 选择第一个恒流源输出引脚 (AIN2) 选择第二个电流源输出引脚(AIN7)
//		ADS124S08_WriteReg(ADC_REG_IDACMUX,&Cmd,1);
 
    //上电后,等待电源和参考电压完全稳定后再进行校准
//    Cmd=ADS124S08_Calibrate(Gain);                        // 通道校准.配置转换参数
 
//		Cmd = 0x03;
//		ADS124S08_WriteReg(ADC_REG_GPIODAT,&Cmd,1);
//
//	  Cmd = 0x0f;
//		ADS124S08_WriteReg(ADC_REG_GPIOCON,&Cmd,1);
 
    //重新配置Data Rate Register
/*    Cmd=0x20|ADC_SPS_4000;  //0011 0000 关闭斩波模式,选择内部时钟,单次转换,低延迟滤波,数据转换速率4000
    ADS124S08_WriteReg(ADC_REG_DATARATE,&Cmd,1);*/
 
    AD_START_LOW;     //START/SYNC保持低电平,等待启动命令或上升沿触发转换
 
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_Start
*	功能说明: 启动转换
*	        单次转换模式下完成转换时,器件进入待机模式,单次转换模式下拉低START引脚不会进入待机模式
*	形    参: CovMode: 转换模式(单次/连续)
*	返 回 值: 无
**********************************************************************************************************/
void ADS124S08_Start(uint8_t CovMode)
{
    ADS124S08_WriteCmd(ADC_CMD_WAKEUP);
 
    AD_START_HIGH ;                          //启动ADC转换
    for (volatile uint32_t d = 0; d < 500; d++) { __NOP(); }  // ~1ms延时
    if(CovMode==ADC_MODE_SINGLECOV)
        AD_START_LOW;          				//产生启动脉冲(单次转换模式)
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_Stop
*	功能说明: 停止转换
*	        连续转换模式下发送 STOP 命令(或将 START/SYNC 引脚拉低)时进入待机模式
*	形    参: 无
*	返 回 值: 无
**********************************************************************************************************/
void ADS124S08_Stop()
{
    ADS124S08_WriteCmd(ADC_CMD_STOP);        // 发送STOP命令
    AD_START_LOW;                            //停止转换
    for (volatile uint32_t d = 0; d < 500; d++) { __NOP(); }  // ~1ms延时
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_Read_CMD
*	功能说明: 底层函数:指令读取ADS124S06中转换的24位数据
*	形    参: 无
*	返 回 值: 24位转换数据
**********************************************************************************************************/
int32_t ADS124S08_Read_CMD(void)
{
    uint8_t Cmd[5]={ADC_CMD_RDATA,ADC_CMD_NOP,ADC_CMD_NOP,ADC_CMD_NOP,ADC_CMD_NOP};  //最后一个字节是为了强制拉高nDRDY
    uint8_t Buf[5];
    int32_t  Data = 0;
 
    // 确保SPI3已使能
    if (!LL_SPI_IsEnabled(SPI3)) {
        LL_SPI_Enable(SPI3);
    }
    
    AD_nCS_LOW;
    for (volatile uint32_t d = 0; d < 2500; d++) { __NOP(); }  // ~5us延时
 
    // 发送命令并接收数据
    for (uint8_t i = 0; i < 5; i++) {
        while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
        LL_SPI_TransmitData8(SPI3, Cmd[i]);
        while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
        Buf[i] = LL_SPI_ReceiveData8(SPI3);
    }
    
    while (LL_SPI_IsActiveFlag_BSY(SPI3)) {}
    for (volatile uint32_t d = 0; d < 2500; d++) { __NOP(); }  // ~5us延时
    AD_nCS_HIGH;
 
    //无STATUS和CRC字节数据(STATUS字节已禁用)
    // RDATA命令时序:发送RDATA命令后,数据在后续的NOP传输中返回
    // Buf[0] = RDATA命令响应(通常是0或状态,在STATUS禁用时为0)
    // Buf[1] = 24位数据的MSB(第一个NOP时返回)
    // Buf[2] = 24位数据的中间字节(第二个NOP时返回)
    // Buf[3] = 24位数据的LSB(第三个NOP时返回)
    // ADS124S06返回24位有符号数据,MSB在前
    
    // 调试:打印接收到的所有字节(可选,用于调试)
     SEGGER_RTT_printf(0, "RDATA Rx: %02X %02X %02X %02X %02X\r\n",Buf[0], Buf[1], Buf[2], Buf[3], Buf[4]);
    
    Data = ((int32_t)Buf[1] << 16) | ((int32_t)Buf[2] << 8) | ((int32_t)Buf[3]);
    
    // 符号扩展:如果最高位为1,扩展为32位有符号数
    if (Data & 0x00800000) {
        Data |= 0xFF800000;  // 符号扩展(最高字节填充1)
    }
    
    return Data;
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_Read_DIR
*	功能说明: 底层函数:直接读取ADS124S06中转换的24位数据(需在CS已拉低时调用)
*	形    参: 无
*	返 回 值: 24位转换数据
**********************************************************************************************************/
int32_t ADS124S08_Read_DIR(void)
{
    uint8_t Cmd[3]={ADC_CMD_NOP, ADC_CMD_NOP,ADC_CMD_NOP};
    uint8_t Buf[3];
    int32_t  Data = 0;
 
    // 确保SPI3已使能
    if (!LL_SPI_IsEnabled(SPI3)) {
        LL_SPI_Enable(SPI3);
    }
    
    // SPI全双工:三次空命令对应三次数据
    for (uint8_t i = 0; i < 3; i++) {
        while (!LL_SPI_IsActiveFlag_TXE(SPI3)) {}
        LL_SPI_TransmitData8(SPI3, Cmd[i]);
        while (!LL_SPI_IsActiveFlag_RXNE(SPI3)) {}
        Buf[i] = LL_SPI_ReceiveData8(SPI3);
    }
    
    while (LL_SPI_IsActiveFlag_BSY(SPI3)) {}
    for (volatile uint32_t d = 0; d < 2500; d++) { __NOP(); }  // ~5us延时
    AD_nCS_HIGH;
 
    //无STATUS和CRC字节数据(直接读取模式,Buf[0-2]是24位数据,MSB在前)
    // ADS124S06返回24位有符号数据:Buf[0]=MSB, Buf[1]=中间字节, Buf[2]=LSB
    Data = ((int32_t)Buf[0] << 16) | ((int32_t)Buf[1] << 8) | ((int32_t)Buf[2]);
    
    // 符号扩展:如果最高位为1,扩展为32位有符号数
    if (Data & 0x00800000) {
        Data |= 0xFF800000;  // 符号扩展(最高字节填充1)
    }
    
    return Data;
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_GetADC_CMD
*	功能说明: 指令获取ADS124S06中转换的24位数据
*	形    参: mode: 转换模式(单次/连续)
*	返 回 值: 24位ADC数据
**********************************************************************************************************/
int32_t ADS124S08_GetADC_CMD(uint8_t mode)
{
    int32_t adcVal = 0;
    uint32_t delays = 0;
    
    // 等待DRDY变为低电平(数据就绪),DRDY=0表示数据就绪
    // 在连续转换模式下,等待时间应该根据数据率调整
    while(nAD_DRDY_STATE != 0)  // DRDY高电平表示忙,等待变为低电平
    {
        for (volatile uint32_t d = 0; d < 5000; d++) { __NOP(); }  // ~10ms延时(根据100SPS,转换周期约10ms)
        delays++;
        if(delays > 200) {
            // 超时(约2秒),返回0表示错误
            return 0;
        }
    }
    
    // DRDY已就绪,使用RDATA命令读取数据
    adcVal = ADS124S08_Read_CMD();
    
    // 注意:0是一个有效的ADC值(当输入为0V时),所以不能简单判断为错误
    return adcVal;
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_GetADC_DIR
*	功能说明: 直接获取ADS124S06中转换的24位数据(需DRDY已为低电平)
*	形    参: 无
*	返 回 值: 24位ADC数据
**********************************************************************************************************/
int32_t ADS124S08_GetADC_DIR(void)
{
    int32_t adcVal = 0;
    
    // 检查DRDY是否就绪(低电平表示数据就绪)
    if (nAD_DRDY_STATE == 0)  // DRDY低电平表示数据就绪
    {
        AD_nCS_LOW;
        for (volatile uint32_t d = 0; d < 10; d++) { __NOP(); }  // 短暂延时
        adcVal = ADS124S08_Read_DIR();
    }
    else {
        AD_nCS_HIGH;  // 如果未就绪,确保CS拉高
    }
    
    if(adcVal==0) {
        adcVal = 1;  // 避免返回0(可能表示错误)
    }
    return adcVal;
}
 
/**********************************************************************************************************
*	函 数 名: ADS124S08_GetADC_Vol
*	功能说明: 把从ADC读来的24位有符号数据转换成对应的电压值
*	形    参: adc_data----ADC读出的24位有符号数据(已符号扩展为32位)
*	返 回 值: 电压值(伏特)
*	公式: Voltage = (ADC_Code / 2^23) * VREF / GAIN
*	其中:VREF = 2.5V, GAIN = 当前PGA增益
**********************************************************************************************************/
float ADS124S08_GetADC_Vol(int32_t adc_data)
{
    // ADS124S06: 24位有符号数据,参考电压2.5V,增益根据配置
    // 满量程:±VREF/GAIN = ±2.5V/GAIN
    // 数据范围:-8388608 到 +8388607 (0x800000 到 0x7FFFFF)
    // 电压计算公式:V = (ADC_Code / 8388608) * VREF / GAIN
    
    const float VREF = 2.5f;  // 内部参考电压 2.5V
    const uint8_t GAIN = 1;    // 当前PGA增益(如果PGA被禁用则为1,需要根据实际配置调整)
    
    // 将24位有符号数转换为电压
    // 注意:adc_data已经是32位有符号数(符号已扩展)
    float voltage = ((float)adc_data / 8388608.0f) * VREF / (float)GAIN;
    
    return voltage;
}


ADS124S06.H

//#include <stdio.h>
#include "main.h"
#include "spi.h"
 
#ifndef ADS124S06_H
#define ADS124S06_H
 
#endif //ADS124S06_H
 
//ADS124S08有关定义
//ADS124S08命令码列表
#define ADC_CMD_NOP         0x00            /*!< 空操作   */
#define ADC_CMD_WAKEUP      0x02            /*!< 退出睡眠模式   */
#define ADC_CMD_POWERDN     0x04            /*掉电*/
#define ADC_CMD_RESET       0x06            /*!< 芯片复位   */
#define ADC_CMD_START       0x08            /*开始转换*/
#define ADC_CMD_STOP        0x0A            /*停止转换*/
//校准命令
#define ADC_CMD_SYSOCAL     0x16            /*!< 系统偏移校准   */
#define ADC_CMD_SYSGCAL     0x17            /*!< 系统增益校准   */
#define ADC_CMD_SELFOCAL    0x19            /*!< 系统自校准   */
//数据读命令
#define ADC_CMD_RDATA       0x12            /*!< 单次读取数据   */
//寄存器读写命令
#define ADC_CMD_RREG        0x20            /*!< 读寄存器001 00000后五位存寄存器地址   */
#define ADC_CMD_WREG        0x40            /*!< 写寄存器   */
 
 
 
//ADS124S08寄存器列表
#define ADC_REG_ICID        0x00
/*#define ADC_REG_STATUS      0x01*/
#define ADC_REG_INPMUX      0x02
#define ADC_REG_PGA         0x03
#define ADC_REG_DATARATE    0x04
#define ADC_REG_REF         0x05
#define ADC_REG_IDACMAG     0x06
#define ADC_REG_IDACMUX     0x07
#define ADC_REG_VBIAS       0x08
#define ADC_REG_SYS         0x09
#define ADC_REG_OFC0        0x0A
#define ADC_REG_OFC1        0x0B
#define ADC_REG_OFC2        0x0C
#define ADC_REG_FSC0        0x0D
#define ADC_REG_FSC1        0x0E
#define ADC_REG_FSC2        0x0F
#define ADC_REG_GPIODAT     0x10
#define ADC_REG_GPIOCON     0x11
 
/* ADS124S08 Register 0x1 (STATUS) Definition
 *|  Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
 *------------------------------------------------------------------------------------------------
 *|  FL_POR  |    nRDY   | FL_P_RAILP| FL_P_RAILN| FL_N_RAILP| FL_N_RAILN| FL_REF_L1 | FL_REF_L0 |
 *------------------------------------------------------------------------------------------------
 */
/** STATUS register address */
#define ADC_REG_STATUS         ((uint8_t) 0x01)
 
/** STATUS default (reset) value */
#define STATUS_DEFAULT          ((uint8_t) 0x80)
 
#define ADS_FL_POR_MASK			0x80
#define ADS_nRDY_MASK			0x40
#define ADS_FL_P_RAILP_MASK		0x20
#define ADS_FL_P_RAILN_MASK		0x10
#define ADS_FL_N_RAILP_MASK		0x08
#define ADS_FL_N_RAILN_MASK		0x04
#define ADS_FL_REF_L1_MASK		0x02
#define ADS_FL_REF_L0_MASK		0x10
 
 
 
 
//ADS124S08支持的增益列表
#define ADC_GAIN_1          0x00
#define ADC_GAIN_2          0x01
#define ADC_GAIN_4          0x02
#define ADC_GAIN_8          0x03
#define ADC_GAIN_16         0x04
#define ADC_GAIN_32         0x05
#define ADC_GAIN_64         0x06
#define ADC_GAIN_128        0x07
#define ADC_GAIN_EN         0x08
 
//ADS124S08支持的转换速率列表
#define ADC_SPS_5           0x01
#define ADC_SPS_10          0x02
#define ADC_SPS_16_6        0x03
#define ADC_SPS_20          0x04
#define ADC_SPS_50          0x05
#define ADC_SPS_60          0x06
#define ADC_SPS_100         0x07
#define ADC_SPS_100         0x07
#define ADC_SPS_400         0x09
#define ADC_SPS_1000        0x0b
#define ADC_SPS_2000        0x0c
#define ADC_SPS_4000        0x0d
//x代表AINX
#define POSI_AIN(x)    (x<<4)       //AIN_P PGA正极输入
#define NEGA_AIN(x)    (x)          //AIN_N PGA负极输入
 
//ADS124S08转换模式
#define ADC_MODE_SINGLECOV      0x00        //单次转换
#define ADC_MODE_CONTINUOUS     0x01        //连续转换
 
//Fixed timing delays
#define DELAY_4TCLK   	(uint16_t) (1) // 1usec ~= (4.0 /ADS124S08_FCLK) which is the minimum required low time for RESET or START/SYNC.
 
 
 
 
 
//定义引脚有关宏函数 - STM32L431RCT6 SPI3配置
// CS: PA15, DRDY: PD2, START: PB6, RST: PC12
#define AD_nCS_GPIO_Port    GPIOA
#define AD_nCS_Pin          LL_GPIO_PIN_15
 
#define AD_START_GPIO_Port  GPIOB
#define AD_START_Pin        LL_GPIO_PIN_6
 
#define nAD_DRDY_GPIO_Port  GPIOD
#define nAD_DRDY_Pin        LL_GPIO_PIN_2
 
#define AD_nRST_GPIO_Port   GPIOC
#define AD_nRST_Pin         LL_GPIO_PIN_12
 
#define   AD_nCS_LOW	LL_GPIO_ResetOutputPin(AD_nCS_GPIO_Port, AD_nCS_Pin)
#define   AD_nCS_HIGH	LL_GPIO_SetOutputPin(AD_nCS_GPIO_Port, AD_nCS_Pin)
 
#define   AD_START_LOW	LL_GPIO_ResetOutputPin(AD_START_GPIO_Port, AD_START_Pin)
#define   AD_START_HIGH	LL_GPIO_SetOutputPin(AD_START_GPIO_Port, AD_START_Pin)
 
#define   nAD_DRDY_STATE  LL_GPIO_IsInputPinSet(nAD_DRDY_GPIO_Port, nAD_DRDY_Pin)
 
 
//使用SPI3 (LL库,无需外部变量)
 
 
 
 
 
//函数定义,供主函数调用
//指令读取ADS124S08中的转换数据
int32_t ADS124S08_Read_CMD(void);
int32_t ADS124S08_Read_DIR(void);
 
 
//启动转换
void ADS124S08_Start(uint8_t CovMode);
 
 
//停止转换
void ADS124S08_Stop(void);
 
 
//ADS124S08初始化
void ADS124S08_Init(void);
 
//void ADS124S08_WriteReg(uint8_t RegAddr,uint8_t Data,uint8_t Length);
void ADS124S08_WriteReg(uint8_t RegAddr,uint8_t *Buffer,uint8_t Length);
//读寄存器
void ADS124S08_ReadReg(uint8_t RegAddr,uint8_t *Buffer,uint8_t Length);
 
 
//复位ADS124S08
void ADS124S08_Reset(void);
void ADS124S08_Chg_Channel(uint8_t channel);
 
int32_t ADS124S08_GetADC_CMD(uint8_t mode);
int32_t ADS124S08_GetADC_DIR(void);
 
float ADS124S08_GetADC_Vol(int32_t adc_data);
 
//判断忙状态
uint8_t ADS124S08_WaitBusy(uint32_t Timeout);
 
void ADS124S08_WriteCmd(uint8_t Cmd);


参考资料:https://blog.csdn.net/DVYWUI/article/details/139321838?fromshare=blogdetail&sharetype=blogdetail&sharerId=139321838&sharerefer=PC&sharesource=m0_52011717&sharefrom=from_link

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐