STM32控制AD7685采集方案(基于SPI接口)

STM32控制AD7685采集方案(基于SPI接口)


一、硬件连接与配置

  1. 核心电路设计

    • 信号线连接

      STM32引脚 AD7685引脚 功能说明
      PA5(SCK) SCK SPI时钟线(需上拉)
      PA6(MISO) SD0 数据接收线
      PA4(NSS) CNV 片选/转换信号(主动拉低)
      PA7(MOSI) SD1 未使用(可悬空或接高电平)
    • 电源滤波

      • AD7685的VDD接3.3V,AGND与DGND单点连接
      • 在VDD与GND间添加10μF电解电容+0.1μF陶瓷电容
  2. 关键参数

    • SPI时钟频率:建议≤9MHz(AD7685最大支持40MHz,但STM32 SPI模块需分频)
    • 转换时间:t_CONV≥0.7μs(实际延时≥3.2μs)
    • 数据格式:16位MSB优先,空闲电平低(CPOL=0,CPHA=1)

二、软件实现流程

1. SPI初始化(HAL库)
// SPI1配置(APB2时钟)
void MX_SPI1_Init(void)
{
  SPI_HandleTypeDef hspi1;
  
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;        // 主模式
  hspi1.Init.Direction = SPI_DIRECTION_2LINES; // 全双工
  hspi1.Init.DataSize = SPI_DATASIZE_16BIT;   // 16位数据
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;  // CPOL=0
  hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;      // CPHA=1(下降沿采样)
  hspi1.Init.NSS = SPI_NSS_SOFT;            // 软件控制片选
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; // 72MHz/4=18MHz
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;     // 高位先行
  HAL_SPI_Init(&hspi1);
}

// GPIO初始化(CNV引脚)
void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  
  __HAL_RCC_GPIOA_CLK_ENABLE();
  
  // CNV引脚配置(PA4)
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
2. 数据采集流程
#define CNV_HIGH() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)
#define CNV_LOW()  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)

uint16_t AD7685_Read(void)
{
    uint16_t adc_val = 0;
    
    CNV_LOW();          // 拉低CNV启动转换
    HAL_Delay(4);       // 等待≥3.2μs(实际延时需根据系统时钟调整)
    CNV_HIGH();         // 释放CNV进入数据读取
    
    // 读取16位数据(MSB优先)
    HAL_SPI_Receive(&hspi1, (uint8_t*)&adc_val, 2, 1000);
    
    return adc_val;
}
3. 数据处理与显示
// 电压转换(假设参考电压3.3V)
float AD7685_Voltage(uint16_t raw)
{
    return (raw / 65535.0f * 3.3f);
}

// 主循环
while(1)
{
    uint16_t raw = AD7685_Read();
    float voltage = AD7685_Voltage(raw);
    printf("ADC值:%d, 电压值:%.2fV\n", raw, voltage);
    HAL_Delay(1000);
}

三、关键调试技巧

  1. 时序验证

    • 使用逻辑分析仪捕获CNV与SCK信号,确保:

      • CNV拉低后至少等待3.2μs再拉高
      • SCK时钟频率≤9MHz(通过示波器测量)
  2. 数据校验

    • 空载时读取值应在0x8000附近(1.65V中值)

    • 接入已知电压(如1V),计算实际增益误差:

      float error = (AD7685_Voltage(raw) - 1.0f) / 1.0f * 100%;
      
  3. 抗干扰措施

    • 在SCK/MISO线串联100Ω电阻并并联10pF电容

    • 添加软件数字滤波(滑动平均):

      #define FILTER_SIZE 8
      static uint16_t buffer[FILTER_SIZE] = {0};
      static uint8_t idx = 0;
      
      buffer[idx++] = raw;
      if(idx >= FILTER_SIZE) idx = 0;
      uint32_t sum = 0;
      for(int i=0; i<FILTER_SIZE; i++) sum += buffer[i];
      return sum / FILTER_SIZE;
      

参考代码 STM32控制AD7685采集 www.youwenfan.com/contentcsr/101900.html

四、常见问题解决

现象 可能原因 解决方案
数据跳变 电源噪声/地环路干扰 添加LC滤波,优化PCB地平面
固定值输出 SPI时序错误 检查CPOL/CPHA设置,延长CNV等待时间
通信失败 片选信号未正确控制 确认NSS引脚电平状态,添加延时
负值输出 参考电压未接或漂移 检查REF引脚连接,校准基准电压

五、扩展功能实现

  1. 多通道采集

    • 通过AD7685的通道选择引脚(如CH0-CH7)切换输入通道

    • 示例代码:

      // 切换到CH1(假设CH0接AIN0)
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // CH0选择
      HAL_Delay(1);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
      
  2. DMA传输

    // SPI DMA配置(STM32 HAL库)
    DMA_HandleTypeDef hdma_spi1_rx;
    
    void MX_DMA_Init(void)
    {
      __HAL_RCC_DMA1_CLK_ENABLE();
    
      hdma_spi1_rx.Instance = DMA1_Stream0;
      hdma_spi1_rx.Init.Request = DMA_REQUEST_SPI1_RX;
      hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
      hdma_spi1_rx.Init.DataSize = DMA_DATASIZE_HALFWORD;
      HAL_DMA_Init(&hdma_spi1_rx);
    
      __HAL_LINKDMA(&hspi1, hdmarx, hdma_spi1_rx);
    }
    

 

专注于matlab/simulink,电子电路,编程