1. 项目概述
这个函数信号发生器项目是我去年帮电子系学弟调试的一个课程设计,核心目标是用最便宜的单片机实现实验室级别信号源的基础功能。别看现在市面上各种DDS模块满天飞,自己从底层用单片机实现一遍,对理解信号生成原理和单片机外设使用帮助巨大。
我们选用了STM32F103C8T6这块"蓝色药丸"作为主控,成本不到10块钱,但凭借其72MHz主频和12位DAC,完全能满足音频范围内常见波形的生成需求。最终实现的信号发生器支持四种基础波形(正弦波、三角波、锯齿波、方波),幅值通过电位器可调,频率范围覆盖1Hz-20kHz,通过OLED显示当前参数,整体硬件成本控制在50元以内。
2. 硬件设计解析
2.1 核心器件选型
主控选择STM32F103C8T6主要考虑三点:
- 内置12位DAC,省去外接DAC芯片的成本和布线复杂度
- 足够的外设资源(定时器、GPIO等)满足波形生成需求
- 开发社区资源丰富,遇到问题容易找到解决方案
其他关键器件:
- 电位器:10kΩ线性电位器用于幅值调节
- 运放:LM358双运放,负责信号放大和阻抗匹配
- OLED:0.96寸I2C接口SSD1306,用于参数显示
- 按键:4个轻触开关实现功能切换
2.2 电路设计要点
DAC输出电路需要特别注意:
- 参考电压:使用3.3V LDO单独供电,避免电源噪声影响
- 低通滤波:在DAC输出端加入RC滤波(1kΩ+100nF)
- 运放配置:第一级电压跟随,第二级反向放大(增益=2)
实测发现:DAC直接带载能力很弱,必须加电压跟随器,否则波形会出现明显畸变
3. 软件实现细节
3.1 波形生成算法
正弦波生成
采用查表法+线性插值:
- 预计算256点的正弦表(节省内存)
- 定时器触发DMA传输
- 相位累加器实现频率调节
c复制// 正弦波查表生成代码示例
#define SIN_TABLE_SIZE 256
uint16_t sin_table[SIN_TABLE_SIZE];
void generate_sin_table() {
for(int i=0; i<SIN_TABLE_SIZE; i++) {
sin_table[i] = 2048 + 2047 * sin(2*PI*i/SIN_TABLE_SIZE);
}
}
非正弦波生成
- 三角波:线性增减计数器
- 锯齿波:递增计数器+瞬时回零
- 方波:比较器输出高低电平
3.2 频率控制实现
采用定时器+DMA的硬件联动方案:
- TIM6配置为更新事件触发DMA
- DMA将波形数据搬运到DAC
- 频率公式:f = TIM_CLK / (ARR+1) / 波形点数
c复制// 频率设置函数
void set_frequency(uint32_t freq) {
uint32_t arr = (72000000/256)/freq - 1;
TIM6->ARR = arr;
TIM6->CNT = 0;
}
3.3 幅值调节方案
通过ADC读取电位器电压(0-3.3V),映射到DAC输出范围:
- ADC配置为连续转换模式
- 每次DMA传输前对波形数据做比例缩放
- 加入软件滤波消除电位器抖动
4. 关键问题与解决方案
4.1 高频波形失真
现象:频率>10kHz时正弦波出现台阶
原因:DAC建立时间不足
解决:
- 降低波形点数(从512降到256)
- 开启DAC输出缓冲
- 优化DMA传输时钟配置
4.2 方波边沿振铃
现象:方波上升/下降沿有过冲
解决:
- 在运放反馈端并联10pF电容
- PCB布局缩短输出走线
- 避免使用面包板,改用PCB
4.3 低频波形抖动
现象:1-10Hz波形不稳定
原因:定时器ARR值过大导致精度不足
解决:
- 低频段改用PWM模式生成
- 加入软件校准补偿
5. 性能测试数据
测试条件:空载,室温25℃,电源稳压供电
| 波形类型 | 频率范围 | 幅值范围 | THD@1kHz |
|---|---|---|---|
| 正弦波 | 1Hz-20kHz | 0-3Vpp | <1.5% |
| 三角波 | 1Hz-20kHz | 0-3Vpp | - |
| 方波 | 1Hz-20kHz | 0-3Vpp | 上升时间<1μs |
| 锯齿波 | 1Hz-20kHz | 0-3Vpp | - |
6. 优化与扩展方向
- 频率精度提升:改用32位定时器或PLL倍频
- 波形混合功能:多波形叠加输出
- 扫频模式:自动频率扫描
- PC端控制:通过串口实现远程控制
这个项目最让我意外的是,用如此廉价的硬件也能实现不错的波形质量。调试过程中最大的收获是对DAC动态性能的理解——不是所有12位DAC都能胜任高速波形生成,必须仔细研读芯片数据手册中的建立时间参数。