1. 项目背景与硬件选型
第一次接触波形发生器是在大学电子设计课上,当时看到示波器上跳动的曲线觉得特别神奇。后来才知道,这些基础波形在通信、音频处理等领域有广泛应用。用51单片机直接输出模拟信号是不可能的,因为它只能输出0或1两种状态。这时候就需要一个关键芯片——PCF8591。
PCF8591这颗8位DAC芯片真是性价比之王,价格不到5块钱却能解决大问题。它通过I2C接口与单片机通信,只需要两根线(SDA和SCL)就能传输数据。我对比过其他DAC芯片,比如DAC0832需要并行接口,占用太多IO口;而更高级的AD9850虽然性能强但价格贵。对于初学者来说,PCF8591是最佳选择。
硬件连接时要注意几个关键点:
- 开发板上的P2.0和P2.1分别接SCL和SDA
- 地址引脚A0-A2全部接地,这样写地址就是0x90
- 参考电压接5V,这样输出范围就是0-5V
- 记得加上拉电阻(通常4.7kΩ)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. I2C通信协议实现
刚开始调试I2C时经常遇到通信失败的问题,后来发现是时序没把握好。51单片机的机器周期是1μs(12MHz晶振时),而PCF8591要求SCL高电平时间最少4.7μs。我的经验是延时函数这样写:
c复制void I2C_Delay() {
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
发送数据时要特别注意这个顺序:
- 起始信号:SCL高电平时SDA从高变低
- 发送设备地址(0x90)
- 发送控制字(0x40表示启用模拟输出)
- 发送数据值(0-255对应0-5V)
- 停止信号:SCL高电平时SDA从低变高
调试技巧:用逻辑分析仪抓取I2C波形最直观。如果没有仪器,可以用LED灯观察SDA线状态,至少能判断是否有信号输出。
3. 四种波形生成原理
3.1 正弦波的数学魔法
正弦波实现比想象中简单,关键是用好math.h里的sin函数。这里有个坑要注意:sin()的参数是弧度制而不是角度。我的做法是:
- 角度变量从0°到360°循环
- 转换为弧度:radian = angle * 3.14159/180
- 将sin返回
