ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

51单片机AD/DA转换Proteus仿真实验设计与调试

51单片机AD/DA转换Proteus仿真实验设计与调试 简介面向单片机初学者的AD/DA转换实验设计资源基于Proteus仿真平台以ADC0809和DAC0832为核心覆盖A/D转换、模拟量采集、LED二进制显示以及D/A转换循环输出锯齿波和三角波等典型练习场景适合课程设计或实验教学配套使用。压缩包共121个文件、约3.68MB包含Proteus仿真图png、单片机源程序c/h、Keil及Proteus工程文件、编译生成的hex/lst/obj和备份文件可直接打开工程查看代码、仿真运行或烧录验证。已有201人学习下载。借助仿真图与配套代码可以对照理解A/D转换芯片与单片机的接口方法、ADC0809的转换性能与编程方式、单片机数据采集的实现思路同时了解D/A转换的基本原理、DAC0832的编程方法及系统中扩展D/A转换的常见方式从原理图到代码调试形成完整闭环。1. 为什么AD/DA实验要先放进Proteus再做一遍如果只给一块还没接示波器的开发板让你用51单片机采集电位器电压再原样输出新手大概率会卡在三个地方第一次卡在ADC0809的启动时序第二次卡在EOC一直不跳变第三次卡在DAC输出始终只有0V。这三个坑放在Proteus仿真里分别对应时钟源没接、引脚接错、运放没装定位起来比折腾真实硬件快得多。这个标题拆开看“基于单片机”说明控制核心是51内核的单片机“protues仿真”强调用ISIS画原理图、用虚拟示波器验证而“AD DA实验设计”是把模拟量采集和模拟量输出放到同一条数据链路上。对正在做protues入门、准备单片机毕业设计的人来说这个实验刚好卡在“会读单片机数字量”和“会处理连续电压”之间。电位器或信号源产生模拟电压ADC0809将其转成8位数字量单片机把数字量原样或加工后交给DAC0832重新还原成电压整个过程不依赖真实硬件调试成本和烧芯片的概率都低。2. ADC0809与DAC0832的选型依据和仿真差异2.1 为什么仿真里偏爱0809和0832这对组合仿真和实物选型逻辑不一样。实物上你可能用STM32内置ADC或者挂一块ADS1115走I2C但在Proteus教学场景里并行接口的0809和0832有不可替代的优势所有时序引脚直接裸露在原理图上START、EOC、OE、WR1的电平变化都可以用电压探针逐个观察。对51单片机来说8位并行接口的读写代码也最简单不存在I2C时序的封装隐藏问题。ADC0809是8位逐次逼近型ADC带8路模拟输入输出带三态缓冲可以直接挂在P0口这样的双向数据总线上。DAC0832是8位并行DAC内部是R-2R梯形电阻网络输出的是电流而不是电压通常要外接运算放大器才能得到0到5V的电压。两个芯片一个负责把连续电压变数字一个负责把数字变回连续电压正好覆盖模拟信号链路的两端。直接说结论这套组合适合两类人一类是想把AD/DA转换过程看得清清楚楚的初学者另一类是在做课程设计、需要快速产出“仿真图源代码”交付物的学生。如果换成串行ADC0832确实省引脚但仿真里串行时钟和MISO/MOSI的时序观察起来远不如并行直观。芯片位数接口仿真中必须外接调试重点ADC080988位并行CLOCK时钟源启动时序、通道选择、EOC等待DAC083288位并行运算放大器或电压探针CS/WR1写时序、电流转电压2.2 逐次逼近与R-2R网络原理不需要全懂但三个点不能错ADC0809内部是逐次逼近结构转换过程从最高位开始逐步逼近输入电压所以数据稳定需要时间编程时必须等待EOC信号变成高电平不能启动转换后立刻去读数据。很多人写代码时直接读P0口读回来的一会儿是0xFF一会儿是0x00多数就是漏了这一步。DAC0832的R-2R梯形网络输出的电流在IOUT1和IOUT2之间形成差值外部运放把这个电流差转换成电压。仿真中如果不接运放直接在IOUT1引脚上看电压读数会非常奇怪因为高阻电流输出不能简单用电压表量。这是仿真图和实物接线最容易混淆的地方。另外要记住一个换算关系ADC0809字长8位0到5V输入对应数字0到255每个数字量对应约19.6mVDAC0832同理数字量每增加1理想输出电压步进约5V/255。做实验时心里有这组数就能快速判断采集回来的值是不是合理。// 把AD值换算成实际电压值方便在调试窗口观察 float voltage (float)adc_val * 5.0f / 255.0f;这段代码的逻辑是先把整数adc_val转成浮点数再乘以5V满量程最后除以255。参数里的5.0f对应基准电压如果实际电路用4.096V基准这里就要改成4.096f。仿真里默认电源5V时这个换算关系能让你在虚拟终端里直接看到电压数值而不用对着十六进制数据心算。2.3 观察工具选择虚拟示波器、电压探针和直流电压表Proteus左侧工具条的“Virtual Instruments”面板里有OSCILLOSCOPE适合观察连续变化的波形调试AD/DA实验时我习惯同时放两个东西一个VOLTAGE PROBE放在DAC输出端看波形形状一个DC VOLTMETER放在电位器抽头上看当前绝对电压。示波器负责看趋势电压表负责读准确值两者组合起来就能完整描述模拟链路的状态。还要提醒一个搜索陷阱网上搜“AD检查原理图有没有连上”出来的结果大部分是Altium Designer的操作跟这里的AD不是一回事。这里的AD是Analog-to-Digital检查原理图连线不靠外部工具直接在Proteus里核对网络标号和总线标签就够了第3章会说具体做法。3. Proteus仿真图搭建元件放置、网络标号和虚拟示波器3.1 元件清单与调试前的引脚规划画仿真图之前先把引脚分配表写出来否则连到一半会发现P0口既接ADC又接DAC控制线挤在一起理不清。我习惯把控制信号拆成两组ADC组管启动和读取DAC组管输出锁存数据总线共用P0口但分时复用。单片机引脚接到哪里作用P0.0-P0.7ADC0809的D0-D7、DAC0832的D0-D78位数据总线分时复用P2.0ADC0809的START/ALE启动一次转换P2.1ADC0809的EOC查询转换是否完成P2.2ADC0809的OE打开输出缓冲P2.3-P2.5ADC0809的ADDA/ADDB/ADDC选择模拟输入通道P2.6DAC0832的CS片选信号P2.7DAC0832的WR1写入数据元件清单方面AT89C51是主控ADC0809负责采集DAC0832负责输出LM358做电流转电压POT-HG电位器当模拟输入源RESPACK-8上拉排阻用于P0口另加一个CLOCK源给ADC0809提供时钟。如果想让演示效果更直观再加一个SINE信号源接到IN1通道。3.2 放置器件、改属性、连线三步走第一步放置器件。从元件库搜索并放置AT89C51、ADC0809、DAC0832、LM358、POT-HG、RESPACK-8。双击AT89C51在Clock Frequency属性里把晶振频率设成12MHz这个值影响单片机指令周期也影响延时函数的时间基准。第二步处理网络标号。很多人搜过“protues怎么添加引脚”这里一次讲清楚在ISIS里给导线命名就叫添加网络标号。在需要命名的导线上右键选择Place Wire Label输入类似AD_CLK的名称两条不同位置的导线如果标号相同电气上就算连接在一起。这样做的好处是不用把线绕满整个原理图总线区域看起来也干净。第三步连线。先把两片芯片的VCC和GND接好再接8位数据总线每条数据线从P0口连到ADC0809的D0-D7同时也连到DAC0832的D0-D7。控制线单独走P2.0接START/ALEP2.1接EOCP2.2接OE通道选择三根线ADDA、ADDB、ADDC分别接P2.3到P2.5。DAC0832的ILE接VCCWR2和XFER在仿真里直接接地CS和WR1接单片机。3.3 给ADC0809接时钟源给DAC接运放ADC0809的CLOCK引脚必须接时钟不接的话仿真里芯片不工作EOC永远停在低电平程序会卡死在等待循环。双击CLOCK源把频率设成640kHz这是0809手册里给出的典型工作频率仿真里选这个值最不容易出错。频率太低转换变慢频率超过1280kHz则超过芯片极限后面第5章会展开讲。DAC0832的输出端要接运放。在原理图上放置LM358把IOUT1接到运放反相输入端IOUT2接到同相输入端运放输出端再接一个反馈电阻到反相输入端。这个运放电路的功能是把DAC输出的差分电流转换成单端电压输出范围约0到5V。运放输出端接一个VOLTAGE PROBE和示波器A通道就能直接看到还原后的电压波形。3.4 通电前检查引脚标号与总线一致性运行仿真前做一遍系统检查重点看三处。检查数字芯片的电源是否都接好尤其注意ADC0809和DAC0832这两个芯片的VCC、GND漏接一个仿真时就报错或者输出全零。检查P0口上拉排阻虽然Proteus仿真里不接上拉也能跑但真实硬件中P0口是开漏结构加上RESPACK-8到VCC才算完整设计。检查总线标签数据总线D0到D7如果写成D0、D1、D2这样连续编号两边芯片的对应关系必须一致总线上一根线标签错位读出来的数据就会整体移位。检查完后直接点击运行如果示波器上没有任何波形优先看左下角信息栏有没有未连接引脚提示。Proteus不会像PCB工具那样给出完整错误报告但未连接引脚会明确显示按提示回到原理图补线就行。4. Keil工程与51源码ADC读取和多路通道切换的实现4.1 引脚定义与读写时序约定软件部分用Keil编写C51代码工程建立后先把引脚定义写好。P0口在REG51.H里已经定义成sfr可以直接读写控制线逐一定义为sbit。这里有个关键设计P0口同时连接ADC0809和DAC0832同一时刻只能有一个芯片在驱动总线所以读AD和写DA必须做成两个独立函数中间用OE引脚做总线切换。#include REG51.H sbit START P2^0; // ADC0809 启动/地址锁存 sbit EOC P2^1; // 转换结束标志输入 sbit OE P2^2; // 输出使能 sbit ADDA P2^3; // 通道选择位 A sbit ADDB P2^4; // 通道选择位 B sbit ADDC P2^5; // 通道选择位 C sbit DAC_CS P2^6; // DAC0832 片选 sbit DAC_WR P2^7; // DAC0832 写信号这段定义的核心是把控制线全部映射到P2口P0口保留给数据总线。EOC是输入引脚在C语言里声明成sbit后直接读取即可。START和OE是输出引脚用来产生启动脉冲和打开数据缓冲。通道选择三根线ADDA、ADDB、ADDC的编码方式是从低位到高位排列对应0809内部多路开关的二进制地址。4.2 AD采集与DA输出的最小源码主功能代码只需要两个函数加一个主循环。ADC读取函数的流程是先选通道再发启动脉冲然后等待EOC变高最后打开OE读数据。DAC输出函数则相反先把数据写到P0口再拉低CS和WR1写信号上升沿锁存数据。unsigned char adc_read(unsigned char ch) { unsigned char val; // 选择模拟通道: ch 的低三位对应 C/B/A ADDC (ch 2) 0x01; ADDB (ch 1) 0x01; ADDA ch 0x01; // 产生正脉冲启动转换 START 0; START 1; START 0; // 等待转换结束EOC 从低电平变为高电平 while (0 EOC); // 打开输出缓冲从 P0 口读取 8 位结果 OE 1; val P0; OE 0; return val; } void dac_write(unsigned char dat) { P0 dat; // 数据写进 DAC 的数据输入寄存器 DAC_CS 0; // 片选拉低 DAC_WR 0; // 写信号拉低 DAC_WR 1; // 写信号上升沿数据被锁存 DAC_CS 1; // 片选拉高完成一次写入 }代码里的时序要重点说明。START脉冲由三条连续赋值语句产生先拉低再拉高再拉低这个正脉冲宽度在12MHz晶振下约等于几条指令周期已经满足ADC0809启动信号不小于100ns的要求。EOC轮询是转换完成标志转换期间EOC保持低电平转换结束后跳高所以while(0 EOC)会一直等待直到转换完成。OE打开后读取P0口的数据读完立刻关闭OE这样下次DA写入时总线不会冲突。dac_write函数里先写P0再拉CS保证数据总线已经稳定后DAC才开始采样。主程序里做一个最简单的回环读取电位器电压对应的数字量原样写入DAC示波器就能看到输入和输出波形同步变化。这个回环虽然功能简单但把“模数转换-数字处理-数模转换”整条链路串起来了。void delay(unsigned int n) { while (n--); } void main(void) { unsigned char v; P0 0xFF; // 数据总线初始化为高电平 while (1) { v adc_read(0); // 采集通道 0接电位器 dac_write(v); // 原样送到 DA观察波形跟随 delay(800); // 控制刷新率 } }delay(800)的参数决定了采样输出频率800约等于几毫秒延时。如果想看更平滑的波形把参数调小到200左右如果希望LED指示渐变效果就把参数加大到2000肉眼能清楚看到亮度变化。P0初始化为0xFF是为了让总线在空闲时处于确定电平避免悬空状态干扰后续读写。4.3 双通道轮流采集与看波形单通道回环跑通后把实验扩展成双通道很有意义。在IN0上接电位器IN1上接SINE信号发生器主程序轮流采集两个通道就能在示波器上同时观察两路信号的还原情况。void main(void) { unsigned char ch 0; while (1) { dac_write(adc_read(ch 0x01)); // 轮流采集 IN0 和 IN1 delay(400); ch; } }这个写法用ch的最低位切换通道ch为偶数时采集IN0奇数时采集IN1。delay(400)不只是控制刷新率还留给示波器足够的波形刷新时间。如果去掉这个延时切换速度过快示波器上看到的波形会混叠成一团。4.4 在Proteus里加载HEX文件代码编译前先确认Keil工程输出了HEX文件。在Options for Target的Output页面勾选Create HEX File编译后工程目录下会生成同名.hex文件。回到Proteus双击AT89C51芯片在Program File里选择这个HEX文件然后运行仿真。这是最稳定的加载方式比Keil和Proteus联调省事因为联调需要额外配置双方调试接口不同版本之间的兼容性参差不齐。如果坚持要单步调试常见做法是在Keil的Debug设置里选择Proteus VSM Simulator同时打开Proteus的远程调试监视器。但我个人建议先直接加载HEX跑通功能确认整体行为正确后再考虑单步调试定位具体问题效率会高很多。5. 处理好这三个坑仿真结果才可信5.1 时钟源频率为什么是640kHzADC0809的CLOCK引脚频率直接影响转换时序仿真中这个参数经常被随手填成1kHz或者10kHz结果程序卡在EOC等待上。我直接把CLOCK源频率设为640kHz这是0809手册的典型工作条件转换时间约100us既能保证EOC产生清晰的高低跳变又不会因为频率太高导致仿真抖动。时钟频率转换时间约仿真表现100kHz128us稳定但波形刷新慢640kHz20us推荐值EOC脉冲清晰2MHz10us可能超出芯片上限取样不稳调频率时注意一点如果示波器波形有毛刺先检查CLOCK源旁边有没有误接地再检查频率数值本身。Proteus不报频率超限错误超了也是照跑但结果会偏离真实芯片行为。5.2 P0口上拉与总线竞争P0口在51单片机里是开漏结构输出高电平需要外接上拉电阻。仿真中偷懒不接上拉逻辑上照样能跑但P0总线同时被ADC0809和DAC0832挂载时会产生总线竞争问题。读AD时OE必须打开此时P0口由ADC驱动读完必须立即OE置0否则紧跟着写DAC时P0上等于两个输出同时在抢总线轻则数据错误重则示波器上出现明显的不定态毛刺。所以在源码里我才强调OE的时序读数据放在OE1之后读取完成立刻OE0。这个顺序就是给总线上锁确保任意时刻只有一个芯片在输出。排阻RESPACK-8的加入还能让仿真更贴近实物真机调试时不会因为漏加上拉而踩坑。5.3 把实验升级成课程设计的三个改动电位器输入换成SINE信号发生器是最值得做的一步。接上信号源后示波器能同时看到输入正弦波和输出还原波形这在实训报告里是一张很有说服力的截图直接证明AD/DA链路工作在连续信号上。把SINE源频率设为100Hz幅度设为2V偏移量设为2.5V输出波形在示波器上会非常干净。第二个改动是把ADC0809和DAC0832换成STC单片机内置ADC。Proteus库里有STC系列芯片模型直接使用STC12C5A60S2P1口就是ADC输入配置ADC_CONTR寄存器后无需外部芯片整个仿真图缩小三分之一。这段改造成本低适合作为进阶练习。第三个改动是把采集到的数字量通过串口发出用COMPIM模型连接Virtual Terminal就能在屏幕上看到一行行AD值不断刷新。这个功能再往下扩展加上阈值判断和继电器控制就是一个完整的温湿度检测或光照采集系统雏形毕业设计往往就是从这一步开始长出血肉的。串口波特率设9600或115200均可注意和虚拟终端的波特率保持一致否则打印出来的数字会乱码。把扫描时间调到每格20ms、触发源选DA输出通道做完这两项再读数据波形就稳定多了。本文还有配套的精品资源点击获取
返回列表