资讯动态

51单片机与TLC5615低成本正弦信号发生器方案

发布时间:2026/9/16 15:13:17 来源:尧图企业网站定制
简介一份面向单片机与嵌入式初学者的正弦信号发生器设计资料以51单片机为控制核心搭配TI公司的12位DAC芯片TLC5615通过串行接口输出正弦波。资料包含完整的电路原理图、C语言源代码和Proteus仿真电路压缩包共16个文件涵盖了原理图DSN文件、Keil工程UV2文件、C源文件、HEX固件及仿真工程文件等整体仅72KB轻便易读。已有3619人学习下载。项目中不仅展示了电源、单片机最小系统、DAC转换与滤波电路的搭建方法还通过查表法生成正弦波形数据详细演示了单片机与DAC协同工作的流程。读者可在Proteus中直接运行仿真实时观察波形输出并调试参数通过修改查表数据还可扩展为其他波形。适合课程设计、电子竞赛或自学实践既能加深对51单片机通信接口的理解也能提升模拟电路与嵌入式综合设计能力。1. 正弦信号发生器51单片机与TLC5615的一种低成本解法做51单片机课程设计时正弦信号发生器是出现频率很高的题目。常见的实现路线有三种直接用PWM加RC滤波、用DDS芯片如AD9833、以及用单片机外挂并行或串行DAC。PWM方案的毛病是分辨率与输出频率互相牵制想要1kHz以上且波形平滑普通51的定时器资源会很紧张DDS芯片效果最好但多数人手里没有现成模块Proteus里也未必有模型。中间路线就是用51单片机加一颗串行DAC在代码里用查表法逐点刷新输出。TLC5615是TI的10位串行DAC三根口线就能驱动内置2倍增益输出缓冲输出端几乎不需要额外运放。整条链路从电路原理图、源代码到Proteus仿真电路都能在课程设计周期内完整跑通。这篇内容就是按“先讲连接和时序再给可编译的代码最后说Proteus排错和实物调校”的顺序展开目标是让读者拿到原理图能画板拿到代码能出波形仿真与实物之间的坑也提前标出来。2. 原理图到连线51单片机与TLC5615的关键信号与参考电压2.1 TLC5615引脚功能与SPI兼容时序TLC5615是8脚DIP/SOIC封装芯片本身是10位DAC但输入数据帧设计成了16位或最少12位。串行接口与SPI兼容工作方式非常简单CS拉低后数据在SCLK上升沿逐位移入内部移位寄存器MSB在前16位数据全部移完后把CS拉高数据锁存到DAC寄存器输出端OUT立即更新为对应的模拟电压。16位帧的格式是前4位填充任意值通常填0中间10位是有效的DAC数据后2位也是填充任意值通常填0。这句格式说明很重要很多人在写驱动时把数据直接左移6位或右移4位导致波形完全错乱。常见做法是直接把10位数据左移2位让数据落在16位帧的bit11~bit2上其余填充位保持0。信号名连接到51的位置功能说明DINP1.0串行数据输入最高位先进入芯片SCLKP1.1串行时钟上升沿把DIN采样进移位寄存器CSP1.2片选低电平期间传输高电平锁存输出DOUT悬空级联输出本设计不用留空即可REFIN2.5V基准电压决定DAC满幅输出输出约为2倍REFINOUT示波器探头或滤波电路模拟输出引脚VDD5V供电2.7V到5.5V均可工作AGND系统地模拟地与数字地单点相连这8个引脚里最容易忽略的是REFIN。TLC5615输出电压公式是Vout 2 × REFIN × D / 1024也就是说满幅输出是参考电压的2倍。如果REFIN接2.5V理论上D1023时输出接近5VD512时输出2.5VD0时输出0V。这个2倍关系决定了参考电压的精度会直接反映在输出波形幅度上原理图里不能随便从5V电源串个电阻就完事。2.2 原理图连接与51最小系统注意点原理图分两部分51单片机最小系统以及TLC5615的DAC输出部分。最小系统是常规配置12MHz晶振接XTAL1和XTAL2两个30pF电容分别到地复位电路用10μF电解电容和10kΩ电阻组成上电复位第31脚EA必须接VCC这脚如果悬空或接地单片机默认去外部ROM取指令程序不会从片内Flash启动。Proteus仿真里这个脚不接往往也能跑但做成实物时不接EA必然黑屏无输出所以原理图上一律画成接高电平。TLC5615的连线按表格接到P1.0、P1.1、P1.2。选P1口的原因是51的P1口内部有上拉直接输出高电平稳定不像P0口是开漏结构必须外接上拉电阻才能输出可靠高电平。REFIN建议用10kΩ电位器从5V分压取得并在REFIN引脚对地并联一个0.1μF陶瓷电容。这个电容的作用是滤掉基准电压上的高频噪声DAC输出端的波形干净程度有一半取决于REFIN上的纹波。OUT引脚可以直接接到示波器或下级电路芯片输出端自带缓冲放大器带载能力足够驱动后级的RC滤波网络。AGND和DGND在芯片附近单点连接不要在两块地之间再铺大面积的连通区域否则数字信号跳变会通过地平面耦合进模拟输出。2.3 为什么是TLC5615选型对比与边界和常见的DAC0808比TLC5615是串行接口只占3个I/O口而DAC0808是8位并行总线还要占用整个P0口加控制线布线负担和单片机引脚压力都大。和PCF8591比TLC5615是10位分辨率PCF8591只有8位且I2C速率受限于标准模式刷正弦查表时扫描速率拉不上去。和PWM滤波方案比PWM方案在普通51上要达到10位分辨率需要极高频率的定时器重载输出频率一高分辨率就断崖式下降。TLC5615的10位分辨率配合SPI串行输出在12MHz主频下能稳定输出几十到一百多赫兹的正弦波这在很多信号源应用场景里已经够用。这条路线也有它的边界51单片机没有硬件SPI驱动完全靠GPIO模拟写一次16位数据需要十几微秒到上百微秒所以查表点数越多、输出频率越高对时序的要求就越紧张。做实物时如果发现波形出现周期性毛刺先检查采样间隔和DAC写入耗时是否已经互相挤压。这也是后续章节要重点处理的问题。3. 源代码落地查表法正弦波与TLC5615驱动时序3.1 生成正弦波采样表Python脚本与偏置设计查表法的思路很直接把一个周期的正弦波离散成N个点预先计算好每个点对应的DAC数值单片机按固定时间间隔把表里的数值逐个写入DAC输出端就得到阶梯状的正弦波。N越大波形越细腻但占用ROM越多、刷新周期越长N越小刷新率越高但波形台阶明显。这里取64点既能让波形在示波器上看不出明显折线又不会把ROM空间和中断时间占满。生成查表的Python脚本如下这个脚本在任何带Python的机器上都能直接跑import math N 64 vals [round(512 500 * math.sin(2 * math.pi * i / N)) for i in range(N)] for r in range(0, N, 8): print( , .join(str(v) for v in vals[r:r 8]) ,)输出结果直接复制到Keil的数组里。这里有两个设计细节需要解释第一DAC是10位取值范围是0到1023波形中点取512对应REFIN2.5V时的输出2.5V第二幅度取500而不是512因为正弦波峰值加到中点上会达到1012离满量程1023保留了11个LSB的余量输出端即使靠近电源轨也不会削波。TLC5615的输出摆幅不能完全到电源轨幅度留余量是必要的。3.2 TLC5615写时序的C语言实现完整的Keil C51工程代码结构如下文件里包含查表数组、DAC写入函数、定时器中断和主函数#include reg51.h #define N 64 sbit CS P1^0; sbit SCLK P1^1; sbit DIN P1^2; code unsigned int sin_tab[N] { 512, 561, 609, 657, 703, 748, 790, 829, 866, 898, 927, 952, 974, 990, 1002, 1009, 1012, 1009, 1002, 990, 974, 952, 927, 898, 866, 829, 790, 748, 703, 657, 609, 561, 512, 463, 414, 367, 321, 276, 234, 195, 158, 126, 97, 72, 50, 34, 22, 15, 12, 15, 22, 34, 50, 72, 97, 126, 158, 195, 234, 276, 321, 367, 414, 463 }; void TLC5615_Write(unsigned int value) { unsigned char i; value 0x03FF; // 只保留10位有效数据 value 2; // 左移2位对应16位帧中的D11~D2位置 CS 0; // 片选拉低开始传输 for (i 0; i 16; i) { SCLK 0; // 时钟拉低准备建立数据 DIN (value 0x8000) ? 1 : 0; // 先发最高位 SCLK 1; // 上升沿TLC5615采样DIN value 1; // 下一位 } CS 1; // 片选拉高DAC输出更新为当前值 } void Timer0_Init(void) { TMOD 0xF0; TMOD | 0x01; // 定时器0工作模式116位定时 TH0 0xFE; // 采样间隔约312us对应50Hz输出 TL0 0xC8; ET0 1; // 开定时器0中断 TR0 1; // 启动定时器 EA 1; // 开总中断 } void Timer0_ISR(void) interrupt 1 { static unsigned char idx 0; TH0 0xFE; // 先重装初值再写DAC TL0 0xC8; TLC5615_Write(sin_tab[idx]); idx (idx 1) 0x3F; // 查表指针0~63循环 } void main(void) { P1 0x07; // 上电先把CS、SCLK、DIN置为高电平 Timer0_Init(); while (1) { // 主循环空闲可在此处扫描按键调整TH0/TL0实现变频 } }代码里最关键的是TLC5615_Write函数。value 0x03FF把输入限制在10位范围内避免越界数据破坏输出value 2把10位数据放到16位帧的中间位置循环从bit15开始逐位移出前4位是填充0紧接着10位有效数据最后2位也是0。DIN先赋值、SCLK再拉高这个顺序保证数据在上升沿到达时已经稳定。CS在整个16个时钟周期内保持低电平结束后拉高锁存DAC输出才更新。如果写成CS先拉高再移数据输出会一直停留在上一次的值。中断服务函数里先重装定时器初值再调用DAC写入是因为DAC写入耗时长先重装可以避免写入期间定时器继续跑导致初值误差积累。3.3 定时中断与频率调节输出频率由查表点数和采样间隔共同决定。64点表时输出频率f 1 / (64 × Ts)其中Ts是定时器中断间隔。当前代码里TH00xFE、TL00xC8对应十进制初值65224在12MHz晶振下机器周期1μs定时间隔为65536-65224312μs输出频率约50Hz。把TH0和TL0改成下面的组合可以得到不同频率输出频率定时器初值TH0 / TL0采样间隔50Hz652240xFE / 0xC8312μs75Hz653280xFF / 0x30208μs100Hz653800xFF / 0x64156μs频率调高时要注意中断里DAC写入本身的耗时。12MHz主频下一次TLC5615_Write大约需要150μs到200μs如果采样间隔小于这个时间中断还没执行完下一次溢出就到来了波形会直接出现周期性毛刺。100Hz这一档的156μs已经比较靠近边界Keil里需要开启优化选项或者把循环改成12位传输来节省时间。更稳妥的做法是保持50Hz和75Hz这两档把查表点数降到32个输出频率就能翻倍到100Hz和150Hz。低频段则没有这个限制20Hz、10Hz只需要把初值往小调波形质量不受影响。如果需要更高频率建议换用有硬件SPI的STC15系列单片机或者改用DDS方案这属于这条技术路线的合理边界。4. Proteus仿真电路搭建从元件摆放到底层排错4.1 元件清单与电路绘制步骤Proteus仿真电路的搭建流程和真实画原理图几乎一致。新建工程后在左侧元件模式面板点“P”打开元件库输入关键字分别选取AT89C51、TLC5615、10kΩ电阻、10μF电解电容、0.1μF陶瓷电容、30pF电容、12MHz晶振、10kΩ电位器POT-HG。Proteus元件库里TLC5615可以直接搜到实际条目名可能带批次后缀选带模拟输出的那个即可。放置元件后按第2章的连接表布线单片机部分注意EA脚接VCC、复位电路不要漏掉。一些操作细节DIN、SCLK、CS三根线从P1.0到P1.2引出布线时尽量让这三根线短直REFIN用电位器中间抽头连接电位器两端分别接5V和GNDOUT引脚直接拉一根线到虚拟示波器的A通道输入。GND统一用GROUND终端VCC用POWER终端双击POWER把电压设置为5V。TLC5615的AGND和DGND在芯片附近汇合到同一个GND节点不要在仿真里为模拟地和数字地分别建立网络。4.2 仿真参数设置与HEX加载代码编译需要先让Keil生成HEX文件。在Keil的Options for Target里勾选Output页的Create HEX File重新编译后工程目录下会生成.hex文件。回到Proteus双击AT89C51芯片在Program File一栏选择这个HEX文件并确认Clock Frequency设置为12MHz。这里要注意Proteus里AT89C51的时钟频率是在芯片属性里设置的不是通过外部晶振器件决定如果原理图上额外放了晶振两者的频率设置必须保持一致否则定时器初值算出来完全对不上。仿真运行前放置虚拟示波器右侧工具栏的Virtual Instruments模式里选OSCILLOSCOPE把A通道接到TLC5615的OUT引脚然后点击左下角运行按钮。正常情况下示波器上应该出现一条以2.5V为中线、幅度约4.8V峰值、频率50Hz的正弦波形。如果看到的是直流电平不动多半是HEX文件没有加载成功如果波形像是乱码先检查DIN和SCLK的引脚定义是否和代码一致。初次仿真建议把示波器的时间轴放到5ms每格能看到完整的两个周期便于判断频率是否正确。4.3 常见仿真问题定位Proteus仿真中出现的故障往往比实物更有规律下表的排查顺序基本能覆盖大部分情况现象常见原因处理方法OUT始终为0V单片机没有加载HEX文件在AT89C51属性里重新选择.hex并运行OUT输出恒定5V或2.5VCS始终为高数据没有锁存检查CS是否接对引脚程序里CS1的位置波形是台阶状但频率不对定时器初值或晶振频率设置错误核对TH0/TL0对应关系确认Clock Frequency为12MHz波形有周期性抖动采样间隔小于DAC写入耗时降低频率档位或减少查表点数正弦波顶部削平REFIN电压偏高导致输出接近电源轨调低电位器使REFIN接近2.5V波形存在高频毛刺REFIN没有并联滤波电容在REFIN与AGND之间加0.1μF电容用Proteus仿真51单片机时最容易忽略的是EA脚。仿真模型里EA悬空偶尔也能运行但这会在实物移植时误导人所以仿真原理图上也建议把EA接VCC让仿真环境和真实硬件行为保持一致。另一个值得注意的地方是虚拟示波器的接地示波器探头的地必须和电路GND连接否则波形显示会飘移。5. 输出级调校隔直、滤波与参考电压校准5.1 去掉2.5V直流偏置TLC5615是单电源供电输出波形天然带有2.5V直流分量不是正负对称的交流正弦。如果后级要接功率放大器或音频设备这个直流偏置必须去掉。最简单的隔直方式是OUT引脚串联一个电解电容再接一个10kΩ电阻到GND作为负载构成高通滤波器。截止频率按f 1 / (2πRC)计算电容取10μF时截止约1.6Hz对20Hz以上的信号几乎无衰减。实际电路里电容正极接DAC输出侧因为DAC输出电压总是高于0V。5.2 一阶RC滤波的截止频率估算64点查表输出的本质是阶梯波每个台阶宽度等于采样间隔在频谱上会形成采样频率及其谐波分量。以50Hz输出为例采样频率是3.2kHz台阶噪声集中在3.2kHz附近。在隔直电容后面串一个1kΩ电阻、并联0.1μF电容到地截止频率约为1.59kHz能把3kHz以上的台阶分量压下去同时保持50Hz基波几乎不受影响。筛选电容时按公式f 1 / (2πRC)取输出最高基波频率的3到5倍即可过高滤波效果不明显过低会让正弦波幅度衰减。5.3 REFIN用基准源并做幅度校准REFIN直接接5V分压的做法在实物中会让波形幅度随电源波动而漂移因为Vout和REFIN是严格2倍关系。做实物时建议把REFIN改接TL431稳压到2.5V再经电位器微调。校准步骤很具体先在DAC写入代码里让对方输出一个固定值比如把查表索引固定到D512此时OUT应该等于REFIN的2倍用万用表测量并调整REFIN电位器使OUT读数精确到5.000V附近然后恢复查表运行波形幅度自然就正确了。校准时把万用表探头点在OUT与AGND之间先调REFIN到2.500V再观察波形是否上下对称一般就能把幅度误差压到1%以内。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价