STM32学习笔记: ADC与DAC开发实战指南
本文详细介绍了STM32中的ADC和DAC模块应用。首先解析了ADC(采样-保持-量化-编码)和DAC(电阻网络转换)的工作原理及关键参数,包括分辨率、转换时间和量化误差。其次阐述了STM32硬件架构配置要点,如ADC的通道管理、触发源设计,以及DAC的波形生成模式。核心部分通过代码实例展示了ADC多通道扫描+DMA传输的实现,以及DAC正弦波发生器的开发方法。最后提出一个闭环温控系统综合案例,并
·
一、基础概念解析
-
ADC(模数转换器)工作原理
- 核心流程:采样→保持→量化→编码,将连续模拟信号(如电压)离散化为数字量
- 关键参数:
- 分辨率:12位(4096级),LSB = VREF+ / 4096
- 转换时间:最小1μs(ADCCLK=14MHz时)
- 量化误差:±0.5LSB(固有误差)
-
DAC(数模转换器)工作原理
- 通过电阻网络将数字寄存器值转换为模拟电压
- 输出电压公式:
Vout = (DOR / 4095) × Vref - 输出缓冲器作用:降低阻抗(禁用可提速但需外接运放)
二、STM32硬件架构与配置
ADC模块
- 通道管理
- 16个外部通道 + 2个内部通道(温度传感器、参考电压)
- 规则组(16通道)与注入组(4通道,支持打断)
- 触发源配置
- 软件触发:
HAL_ADC_Start(&hadc) - 定时器触发:闭环控制场景(如TIM2_TRGO)
- 软件触发:
- 抗干扰设计
- 硬件:RC低通滤波(10kΩ电阻 + 100nF电容)
- PCB布局:VREF+并联10μF+0.1μF去耦电容
DAC模块
- 双通道输出
- PA4(通道1)、PA5(通道2)
- 缓冲器使能建议:
hdac.Instance->CR |= DAC_CR_BOFF1; // 关闭缓冲提升响应速度
- 波形生成模式
- 三角波/噪声波:内置硬件生成
- 正弦波:需预计算查表法实现
三、代码实战(基于HAL库)
- 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周期)
- 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联动)
硬件连接:
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配置要点 |
六、扩展应用方向
- 音频信号处理
- ADC采集MIC输入 → FIR滤波 → DAC输出还原
- 实时性保障:计算耗时需<采样周期(例:44.1kHz需<22.7μs)
- 物联网传感器节点
- 低功耗设计:ADC注入模式唤醒待机设备,采样后返回睡眠
- 动态电压调节:DAC控制太阳能板MPPT电路
更多推荐



所有评论(0)