1. AD7490与STM32L496ZG的硬件协同设计
AD7490是一款16位、1MSPS的高性能逐次逼近型ADC芯片,而STM32L496ZG则是STMicroelectronics推出的低功耗ARM Cortex-M4微控制器。这两者的组合在工业传感器采集、便携式医疗设备等领域具有广泛应用前景。
1.1 芯片选型依据与性能对比
AD7490的主要技术优势体现在:
- 16位分辨率(STM32内置ADC通常为12位)
- 1MSPS转换速率(STM32L4系列内置ADC最高仅5.33MSPS但精度会下降)
- 真差分输入设计(共模抑制比达90dB)
- 低功耗特性(3V供电时仅5.5mW)
与STM32内置ADC相比,AD7490在以下场景更具优势:
- 需要高精度测量的场合(如电子秤、色谱仪)
- 存在强干扰的工业环境(得益于差分输入)
- 多通道同步采样需求(AD7490支持8通道多路复用)
1.2 硬件接口设计要点
典型连接方案如下图所示(文字描述):
AD7490 STM32L496ZG VDD ----------- 3.3V GND ----------- GND CS ----------- PA4(SPI1_NSS) SCLK ---------- PA5(SPI1_SCK) SDATA --------- PA6(SPI1_MISO) CONVST -------- PB0(定时器触发) BUSY ---------- PC13(EXTI中断) REFIN+ -------- 2.5V基准源 REFIN- -------- GND AIN0+/- ------- 传感器差分输入关键设计注意事项:
- 基准电压源选择:建议使用ADR4525等低噪声基准源,噪声系数需<3μVp-p
- 模拟前端设计:必须配置RC抗混叠滤波器,截止频率按fs/2.5计算(1MSPS时建议400kHz)
- 电源去耦:每个电源引脚需布置0.1μF+1μF MLCC电容,布局时尽量靠近芯片引脚
- 信号走线:模拟信号走线需与数字信号隔离,必要时采用屏蔽层设计
2. STM32L496ZG的ADC接口配置
2.1 SPI接口初始化
AD7490采用SPI兼容接口,STM32L496ZG需配置如下参数:
// SPI1初始化代码示例 void SPI1_Init(void) { __HAL_RCC_SPI1_CLK_ENABLE(); 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; hspi1.Init.CLKPhase = SPI_PHASE_2EDGE; // 数据在第二个边沿采样 hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; // 10MHz @ 80MHz PCLK hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; HAL_SPI_Init(&hspi1); }注意:SPI时钟相位(CLKPhase)必须配置为2EDGE,这与AD7490的时序要求严格匹配。
2.2 定时器触发配置
AD7490的CONVST引脚需要精确的定时触发信号,推荐使用STM32的定时器输出比较功能:
// TIM3初始化示例 - 产生10kHz采样时钟 void TIM3_Init(void) { __HAL_RCC_TIM3_CLK_ENABLE(); htim3.Instance = TIM3; htim3.Init.Prescaler = 80-1; // 1MHz计数频率 htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 100-1; // 10kHz触发频率 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim3); TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 50; // 50%占空比 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); }3. AD7490驱动实现与优化
3.1 基本数据采集流程
AD7490的工作时序包含三个阶段:
- 转换启动:CONVST上升沿启动转换
- 转换过程:BUSY信号变高(典型时间650ns@1MSPS)
- 数据读取:BUSY下降沿后通过SPI读取数据
典型采集代码如下:
uint16_t AD7490_ReadChannel(uint8_t channel) { uint16_t config = (channel << 12) | 0x8000; // 通道选择+WRITE位 uint16_t result; // 启动转换 HAL_GPIO_WritePin(CONVST_GPIO_Port, CONVST_Pin, GPIO_PIN_SET); delay_ns(10); // 至少5ns高电平 HAL_GPIO_WritePin(CONVST_GPIO_Port, CONVST_Pin, GPIO_PIN_RESET); // 等待转换完成 while(HAL_GPIO_ReadPin(BUSY_GPIO_Port, BUSY_Pin) == GPIO_PIN_SET); // 读取数据 HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)&config, (uint8_t*)&result, 1, 100); return result & 0x0FFF; // 取低12位有效数据 }3.2 高速连续采集方案
要实现1MSPS的连续采集,必须采用DMA传输:
- 配置SPI的DMA请求
// DMA1 Stream0配置(SPI1_RX) hdma_spi1_rx.Instance = DMA1_Stream0; hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3; hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_spi1_rx.Init.Mode = DMA_CIRCULAR; // 循环模式 hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(&hdma_spi1_rx); __HAL_LINKDMA(&hspi1, hdmarx, hdma_spi1_rx);- 实现双缓冲采集
#define BUF_SIZE 1024 uint16_t adc_buf1[BUF_SIZE], adc_buf2[BUF_SIZE]; volatile uint8_t active_buf = 0; void Start_Continuous_Acquisition(void) { // 配置定时器触发间隔为1us TIM3->ARR = 80-1; // 1MHz @ 80MHz时钟 // 启动DMA双缓冲 HAL_SPI_Receive_DMA(&hspi1, (uint8_t*)adc_buf1, BUF_SIZE); // 启用定时器触发 HAL_TIM_Base_Start(&htim3); } // DMA传输完成中断回调 void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) { if(active_buf == 0) { // 切换到缓冲区2 HAL_SPI_Receive_DMA(&hspi1, (uint8_t*)adc_buf2, BUF_SIZE); active_buf = 1; Process_ADC_Data(adc_buf1, BUF_SIZE); } else { // 切换到缓冲区1 HAL_SPI_Receive_DMA(&hspi1, (uint8_t*)adc_buf1, BUF_SIZE); active_buf = 0; Process_ADC_Data(adc_buf2, BUF_SIZE); } }4. 系统校准与性能优化
4.1 校准流程实现
高精度ADC系统必须进行定期校准:
- 零点校准:短路所有输入到AGND,记录偏移值
void Calibrate_Offset(void) { uint32_t sum = 0; for(int i=0; i<1000; i++) { sum += AD7490_ReadChannel(0); // 通道0接地 } offset = sum / 1000; }- 满量程校准:施加精确的参考电压(如2.5V)
void Calibrate_Gain(void) { uint32_t sum = 0; for(int i=0; i<1000; i++) { sum += AD7490_ReadChannel(1); // 通道1接2.5V参考 } uint16_t raw = sum / 1000; gain = 2.5f / ((raw - offset) * LSB_SIZE); }- 温度补偿:内置温度传感器监测环境变化
float Apply_Temp_Compensation(uint16_t raw, float temp) { // 使用二阶补偿公式 return (raw - offset) * gain * (1.0 + temp_coeff1*(temp-25.0) + temp_coeff2*(temp-25.0)*(temp-25.0)); }4.2 噪声抑制技巧
实测中发现以下措施可有效提高SNR:
- 电源处理:
- 使用低噪声LDO(如TPS7A4700)
- 在ADC电源引脚增加10Ω电阻+10μF钽电容组合
- 布局优化:
- 模拟和数字地平面单点连接
- 时钟信号远离模拟输入
- 使用四层板时,内层专门布置电源平面
- 软件滤波:
#define FILTER_DEPTH 8 uint16_t Moving_Average_Filter(uint16_t new_sample) { static uint16_t buffer[FILTER_DEPTH]; static uint8_t index = 0; static uint32_t sum = 0; sum = sum - buffer[index] + new_sample; buffer[index] = new_sample; index = (index + 1) % FILTER_DEPTH; return sum / FILTER_DEPTH; }5. 实际应用案例分析
5.1 工业温度监测系统
系统参数要求:
- 8路PT100温度传感器
- 测量范围:-50℃~200℃
- 精度:±0.5℃
- 采样率:100Hz/通道
硬件配置方案:
- 前端电路:
- 采用3线制接法消除引线电阻影响
- 恒流源驱动(0.5mA)
- 仪表放大器INA128进行信号调理
- AD7490配置:
- 差分输入模式
- 内部缓冲器启用
- 采样率设置为100kHz(8通道轮询)
- STM32处理:
- 定时器触发频率800Hz(8通道×100Hz)
- DMA传输至内存环形缓冲区
- 实时RTD温度转换算法
5.2 便携式ECG设备
关键设计考虑:
- 信号特性:
- 幅值范围:0.5-4mV
- 带宽:0.05-150Hz
- 共模干扰可能达数伏
- 模拟前端:
- 三级放大设计(总增益1000倍)
- 右腿驱动电路
- 50Hz陷波器
- AD7490特殊配置:
- 参考电压降至1V(提高小信号分辨率)
- 启用内部数字滤波器(sinc3)
- 采用同步采样模式(3通道同步)
- 低功耗优化:
- 动态调整采样率(休息时250Hz,运动时500Hz)
- 利用STM32L4的停止模式
- 数据压缩算法减少无线传输量
在开发过程中,我们发现AD7490的输入阻抗(约1MΩ)在某些高阻抗传感器应用中可能不足,此时需要增加电压跟随器。另外,当使用内部参考电压时,上电后需要至少10ms稳定时间,这个细节在最初设计时容易被忽略导致启动阶段数据异常。