一、基础概念解析

  1. ADC(模数转换器)工作原理

    • 核心流程:采样→保持→量化→编码,将连续模拟信号(如电压)离散化为数字量
    • 关键参数:
      • 分辨率:12位(4096级),LSB = VREF+ / 4096
      • 转换时间:最小1μs(ADCCLK=14MHz时)
      • 量化误差:±0.5LSB(固有误差)
  2. DAC(数模转换器)工作原理

    • 通过电阻网络将数字寄存器值转换为模拟电压
    • 输出电压公式:Vout = (DOR / 4095) × Vref
    • 输出缓冲器作用:降低阻抗(禁用可提速但需外接运放)

二、STM32硬件架构与配置
ADC模块

  1. 通道管理
    • 16个外部通道 + 2个内部通道(温度传感器、参考电压)
    • 规则组(16通道)与注入组(4通道,支持打断)
  2. 触发源配置
    • 软件触发:HAL_ADC_Start(&hadc)
    • 定时器触发:闭环控制场景(如TIM2_TRGO)
  3. 抗干扰设计
    • 硬件:RC低通滤波(10kΩ电阻 + 100nF电容)
    • PCB布局:VREF+并联10μF+0.1μF去耦电容

DAC模块

  1. 双通道输出
    • PA4(通道1)、PA5(通道2)
    • 缓冲器使能建议:
      hdac.Instance->CR |= DAC_CR_BOFF1;  // 关闭缓冲提升响应速度 
      
  2. 波形生成模式
    • 三角波/噪声波:内置硬件生成
    • 正弦波:需预计算查表法实现

三、代码实战(基于HAL库)

  1. ADC多通道扫描+DMA传输
    场景:同步采集光照(通道5)和芯片温度(通道18)
// CubeMX配置:ADC1通道5&18,DMA循环模式 
#define ADC_CHANNELS 2 
uint32_t adc_buffer[ADC_CHANNELS];  // 存储转换结果
 
void ADC_Init() {
  hadc.Instance = ADC1;
  hadc.Init.ScanConvMode = ENABLE;        // 扫描模式 
  hadc.Init.ContinuousConvMode = ENABLE;  // 连续转换 
  hadc.Init.DMAContinuousRequests = ENABLE;
  hadc.Init.NbrOfConversion = ADC_CHANNELS;
  HAL_ADC_Init(&hadc);
 
  // 通道配置 
  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_5;      // 光照通道 
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES;
  HAL_ADC_ConfigChannel(&hadc, &sConfig);
 
  sConfig.Channel = ADC_CHANNEL_18;     // 温度传感器 
  sConfig.Rank = 2;
  HAL_ADC_ConfigChannel(&hadc, &sConfig);
 
  // 启动DMA传输 
  HAL_ADC_Start_DMA(&hadc, adc_buffer, ADC_CHANNELS);
}
 
// DMA传输完成中断中处理数据
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
  float light_voltage = (adc_buffer[0] * 3.3f) / 4095;  // 光照电压 
  float temp = ((1.43 - adc_buffer[1]*3.3f/4095) / 0.0043) + 25; // 温度计算
}

关键点:采样时间需根据信号阻抗调整(STM32F1建议55.5~239.5周期)

  1. DAC波形发生器(正弦波输出)
// 预计算256点正弦表(12位分辨率)
uint16_t sin_wave[256];
void Generate_SineTable() {
  for(int i=0; i<256; i++) {
    sin_wave[i] = 2048 + 2047 * sin(2 * M_PI * i / 256); 
  }
}
 
// 定时器触发DAC更新 
void DAC_Start() {
  hdac.Instance = DAC;
  hdac.State = HAL_DAC_STATE_RESET;
  HAL_DAC_Init(&hdac);
 
  DAC_ChannelConfTypeDef sConfig = {0};
  sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;  // TIM6触发 
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
  HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1);
 
  // 启动DAC并绑定正弦表
  HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)sin_wave, 256, DAC_ALIGN_12B_R);
}
 
// TIM6配置(控制输出频率)
void TIM6_Init() {
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 83;       // 84MHz/84 = 1MHz
  htim6.Init.Period = 100;         // 10kHz更新率 → 输出频率=10k/256≈39Hz
  HAL_TIM_Base_Init(&htim6);
  HAL_TIM_Base_Start(&htim6);
}

调试技巧:用示波器观察PA4输出,若波形畸变需使能缓冲器或减小负载


四、综合实战项目
闭环温控系统(ADC+DAC联动)
硬件连接:

ADC通道1
DAC通道1
温度反馈
PT100传感器
STM32
加热器驱动电路
被控物体

PID控制核心代码:

float Kp=0.5, Ki=0.01, Kd=0.1; 
float error_prev=0, integral=0;
 
void PID_Update(float target_temp) {
  float current_temp = Read_Temp();  // 从ADC获取温度
  float error = target_temp - current_temp;
  
  integral += error;
  float derivative = error - error_prev;
  error_prev = error;
  
  float output = Kp*error + Ki*integral + Kd*derivative;
  output = (output > 4095) ? 4095 : (output < 0) ? 0 : output;
  
  HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, (uint32_t)output);
}

五、性能优化与故障排除

问题现象 解决方案 参考依据
ADC数值跳变 增加RC滤波电路,延长采样时间 PCB布局抗干扰
DAC输出带载能力差 使能输出缓冲或外接电压跟随器 负载匹配设计
转换精度不足 启用过采样:4倍采样→分辨率+1位 AN4195手册
多通道数据错位 检查DMA内存地址对齐(右对齐推荐) DMA配置要点

六、扩展应用方向

  1. 音频信号处理
    • ADC采集MIC输入 → FIR滤波 → DAC输出还原
    • 实时性保障:计算耗时需<采样周期(例:44.1kHz需<22.7μs)
  2. 物联网传感器节点
    • 低功耗设计:ADC注入模式唤醒待机设备,采样后返回睡眠
    • 动态电压调节:DAC控制太阳能板MPPT电路
Logo

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

更多推荐