去年在调试一个音频电路时,我急需一个能输出多种波形的信号源。市面上的函数发生器动辄上千元,而实际需求只是简单的波形测试。于是我用STC89C52单片机+DAC0832搭建了这个成本不到50元的信号发生器,实测效果出乎意料的好。
这个设计最核心的特点是所有参数都采用整数档位调节。幅值1-5V按1V步进,频率100Hz-1kHz按100Hz步进。这种设计虽然牺牲了连续可调性,但带来了三大优势:
主控芯片选用STC89C52主要基于三点考虑:
数模转换模块采用DAC0832的原因:
注意:DAC0832是电流输出型DAC,必须配合运放使用。我曾尝试直接接负载,结果波形严重畸变。
输出级电路采用经典的反相放大结构:
code复制DAC输出 → 10kΩ → LM358(-)
|
20kΩ → 输出
|
10kΩ → GND
这个配置实现了2倍放大,将DAC的0-2.5V输出扩展到0-5V范围。实际调试中发现三个关键点:
幅值控制电路采用数字电位器X9C103S,其核心优势在于:
正弦波生成采用查表法,预存的72点正弦表对应5°相位间隔。这里有个重要技巧:数组长度选择72(360/5)可以使频率计算变得非常直观。
定时器中断服务程序的关键代码:
c复制void timer_isr() interrupt 1 {
static unsigned char index = 0;
index += step; // step决定频率
if(index >= 72) index -= 72;
switch(currentWave){
case SINE: DAC_OUT = SinTab[index]; break;
case TRI: DAC_OUT = TriTab[index]; break;
// 其他波形处理
}
}
频率控制原理:
数字电位器的控制逻辑看似简单,但有几点需要注意:
c复制void set_amplitude(int vol) {
digitalWrite(POT_CS, LOW);
for(int i=0; i<vol; i++){
digitalWrite(POT_UP, HIGH);
delayMicroseconds(100); // 必须的延时
digitalWrite(POT_UP, LOW);
}
digitalWrite(POT_CS, HIGH);
}
实测发现:延时不足50μs会导致抽头位置移动不可靠。而每次调整后需要等待至少10ms让输出电压稳定。
初期测试时发现正弦波在1kHz时有明显台阶感,通过以下措施改善:
普通IO口生成的方波上升沿约100ns,但受线路分布电容影响会变缓。改进方案:
测试中发现波形上有约20mV的毛刺,采取以下对策:
经过优化后,各波形参数如下:
| 波形类型 | 频率范围 | 幅值误差 | THD(1kHz) |
|---|---|---|---|
| 正弦波 | 100-1kHz | ±0.15V | <1.5% |
| 三角波 | 100-1kHz | ±0.2V | <3% |
| 方波 | 100-1kHz | ±0.1V | 上升时间1.2μs |
| 锯齿波 | 100-800Hz | ±0.25V | 线性度>95% |
通过长按按键触发的扫频功能,核心逻辑是:
c复制void sweep_mode() {
for(int f=100; f<=1000; f+=10){
set_frequency(f);
delay(50); // 每50ms步进10Hz
}
}
这个功能特别适合测试电路的频率响应特性。
通过修改DAC输出算法,可以实现波形叠加:
c复制DAC_OUT = (SinTab[index] + TriTab[index]) / 2;
这种混合波形在测试滤波器时非常有用。
输出幅度不足:
高频波形失真:
按键响应迟钝:
这个项目最让我惊喜的是DAC0832的表现,8位分辨率在音频范围内完全够用。下次准备尝试加入STM32方案,实现更高精度的任意波形生成。