微机原理实战:基于8086与DAC0832的波形生成与接口技术详解

📅 2026/8/27 4:33:11
微机原理实战:基于8086与DAC0832的波形生成与接口技术详解
1. 项目概述从“0”和“1”到真实世界的桥梁搞硬件的朋友尤其是玩单片机、嵌入式或者像我一样从古老的8086微机原理入门的肯定绕不开两个核心概念数模转换DAC和模数转换ADC。这俩兄弟说白了就是数字世界和模拟世界之间的“翻译官”。我们写的程序、处理的信号在芯片内部都是高低电平是离散的“0”和“1”。但现实世界是连续的温度、声音、光线、压力这些信号都是平滑变化的模拟量。想让单片机感知环境温度或者驱动一个电机平滑转动就必须靠ADC把连续的模拟信号变成数字量给CPU处理再靠DAC把CPU计算出的数字结果变回模拟量去控制外部设备。这次我打算结合经典的DAC0832芯片把微机原理与接口技术里这部分内容彻底捋清楚。网上资料很多但要么太理论一堆公式看得人头大要么太零碎只讲操作不讲为什么。我希望能写一份真正“能用”的笔记不仅告诉你8086怎么接DAC0832怎么编程更要把每个引脚为什么这么接、每句指令背后的时序逻辑、在Proteus里仿真时容易栽的跟头都掰开揉碎了讲明白。这份笔记的目标就是让你看完后不仅能应付考试更能真正动手在仿真或实际电路里把信号给“玩”起来。2. 核心概念与芯片选型背后的逻辑2.1 为什么是DAC和ADC在深入DAC0832之前我们必须先统一思想为什么接口技术里它俩如此重要这得从微型计算机系统的根本任务说起。计算机是信息处理机器但它只能处理数字信息。而物理世界绝大多数需要监测和控制的对象其状态信息如电压、电流、转速、位移都是模拟的。这就存在一个根本矛盾。ADC模数转换器的作用是“采集”。它将一个时间连续、幅值也连续的模拟信号按照一定的采样频率进行“抓拍”采样并将每次抓拍到的模拟电压值用一个有限位数的二进制数字来表示量化。这个过程必然有信息损失采样频率决定了时间上的精度能不能抓住快速变化的信号量化位数决定了幅度上的精度0.1V和0.1001V能不能区分开。常见的ADC芯片如ADC0809就是8位逐次逼近型ADC的典型代表。DAC数模转换器的作用是“控制”。它接收CPU发送来的一个数字量比如8位二进制数11111111然后输出一个与之成比例的模拟电压或电流。例如假设参考电压是5V对于8位DAC数字量11111111255就对应输出5V10000000128对应输出2.5V00000000对应输出0V。这样我们通过程序改变输出的数字就能精确控制输出电压进而驱动仪表指针偏转、让电机转速变化或者生成特定的波形比如正弦波、三角波。所以ADC是系统的“感官”DAC是系统的“手脚”。没有它们微机系统就是一个与世隔绝的数字孤岛。2.2 为什么选择DAC0832作为学习样板市面上DAC芯片很多从8位到24位从并行接口到串行SPI/I2C。但对于学习微机原理与接口技术尤其是基于经典的8086/8088 CPU体系DAC0832几乎是无可替代的入门首选。原因有四结构经典教学意义强DAC0832是8位分辨率的电流输出型DAC。它内部采用R-2R梯形电阻网络这是最经典、最易于理解的DAC结构之一。其内部包含两个寄存器输入寄存器和DAC寄存器支持双缓冲、单缓冲和直通三种工作方式完美契合了“CPU通过数据总线与接口芯片交换数据”这一核心接口技术思想。弄懂它就为理解更复杂的接口芯片打下了坚实基础。与8086时代背景匹配DAC0832是并行接口芯片数据线直接挂到8086的8位或16位数据总线上地址线通过译码电路连接控制线对接读写和中断信号。这一套“CPU-总线-接口芯片”的连接与控制方式是那个时代微机接口技术的标准范式。学习它就是在学习最本质的接口编程思想端口读写、时序配合。Proteus仿真支持完善在Proteus仿真环境中DAC0832模型非常成熟与8086、8255等芯片的协同仿真效果很好。这意味着你可以无成本、无风险地搭建整个硬件电路并编写汇编或C程序进行验证直观地看到数字量如何变成模拟电压以及波形如何被生成。资料丰富坑点明确正因为经典关于它的中文资料、实验指导、常见问题解答浩如烟海。这降低了学习门槛同时大家踩过的坑也基本被总结全了比如电流输出要接运放转换成电压、参考电压的接法、双缓冲的时序问题等学习时更容易找到解决方案。注意虽然DAC0832是电流输出型但实际应用中几乎100%会接一个运算放大器如uA741、LM358构成一个电流-电压转换电路I-V转换电路将输出电流转换为电压。这是新手最容易忽略的关键一步没有运放你将在示波器上看不到任何正确的电压波形。3. DAC0832芯片深度解析与硬件电路设计3.1 引脚功能与内部结构剖析DAC0832是一个20引脚的双列直插式芯片。要驾驭它必须像熟悉老朋友一样熟悉它的每一根引脚。我们可以将其引脚分为几大类数据与电源类DI0~DI78位数字量输入线。这就是CPU给它的“命令”决定了输出电流的大小。通常直接连接到CPU数据总线或并行接口如8255的输出端口。Vcc电源电压5V ~ 15V通常接5V。AGND模拟地。这是模拟电路部分的地基准必须与数字地DGND在一点相连否则会引入巨大噪声。DGND数字地。Vref参考电压输入。这是一个极其关键的引脚它决定了DAC输出的满量程范围。其电压范围通常为-10V ~ 10V。例如Vref接5V则当数字输入为255时对应的电流输出Iout1达到最大值。这个电压的稳定性和精度直接决定了整个DAC输出精度。控制信号类核心ILE输入锁存允许信号高电平有效。它像是一个总开关只有它为高时后续的CS和WR1才可能起作用。CS片选信号低电平有效。当CPU要访问这片DAC0832时必须通过地址译码电路使该引脚变低。WR1输入寄存器的写信号低电平有效。当ILE1且CS0时WR1的一个负脉冲从高变低再变高会将数据总线DI0~DI7上的数据锁存到输入寄存器中。WR2DAC寄存器的写信号低电平有效。XFER数据传送控制信号低电平有效。当XFER0且WR20时会将输入寄存器中的数据锁存到DAC寄存器中并立即开始转换更新模拟输出。模拟输出类Iout1DAC电流输出1。其值与输入数字量成正比。数字量越大Iout1电流越大。Iout2DAC电流输出2。Iout1 Iout2 常数。通常Iout2接地或接运放的同相端构成单极性输出。内部双缓冲结构是DAC0832的精华所在。它有两级寄存器第一级输入寄存器。由ILE、CS、WR1控制。这级缓冲使得CPU可以随时写入数据而不会立即影响DAC输出。这在多片DAC需要同步更新输出时至关重要。第二级DAC寄存器。由XFER和WR2控制。只有当数据从输入寄存器传送到DAC寄存器后模拟输出才会真正改变。这种设计带来了三种工作模式直通模式将所有控制信号接地常有效数据直接进入转换器。此模式缓冲失效抗干扰差极少使用。单缓冲模式让其中一级寄存器直通只使用另一级作为缓冲。这是最常用的模式接线简单。例如将WR2和XFER接地使DAC寄存器直通只用CS和WR1控制输入寄存器。双缓冲模式两级寄存器都作为缓冲。CPU先分时向多片DAC的输入寄存器写入数据然后同时给所有DAC一个XFER和WR2信号让它们同步更新输出。这是产生复杂波形或多通道同步控制的关键。3.2 典型应用电路设计单极性电压输出纸上谈兵终觉浅我们直接来看一个最常用的、与8086连接的单缓冲模式电路。假设我们使用8086 CPU通过一片8255A并行接口芯片来连接DAC0832。这是经典实验平台的标准配置。电路连接步骤CPU与8255连接8086的数据总线、地址总线、控制总线IOR,IOW等按标准方式连接8255。我们假设8255的A口工作于方式0输出。8255与DAC0832数据线连接将8255的A口PA0~PA7连接到DAC0832的DI0~DI7。DAC0832控制线连接单缓冲模式ILE接5V始终有效。CS和WR1连接到8086系统为DAC0832分配的端口地址译码输出和IOW信号。例如通过译码电路当地址为0x300时CS有效。那么WR1可以接IOW。这样当CPU执行OUT 0x300, AL指令时CS和WR1同时有效将AL中的数据锁存至输入寄存器。XFER和WR2直接接地0V。这意味着DAC寄存器是直通的输入寄存器中的数据会立刻传递到DAC寄存器进行转换。模拟输出电路关键Iout1连接到一个运算放大器如uA741的反相输入端-。Iout2直接接地或接运放的同相输入端如果同相端接地。在运放的输出端Vout和反相输入端-之间连接一个反馈电阻Rfb。DAC0832内部已集成一个Rfb约15kΩ可以直接使用将芯片的Rfb引脚9脚连接到运放输出端。运放的同相输入端通过一个电阻接地或接参考地。运放需要±12V或±15V供电视型号而定。电路原理分析这个运放电路构成了一个电流-电压转换器。根据运放“虚短”“虚断”原理反相输入端电压与同相输入端相同均为0V即“虚地”。因此DAC0832输出的电流Iout1全部流经反馈电阻Rfb。输出电压Vout -Iout1 * Rfb。 而Iout1与输入数字量D和参考电压Vref的关系为Iout1 (D / 256) * (Vref / R)其中R为内部梯形网络等效电阻。 最终得到Vout - (D / 256) * Vref * (Rfb / R)。通常设计使得Rfb R于是公式简化为Vout - (D / 256) * Vref。 例如Vref 5V当D255时Vout - (255/256)*5 ≈ -4.98V当D128时Vout ≈ -2.5V。输出是负电压。如果需要正电压可以在后面再加一级反相比例放大器或者使用特殊的接法。实操心得在Proteus中仿真时务必给运放接上正确的正负电源如VCC12V VEE-12V否则运放不工作输出始终为0。这是仿真中最常见的“低级错误”。另外模拟地AGND和数字地DGND在原理图上可以用同一个“GROUND”符号但在心里和实际PCB布局时必须清楚它们是不同的网络最终应单点连接。4. 基于8086与Proteus的软件编程与仿真实战4.1 汇编语言编程驱动DAC0832硬件搭好了接下来就是让CPU“说话”。我们以8086汇编为例假设DAC0832的端口地址为300H由CS译码决定8255的A口地址为318H控制字端口地址为31BH。目标是产生一个锯齿波。; 假设8255 A口、B口、C口及控制口地址分别为 318H, 319H, 31AH, 31BH ; DAC0832数据口地址为 300H CODE SEGMENT ASSUME CS:CODE START: ; 1. 初始化8255设置A口为方式0输出 MOV DX, 31BH ; 8255控制口地址 MOV AL, 10000000B ; 控制字A口方式0输出B口方式0输出未用C口输出未用 OUT DX, AL ; 2. 产生锯齿波循环 WAVE_GEN: MOV AL, 0 ; 数字量从0开始 OUT_LOOP: ; 先送数据到8255 A口 MOV DX, 318H OUT DX, AL ; 数据输出到8255 A口 ; 再将8255 A口的数据“写”到DAC0832通过CS和WR1有效 MOV DX, 300H ; DAC0832的端口地址 OUT DX, AL ; 执行OUT指令时IORC有效结合地址译码使CS有效同时IOW有效作为WR1完成数据锁存与转换 INC AL ; 数字量加1形成上升沿 JMP OUT_LOOP ; 循环当AL从0加到255溢出回0时形成锯齿波下降沿 CODE ENDS END START程序逻辑深度解析初始化首先配置8255的工作方式。这里A口是简单的输出数据从CPU到8255是直通的。核心输出循环程序的核心是一个无限循环。每次循环AL寄存器中的值从0开始通过两条OUT指令输出。第一条OUT DX, ALDX318H将数据暂存到8255的A口输出锁存器。这一步在某些简化电路中可以省略如果DAC直接接数据总线但通过8255可以增强驱动和隔离。第二条OUT DX, ALDX300H这是关键。当CPU执行这条指令时会发生以下事情 a. 地址总线出现300H经过译码电路使得DAC0832的CS引脚变为低电平有效。 b. 控制总线发出IOW写信号这个信号连接到DAC0832的WR1引脚产生一个负脉冲。 c. 由于ILE一直为高CS和WR1同时有效数据总线上的数据即AL的值被锁存进DAC0832的输入寄存器。 d. 因为我们将XFER和WR2接地了单缓冲模式输入寄存器的数据立刻被传递到DAC寄存器并启动内部的R-2R网络进行数模转换。 e. 转换结果是电流Iout1变化经过外部的运放电路输出电压Vout随之改变。波形形成INC AL指令使数字量线性增加输出电压Vout负电压的绝对值也随之线性增加因为Vout -k * D。当AL从0递增到255时输出一个锯齿波的上升沿。当AL从255加1溢出变为0时输出电压跳变回起点形成下降沿从而产生一个连续的锯齿波。注意事项这个循环没有延时因此锯齿波的频率会非常高取决于CPU执行循环一次的时间。要产生特定频率的波形必须在INC AL后或每次输出后插入延时子程序。通过调整延时可以精确控制波形周期。4.2 Proteus仿真搭建与调试技巧理论懂了代码写了不上仿真跑一遍心里总不踏实。Proteus是学习微机原理的神器。下面是在Proteus 8中搭建上述系统的关键步骤和避坑指南元件选取Microprocessor ICs-8086(选择8086模型不是8086 (CMOS)后者可能需要额外配置)。Microprocessor ICs-8255A。Data Converters-DAC0832。Operational Amplifiers-LM358或UA741双电源运放。Resistors,Capacitors,Ground,Power等基础元件。还需要74LS373之类的地址锁存器以及74LS138地址译码器来构成最小系统。关键连线与配置8086配置双击8086在Advanced Properties里将External Clock Frequency设置为你的实验频率如5MHz。在Program File一栏选择你编译好的.exe文件由汇编源程序经MASM汇编、LINK连接生成。这是能让程序运行的关键时钟与复位给8086的CLK引脚接一个时钟源如DCLOCK频率与配置一致。RESET引脚接一个高电平信号仿真开始时下拉再上拉实现复位。地址译码使用74LS138。将8086的地址线如A15, A14, A13连接到138的输入A0参与选择奇偶端口。确保DAC0832的CS和8255的CS分别由138的不同输出端驱动且地址与你程序中定义的300H,318H对应。运放电路务必给UA741或LM358接上正负电源如VCC12V,VEE-12V。将DAC0832的Iout1接运放反相端Rfb引脚9接运放输出端。运放输出端接一个电压探针或示波器通道。仿真运行与观测点击Proteus的运行按钮。在运放输出端添加一个模拟示波器ANALOGUE OSCILLOSCOPE。运行后你应该能在示波器上看到一个锯齿波。如果是一条直线或为0请按以下顺序排查 a.检查电源8086、8255、DAC0832的VCC接5V了吗运放的正负电源接了吗 b.检查地线所有GND引脚都接到地了吗 c.检查程序加载8086的Program File设置正确吗.exe文件路径对吗 d.检查控制信号暂停仿真右键点击DAC0832或8255选择Show Animation Options或直接查看引脚逻辑状态。手动执行你的程序观察CS,WR1,WR2,XFER等关键引脚的电平变化是否与预期一致。 e.检查参考电压Vref引脚接了吗是稳定的电压吗一个经典的Proteus仿真问题如果你发现输出波形有严重的“台阶”感不光滑这很可能是因为仿真步长Simulation Step Time设置过大。Proteus为了加快仿真速度默认步长可能不足以分辨DAC输出快速变化的细节。解决方法在菜单栏System-Set Animation Options中将Simulation Speed调慢如调到1ms或更小或者减少Step Time如设为1us。这样示波器显示的波形就会平滑很多。5. 核心进阶波形生成与双缓冲模式应用5.1 如何产生正弦波、三角波等任意波形产生锯齿波只需让数字量线性增减。要产生更复杂的波形如正弦波核心思想是“查表法”。制作正弦表我们知道正弦函数值在[-1, 1]之间变化。对于8位DAC假设我们采用单极性输出电路最终输出0~Vref的正电压我们需要将正弦波的幅值映射到0-255之间。公式数据值 D 128 127 * sin(2π * i / N)。其中i从0到N-1N是一个周期内采样的点数。128是零点偏移对应0V127是幅值。例如取N64个点用Excel或编程计算出一组64个介于0-255之间的数据这就是正弦表。编程实现; 假设正弦表已定义在数据段表首地址为SIN_TABLE LEA SI, SIN_TABLE ; SI指向正弦表 MOV CX, 64 ; 一个周期的点数 NEXT_POINT: MOV AL, [SI] ; 从表中取一个数据点 MOV DX, 300H ; DAC端口地址 OUT DX, AL ; 输出产生一个电压台阶 CALL DELAY ; 调用延时子程序控制每个点的持续时间从而决定波形频率 INC SI ; 指向下一个点 LOOP NEXT_POINT ; 循环输出一个周期 JMP NEXT_POINT ; 重复输出形成连续波形通过调整DELAY子程序的延时可以改变正弦波的频率。点数N越多生成的波形阶梯越细越接近光滑正弦波但对存储空间和速度要求越高。5.2 双缓冲模式实战两路DAC同步输出单缓冲模式足以应对单路信号输出。但当需要两路或多路模拟输出严格同步变化时例如X-Y示波器显示、立体声音频双缓冲模式就大显身手了。场景使用两片DAC0832分别控制一个图形的X坐标和Y坐标。硬件连接两片DAC0832的DI0~DI7都连接到CPU的数据总线。两片DAC的ILE都接高电平。为每一片分配独立的CS信号如CS1和CS2分别连接到不同的地址译码输出用于单独写入各自的输入寄存器。将两片DAC的XFER引脚连在一起并共同连接到一个独立的控制信号如XFER_SYNC。将两片DAC的WR2引脚连在一起共同连接到CPU的IOW或另一个独立写信号。软件操作流程CPU先通过CS1和WR1将X坐标数据写入第一片DAC的输入寄存器。CPU再通过CS2和WR1将Y坐标数据写入第二片DAC的输入寄存器。此时两片DAC的模拟输出都还未改变CPU最后发出一个信号使XFER_SYNC和WR2同时有效一个负脉冲。在这个脉冲作用下两片DAC同时将各自输入寄存器中的数据锁存到各自的DAC寄存器中并同时开始转换。两路模拟输出同步更新实现了精确的同步控制。这种“先分别准备再同时更新”的机制避免了因CPU顺序写入而造成两路输出变化的时间差对于要求精确同步的应用至关重要。6. 常见问题、故障排查与经验总结6.1 硬件连接与测量问题问题输出为固定电压或0V不随程序变化。排查首要检查电源和地用万用表测量DAC0832的VccPin20是否为5V运放电源是否正常。检查所有GND连接是否可靠。检查控制信号用逻辑分析仪或示波器查看CS、WR1、WR2、XFER的波形。在执行输出指令时CS和对应的WR信号应有清晰的负脉冲。如果没有检查地址译码电路和CPU的控制总线连接。检查数据线在执行输出指令时用示波器查看数据线DI0~DI7上是否有对应的数据波形。如果没有检查CPU数据总线到DAC的连接或中间接口芯片如8255的配置。检查参考电压Vref测量Vref引脚Pin8电压是否稳定且符合预期如5V。Vref接错或浮动会导致输出异常。问题输出波形有毛刺或台阶不光滑。排查软件问题检查程序中输出数据后是否有不必要的操作或中断打扰导致输出间隔不均匀。确保输出循环是稳定周期性的。硬件问题这通常是干扰或时序问题。在数据线和控制线上靠近DAC芯片电源引脚处增加去耦电容如0.1uF瓷片电容。确保电源质量。在Proteus中调整仿真步长见4.2节。运放问题运放响应速度不够压摆率低无法跟上DAC输出的快速变化。尝试更换更高速度的运放模型。问题输出幅度不对或极性反了。排查核对计算公式回顾Vout - (D / 256) * Vref * (Rfb / R)。检查你的Vref值、Rfb连接使用内部Rfb时连接9脚到运放输出。检查运放电路最常见的单运放I-V转换电路输出是负电压。如果你期望正电压需要在后面加一级反相放大器增益为-1或者采用另一种将Iout2接运放同相端的电路结构输出正电压但公式不同。6.2 软件编程与仿真调试问题问题Proteus仿真时程序似乎没运行波形没变化。排查确认程序文件加载双击8086百分百确认Program File路径指向了正确的.exe或.hex文件。这是最常犯的错误。检查CPU时钟8086的CLK引脚必须接有时钟信号且频率与芯片配置中External Clock Frequency一致。执行复位在仿真开始前确保RESET引脚有一个从高到低再到高的过程。可以在RESET引脚接一个单次脉冲发生器。查看汇编列表在源代码中设置断点单步执行观察寄存器和端口状态变化确认程序逻辑是否正确执行到了输出指令。问题产生的波形频率不对。分析波形频率由两个因素决定一个周期内的点数N和每个点之间的延时T。总周期T_total N * T频率f 1 / T_total。调整如果你想提高频率要么减少点数N但会降低波形质量要么缩短延时子程序DELAY的执行时间。精确控制频率需要精确计算CPU时钟周期和循环指令的耗时。最后一点个人体会学习DAC/ADC一定要坚持“软硬结合”。看懂时序图比背下引脚定义更重要在Proteus里调通一个锯齿波比读十遍理论教材收获都大。遇到问题按照“电源-地-时钟-复位-控制信号-数据信号”的顺序排查八成都能解决。DAC0832就像一把钥匙帮你打开了微机控制模拟世界的大门理解了它后面再接触SPI接口的DAC、Σ-Δ型ADC你会发现核心思想都是相通的——如何让数字的“0”和“1”精准、高效地与真实的物理量对话。