刚做完ADC采集的功能,并成功的运行起来,怕时间太长会忘记,所以写个笔记!

根据项目需求,分别需要采集4路AD的数据,查到ADS1254E有4路通道,而且相比于STM32内部的ADC采集数据也比较精确,所以就拿来用。

一、芯片介绍

ADS1254E是一款24位高精度模数转换器,具有4个差分输入通道,CLK时钟最大为8MHz。

根据时序图

DOUT/DRDY引脚:在DRDY模式下,t4时刻为一个高电平,此期间的t1时刻数据写入寄存器,经过t2拉低、在经过t3拉高之后的下降沿开始变为DOUT模式,所以可以确定DOUT在第二个下降沿触发DOUT模式,DOUT模式下 我们需要采集24位的数据,所以这时我们需要给SCLK个信号,并在高电平时读取DOUT的值,转换为低电平,一次往复输出24次,如果只采集单个通道的话,DOUT/DRDY两个模式的总共用时为tDRDY时间,也就是384 • tOSC=384*8MHz =48ns  ,所以我们要在48ns内操作完成,并进行下一轮的数据写入与读取。当然,可以把CLK连接的晶振降低,这样更好的对数据进行采集与分析。

特别注意通道切换

如果需要切换通道,这里需要等内部器件进行稳定,稳定时间大概为5个转换周期 所以下次采集会延时很多,而不是48ns之后。

接下来根据数据手册进行一下配置:

二、硬件连接

ADS1254E的连接:
CH1+接模拟信号1

CH1-AGND

CH2+接模拟信号2
CH2-AGND

CH3+接模拟信号3
CH3-AGND

CH4+接模拟信号4
CH4-AGND

AVDD接模拟电正极

AGND接模拟电负极

DVDD接数字电正极

DGND接数字电负极

VREF接4.096V稳压

STM32与ADS1254E的连接:

CHSEL0接PE14并设置为输出模式

CHSEL1接PE15并设置为输出模式

SCLK接PA5并设置为输出模式

DOUT/DRDY接PA6设置为外部中断模式

因为该芯片的数据输出模式和数据准备模式为同一个引脚(DOUT/DRDY ),我试过如果用SPI的话,需要来回切换PA6端口模式,比较麻烦,索性直接采用模拟SPI进行通信。

(因为之前打算用SPI1所以这里连接了PA5,PA6,如果后期打算用SPI1进行其它通信的话,这里的连接可以改用其它端口)

芯片的时钟连接:

CLK接8MHz有源晶振,我也试过直接找个STM32的IO输出一个1-8MHz的PWM也可以,可以节省一个晶振。


三、MubeMX程序生成后添加相关代码

HAL_Delay_us函数进行SCLK的稳定,约1us

ADS1254_SelectChannel函数用来通道的切换;

read_ads1254函数用来模拟SPI进行24位的数据采集;并返回ADC数据ADC_data;

#include "ads1254.h"

uint8_t ADC_Channel_Flog=0;

void HAL_Delay_us(uint32_t us) {
    us *= (SystemCoreClock / 1000000) / 5; // 根据主频调整除数(5为经验值)
    while (us--) {
        __NOP();
    }
}


void ADS1254_SelectChannel(uint8_t channel) {
  // 通道映射:0=CH1, 1=CH2, 2=CH3, 3=CH4
  HAL_GPIO_WritePin(SSI_CH0_GPIO_Port, SSI_CH0_Pin, (channel & 0x01) ? GPIO_PIN_SET : GPIO_PIN_RESET);
  HAL_GPIO_WritePin(SSI_CH1_GPIO_Port, SSI_CH1_Pin, (channel & 0x02) ? GPIO_PIN_SET : GPIO_PIN_RESET);

}

int32_t read_ads1254() {
		
		uint32_t ADC_data=0;
    for (uint8_t i = 0; i < 24; i++) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); // SCLK高
				HAL_Delay_us(1);
        ADC_data <<= 1;
        ADC_data |= HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6); // 读取DOUT
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // SCLK低
				HAL_Delay_us(1);
    }
		
    return ADC_data;
}

PA6中断函数,在第二个下降沿之后对数据进行采集,

定义一个uint8_t ADC_Flog=0; 在==2时进行ADC的数据采集。首先在函数调用read_ads1254函数,并把返回的值赋值给adcValues[ADC_Channel_Flog];

然后ADC_Channel_Flog+1,再调用ADS1254_SelectChannel进行通道的切换。


uint32_t adcValues[4] = {0};  // 存储 4 个通道的 ADC 值储存4个通道AD值
void EXTI9_5_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI9_5_IRQn 0 */
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_6) != RESET) {
		
			ADC_Flog++;

		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_6);	
		if(ADC_Flog==2)
		{
				ADC_Flog=0;
				 adcValues[ADC_Channel_Flog] = read_ads1254();
				ADC_Channel_Flog = (ADC_Channel_Flog + 1) & 0x03; 
 	    	ADS1254_SelectChannel(ADC_Channel_Flog);	
		}		

	}
  /* USER CODE END EXTI9_5_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
  /* USER CODE BEGIN EXTI9_5_IRQn 1 */

  /* USER CODE END EXTI9_5_IRQn 1 */
}

这样我们就可以通过adcValues的数组得到4个通道的AD值了,如下:

可以测量模拟电压值对比得到的AD值,

根据公式:
电压值/稳压值*2的23次方=AD值

所以 电压值=AD值 /2的23次方*稳压值
例如:计算adcValues的通道3,值为1450696

1450696/2^23*4.096=0.70834765625

因万用表误差和实际干扰,实测约为0.704

补上单通道采集与多通道采集的周期时间:

四通道切换采集约367us

单通道切换采集约47.9us

总结:

硬件真的是学无止境,而且也要学而时习之,所以写此笔记,以后再用到时可以拿来回忆回忆!

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐