以下是针对 题目8:ADC采集与DAC输出 的详细实现方案,包含流程图和图形化展示:
流程图
硬件连接
模块 | STM32引脚 | 功能 |
---|---|---|
光敏电阻 | PA0 | ADC1_IN0 |
电位器 | PA1 | ADC1_IN1 |
DAC输出 | PA4 | DAC1_OUT1 |
示波器/万用表 | PA4 | 观测输出波形 |
步骤1:配置ADC多通道扫描+DMA
1.1 STM32CubeMX配置
- ADC1设置:
- Mode: Scan Conversion Mode(扫描模式)
- Continuous Conversion Mode: Enabled
- DMA Continuous Requests: Enabled
- Number of Conversions: 2
- Rank 1: Channel 0 (PA0), Sampling Time: 15 Cycles
- Rank 2: Channel 1 (PA1), Sampling Time: 15 Cycles
- DMA配置:
- Mode: Circular
- Data Width: Half Word(匹配ADC的12位分辨率)
1.2 关键代码
// ADC初始化(CubeMX生成)
MX_ADC1_Init();
MX_DMA_Init();
// 启动ADC+DMA传输
uint16_t adc_buffer[2]; // 存储双通道数据
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, 2);
步骤2:生成DAC波形
2.1 正弦波查表法
// 生成正弦波表(256点,12位分辨率)
#define WAVE_SIZE 256
uint16_t sine_wave[WAVE_SIZE];
for (int i = 0; i < WAVE_SIZE; i++) {
sine_wave[i] = (uint16_t)(2048 * (1 + sin(2 * M_PI * i / WAVE_SIZE))); // 0~4095
}
2.2 DAC+DMA输出
// DAC初始化(CubeMX配置PA4为DAC_OUT1)
MX_DAC_Init();
HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)sine_wave, WAVE_SIZE, DAC_ALIGN_12B_R);
步骤3:动态调整波形(基于ADC输入)
// 在ADC转换完成回调中调整波形频率
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
uint16_t light_value = adc_buffer[0]; // 光敏电阻值
uint16_t pot_value = adc_buffer[1]; // 电位器值
// 根据电位器值调整波形频率
float freq = 100 + (pot_value / 4095.0f) * 1000; // 100Hz~1100Hz
update_dac_frequency(freq);
}
// 更新DAC输出频率(通过调整DMA传输速度)
void update_dac_frequency(float freq) {
uint32_t update_rate = SystemCoreClock / (WAVE_SIZE * freq);
hdac.DMA_Handle->Instance->CNDTR = WAVE_SIZE;
hdac.DMA_Handle->Instance->CPAR = (uint32_t)&(DAC->DHR12R1);
hdac.DMA_Handle->Instance->CMAR = (uint32_t)sine_wave;
hdac.DMA_Handle->Instance->CCR |= DMA_CCR_EN; // 重启DMA
}
图形化信号流
ADC信号输入 DMA传输 DAC输出
┌───────┐ ┌──────────┐ ┌──────────┐
│ PA0 │─光敏电阻─→│ ADC1_IN0 │──DMA─→│ RAM缓冲区 │─→┐
└───────┘ └──────────┘ └──────────┘ │
┌───────┐ ┌──────────┐ │
│ PA1 │─电位器──→│ ADC1_IN1 │──DMA─→│ RAM缓冲区 │─→┤
└───────┘ └──────────┘ └──────────┘ │
↓
┌──────────────┐
│DAC1_OUT(PA4)│→ 波形
└──────────────┘
关键配置参数
模块 | 参数 | 值 |
---|---|---|
ADC | 时钟频率 | 12MHz |
采样时间 | 15 Cycles | |
分辨率 | 12-bit | |
DAC | 触发源 | TIM6 TRGO |
输出缓冲 | Disabled | |
DMA | 传输模式 | Circular |
数据对齐 | Right-aligned |
常见问题与解决
-
ADC采样值不稳定:
- 增加RC滤波电路(PA0对地并联0.1μF电容)
- 软件均值滤波:
adc_value = (adc_buffer[0] + adc_buffer[1]) / 2
-
DAC输出波形失真:
- 检查DMA传输是否溢出(
HAL_DMA_GetState()
) - 确保查表数据对齐(12位右对齐:
DAC_ALIGN_12B_R
)
- 检查DMA传输是否溢出(
-
系统时钟冲突:
- 确认ADC/DAC时钟源与主频分频比匹配
- 使用独立时钟源(如APB1用于DAC,APB2用于ADC)
扩展功能
-
双缓冲DMA:
// 定义双缓冲区 uint16_t wave_buf1[256], wave_buf2[256]; HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)wave_buf1, 256, DAC_ALIGN_12B_R); // DMA传输完成中断中切换缓冲区 void HAL_DAC_DMAConvCpltCallback(DAC_HandleTypeDef* hdac) { static uint8_t buf_idx = 0; buf_idx ^= 1; HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)(buf_idx ? wave_buf1 : wave_buf2), 256, DAC_ALIGN_12B_R); }
-
实时波形生成:
// 在DMA传输中实时计算三角波 void generate_triangle_wave(uint16_t *buf, uint32_t len) { for (uint32_t i = 0; i < len; i++) { buf[i] = (i % 256) * 16; // 0~4095线性变化 } }
通过此方案,可实现高速ADC信号采集与DAC波形合成的闭环系统,适用于音频处理、闭环控制等场景。