资讯动态

51单片机汇编实战:AD0809与DA0832接口时序与闭环控制

发布时间:2026/10/15 15:40:10 来源:尧图企业网站定制
简介这份资源是51单片机汇编语言实验系列的第五篇配套附件面向电子工程、自动化及计算机相关专业学生与单片机初学者聚焦AD0809模数转换与DA0832数模转换的接口编程实践。压缩包共10个文件约16KB包含asm汇编源程序、uvproj与uvopt工程配置、lst列表文件、obj与m51编译产物以及htm构建日志等覆盖从源码到编译输出的完整Keil5工程结构下载后可直接打开调试。目前已有3230人学习下载说明该实验在汇编语言与接口编程教学中具有较高参考价值。读者可借助其中的参考代码与注释理解AD0809地址线、控制线配置及转换结果读取流程掌握DA0832数据格式、控制引脚设置与模拟输出方法并熟悉Keil5环境下汇编工程的创建、编译与调试环节从而将模数与数模转换的理论知识落实到具体硬件操作中。1. 从一颗 0809 说起为什么汇编做 AD/DA 实验反而更值得花时间很多人第一次在 51 单片机上做模数转换和数模转换实验第一反应是打开 Keil 写 C调两个库函数读个寄存器就完事。但如果你真的想搞明白“模拟量是怎么一步步变成数字、数字又怎么变回模拟量”的汇编反而是更诚实的路径——它逼着你把每一个控制信号、每一次总线时序、每一个等待周期都亲手写出来。AD0809 和 DA0832 这两颗芯片一个负责把外部电压采进来一个负责把数字量送出去变成电压它们和 51 的接口方式几乎是所有嵌入式采集系统的“最小原型”。这篇文章面向的是正在做单片机实验、想真正看懂时序图而不是只会调库的读者。我会从硬件连接讲到汇编指令从启动转换讲到数据读取把每一步为什么这么写、参数怎么算、哪里容易翻车都拆开说清楚。你不需要有仿真器只要有一块开发板和一颗愿意对着时序图抠细节的心就能跟着复现。2. AD0809 与 51 的硬件接口先搞懂“谁在控制谁”2.1 0809 的引脚功能与总线挂载方式AD0809 是一颗 8 通道、8 位逐次逼近型模数转换器片内自带时钟不需要外部提供时钟信号。它的关键引脚分成三组模拟输入组IN0~IN7、通道选择组A、B、C、控制与数据组START、ALE、EOC、OE、CLK、VCC、GND、REF、REF-。在 51 系统里最常见的接法是把 0809 当作一个外部存储器映射的设备用 P0 口做数据总线用 P2 或 P3 的若干位做控制线。具体来说P0 口接 0809 的 D0~D7同时 P0 口外接一个 8 位锁存器比如 74LS373来分离地址和数据。控制信号方面START 和 ALE 可以连在一起由 51 的写信号WR和片选逻辑共同产生OE 由读信号RD和片选逻辑产生EOC 则接到 51 的一个外部中断引脚INT0 或 INT1或者普通 IO 口上用来查询转换是否结束。通道选择线 A、B、C 可以接 P2 的低三位也可以接锁存器输出的地址线。这里有一个容易被忽略的点0809 的 START 是上升沿启动转换ALE 是上升沿锁存通道地址。很多实验板把这两个脚并联用同一个信号驱动这样在启动转换的同时也锁存了通道号。如果你分开控制就要保证 ALE 的上升沿早于或等于 START 的上升沿否则通道号可能还没锁存进去就开始转换了采到的就是上一个通道的残留值。2.2 地址译码与片选逻辑的设计在 51 的汇编里访问外部设备用的是 MOVX 指令。MOVX DPTR, A 产生写信号MOVX A, DPTR 产生读信号。要让 0809 只在自己的地址范围内响应就需要一个片选逻辑。最简单的做法是用一根地址线比如 P2.7直接当片选低电平有效时选中 0809。这样 0809 的基地址就是 0x7FFF 或者 0x0000取决于你用的是哪根线。假设我们用 P2.7 做片选P2.0~P2.2 做通道选择那么写启动转换的地址可以设为 0x0000P2.70P2.0~P2.2000选中 IN0。读转换结果的地址也是 0x0000因为 OE 和 START 共用同一个片选只是读写信号不同。这种“读写同地址”的设计在 0809 上很常见因为它的控制逻辑就是靠 WR 和 RD 来区分启动和读出的。如果你用的是 P2.6 做片选那基地址就变成 0xBFFF 或 0x4000 之类的值。关键是地址线不能和 P0 口的数据线冲突也不能和 0809 的通道选择线冲突。我一般会把通道选择线放在 P2 的低位片选放在 P2 的高位这样在汇编里可以用位操作指令直接改通道号不用每次都重新算地址。2.3 启动转换与 EOC 查询的汇编实现下面这段代码展示了如何用查询方式启动一次 IN0 通道的转换并把结果读回来。假设片选接 P2.7通道选择接 P2.0~P2.2EOC 接 P3.2。; 0809 查询方式采集 IN0 通道 ; 片选 P2.7通道选择 P2.0~P2.2EOC 接 P3.2 ; 结果存放在 R7 中 AD0809_READ: MOV P2, #00H ; P2.70 选中 0809P2.0~P2.2000 选 IN0 MOV DPTR, #0000H ; 指向 0809 的读写地址 MOV A, #00H ; 任意数据写操作只为了产生 WR 脉冲 MOVX DPTR, A ; 写操作START 上升沿启动转换ALE 锁存通道 WAIT_EOC: JB P3.2, WAIT_EOC ; EOC 为低表示转换中等待其变高 ; 如果 EOC 接的是 INT0也可以用 JNB INT0, $ 来查询 MOVX A, DPTR ; 读操作OE 有效结果送入 A MOV R7, A ; 保存结果到 R7 RET这段代码的逻辑很直接先设置 P2 口让片选有效、通道号锁存然后用 MOVX 写操作产生一个写脉冲这个脉冲同时送到 START 和 ALE启动转换并锁存通道接着循环查询 EOC 引脚直到它变高表示转换完成最后用 MOVX 读操作产生读脉冲打开 OE把数据读进累加器。参数说明P2 口的赋值决定了片选和通道号如果你用的是其他引脚需要相应修改。DPTR 的值必须和硬件译码逻辑一致否则 MOVX 访问的地址不会落到 0809 上。EOC 的查询方式有两种接普通 IO 就用 JB/JNB 轮询接外部中断就用中断服务程序。查询方式简单但占用 CPU中断方式效率高但需要配置中断向量。注意0809 的转换时间典型值为 100 微秒左右在 12MHz 晶振的 51 上这个时间足够执行上百条指令。如果你用查询方式EOC 变高后要尽快读走数据否则下一次转换启动会覆盖旧值。3. DA0832 的接口与输出数字量怎么变成电压3.1 0832 的工作模式与引脚连接DA0832 是一颗 8 位电流输出型数模转换器它有两个数据寄存器输入寄存器和 DAC 寄存器。根据 CS、WR1、WR2、XFER 的不同组合0832 可以工作在直通模式、单缓冲模式和双缓冲模式。在 51 实验里最常用的是单缓冲模式即 WR1 和 WR2 接在一起CS 和 XFER 接在一起这样一次写操作就能同时更新输入寄存器和 DAC 寄存器输出立即变化。引脚方面DI0~DI7 接 P0 口ILE 接高电平允许输入锁存CS 和 XFER 接片选逻辑WR1 和 WR2 接 51 的 WR 信号。输出端 IOUT1 和 IOUT2 接运算放大器把电流转换成电压。RFB 是反馈电阻引脚通常和运放的输出端相连构成一个反相放大器。参考电压 VREF 可以接正电压或负电压决定输出电压的范围。3.2 单缓冲模式下的汇编写数据流程单缓冲模式下写一个数据到 0832 只需要一条 MOVX 写指令。假设片选接 P2.6基地址为 0xBFFFP2.60其他地址线任意代码如下; DA0832 单缓冲模式输出 ; 片选 P2.6数据口 P0 ; 输出值在 R6 中 DA0832_OUT: MOV P2, #0BFH ; P2.60 选中 0832其他位不影响 MOV DPTR, #0BFFFH ; 指向 0832 的写地址 MOV A, R6 ; 取要输出的数字量 MOVX DPTR, A ; 写操作CS 和 WR 有效数据锁存并转换 RET这段代码的核心就是一条 MOVX 写指令。P2 口的赋值让片选有效DPTR 指向正确的地址累加器里的数据被送到 P0 口WR 脉冲的上升沿把数据锁进 0832。输出电流 IOUT1 与输入数字量成正比经过运放后变成电压。参数说明R6 的取值范围是 0x00~0xFF对应输出电压从 0 到满量程。满量程电压由 VREF 和运放反馈电阻决定公式是 Vout -VREF × (D/256)其中 D 是输入数字量。如果你用的是单极性输出VREF 接负电压双极性输出则需要额外的运放电路。0832 的建立时间是 1 微秒左右写完后不需要等待可以直接写下一个值。3.3 参考电压与输出运放的参数计算参考电压的选择直接影响输出范围和分辨率。假设 VREF -5V运放反馈电阻等于 0832 内部的 RFB那么输出电压范围是 0 到 5V分辨率是 5V/256 ≈ 19.5mV。如果你需要 0 到 10V 的输出可以把 VREF 设为 -10V或者调整运放的反馈电阻比例。运放的选择也有讲究。0832 的输出是电流需要运放做 I/V 转换。常用的运放有 LM358、OP07 等。LM358 便宜但失调电压较大适合对精度要求不高的场合OP07 精度高但价格贵适合需要稳定输出的实验。反馈电阻一般取 5kΩ 到 20kΩ太小会导致输出电流过大太大会引入噪声。我一般会在 RFB 和运放输出之间串一个可调电阻方便校准满量程。注意0832 的 IOUT1 和 IOUT2 是电流输出不能直接接示波器或万用表必须经过运放转换。如果你测到的电压一直是 0 或者满幅先检查运放供电和反馈电阻是否接对。4. 联调 AD 与 DA把采集和输出串成一个闭环4.1 用 0809 采集电位器电压并通过 0832 输出把 AD 和 DA 串起来可以做一个最简单的“采集-回放”系统用电位器给 0809 提供 0~5V 的模拟输入0809 转换成数字量后51 把这个数字量直接写给 08320832 再输出对应的电压。如果一切正常你用万用表测 0832 的输出应该和电位器的电压基本一致可能有少量偏差取决于参考电压和运放精度。汇编实现上就是把前面两段代码合并到一个循环里; AD 采集 - DA 输出 闭环测试 ; 0809 片选 P2.7通道 IN00832 片选 P2.6 ; 结果同时保存在 R7 中 LOOP: MOV P2, #00H ; 选 0809通道 IN0 MOV DPTR, #0000H MOV A, #00H MOVX DPTR, A ; 启动转换 WAIT: JB P3.2, WAIT ; 等待 EOC 变高 MOVX A, DPTR ; 读转换结果 MOV R7, A ; 保存到 R7 MOV P2, #0BFH ; 选 0832 MOV DPTR, #0BFFFH MOV A, R7 MOVX DPTR, A ; 输出到 0832 SJMP LOOP ; 无限循环这段代码没有做任何数据处理AD 读什么就 DA 输出什么。实际调试时你可以先用这个最简版本验证硬件通路是否正常。如果 DA 输出和 AD 输入对不上先查参考电压和运放再查地址译码和时序。4.2 加入简单滤波与标度变换的汇编思路直接回放的数据会有抖动因为 0809 的转换结果受噪声影响最低位经常跳变。一个简单的改进是连续采多次取平均值或者中值。在汇编里做平均值可以用累加和右移的方式; 连续采集 8 次取平均值后输出 ; 使用 R0 做循环计数R1 做累加和 AVG_FILTER: MOV R0, #08H ; 采集 8 次 MOV R1, #00H ; 累加和清零 SAMPLE: MOV P2, #00H MOV DPTR, #0000H MOV A, #00H MOVX DPTR, A WAIT2: JB P3.2, WAIT2 MOVX A, DPTR ADD A, R1 ; 累加 MOV R1, A DJNZ R0, SAMPLE ; 循环 8 次 ; 累加和除以 8即右移 3 次 MOV A, R1 RR A RR A RR A ANL A, #1FH ; 屏蔽高 3 位保留有效数据 MOV R7, A MOV P2, #0BFH MOV DPTR, #0BFFFH MOV A, R7 MOVX DPTR, A RET这段代码把 8 次采集结果累加然后右移 3 位实现除以 8。注意右移后高 3 位会移入低位所以要用 ANL 屏蔽掉。平均值滤波能明显减少随机噪声但会降低响应速度。如果你需要更快的响应可以减少采样次数或者改用中值滤波。标度变换是另一个常见需求。比如你想把 0~255 的数字量映射到 0~100 的显示值可以用乘法加除法。51 的汇编没有硬件乘法器标准 8051但可以用移位和加法模拟。如果对精度要求不高直接右移一位相当于除以 2右移两位除以 4以此类推。4.3 用示波器验证时序与建立时间调试 AD/DA 时示波器比万用表更有用。你可以用示波器看 0809 的 START 脉冲、EOC 信号和 OE 脉冲确认时序是否符合数据手册。0809 的 START 脉冲宽度要求大于 100 纳秒EOC 在转换结束后变高OE 脉冲宽度也要大于 100 纳秒。如果脉冲太窄0809 可能不响应如果太宽会影响下一次转换的启动时间。对于 0832你可以看 WR 脉冲和输出波形。0832 的建立时间是 1 微秒写完后输出应该在 1 微秒内稳定。如果你看到输出有台阶或毛刺可能是 WR 脉冲太窄或者数据线有竞争。我一般会把示波器接在运放输出端然后让程序输出一个锯齿波从 0 到 255 循环这样能直观看到 DA 的线性度和建立时间。注意示波器探头的地线要接在系统的模拟地上不要接数字地否则会引入开关噪声。如果波形毛刺很大可以在运放输出端并一个 0.1μF 的电容做低通滤波。5. 避坑与排查那些让实验翻车的细节5.1 现象0809 读出的数据一直是 0xFF 或 0x00原因通道选择错误、参考电压未接、或者 EOC 查询逻辑写反了。如果 EOC 接的是 INT0而你在程序里用 JB 查询可能因为中断标志未清除导致一直等待。另外0809 的 REF 和 REF- 必须接稳定的参考电压如果悬空转换结果会乱跳。解决先用万用表测 REF 和 REF- 之间的电压确认在 5V 左右。然后用示波器看 EOC 引脚启动转换后应该看到它从高变低再变高。如果 EOC 一直不变检查 START 脉冲是否真的送到了 0809。最后确认通道选择线 A、B、C 的电平是否和你要选的通道一致。5.2 现象0832 输出始终为 0 或满幅原因运放供电缺失、反馈电阻未接、或者 CS/WR 逻辑不对。0832 是电流输出如果运放没供电IOUT1 没有回路输出电压就是 0。如果反馈电阻没接运放变成开环输出会饱和到电源轨。解决先测运放的电源引脚确认正负电源正常。然后测 RFB 引脚和运放输出之间的电阻应该在 5kΩ 到 20kΩ 之间。如果用的是单电源运放注意 0832 的输出是电流需要加偏置电路才能输出正电压。最后用示波器看 WR 引脚写操作时应该有一个负脉冲。5.3 现象AD 和 DA 同时工作时互相干扰原因P0 口分时复用AD 和 DA 共用数据总线如果片选逻辑有竞争会导致数据冲突。另外0809 的转换过程中会拉低 EOC如果这个信号和 0832 的控制线有耦合可能误触发。解决检查片选逻辑确保任何时候只有一个设备被选中。可以在片选信号上加 RC 滤波减少毛刺。如果干扰严重把 AD 和 DA 的地址分开用不同的地址线做片选避免同时有效。另外0809 的转换时间较长可以在等待 EOC 期间关闭 0832 的片选减少总线活动。5.4 现象汇编程序烧录后不运行或跑飞原因中断向量未正确设置、堆栈溢出、或者地址译码和程序空间冲突。51 的中断向量表在 0003H、000BH、0013H 等位置如果你用了外部中断 0就要在 0003H 放跳转指令。如果程序里用了大量 PUSH/POP堆栈可能溢出到变量区。解决检查中断向量表确保每个用到的中断都有对应的跳转。堆栈指针 SP 初始值一般设为 07H 或 30H如果程序嵌套较深可以设到 60H 以上。另外确认 MOVX 访问的地址范围和程序存储器的地址范围不重叠否则会读到错误的指令。5.5 现象DA 输出有台阶或非线性原因0832 的输入数据变化太快运放压摆率不够或者参考电压不稳定导致输出比例变化。另外如果 P0 口没有上拉电阻输出高电平时驱动能力不足数据线电平可能达不到 VIH。解决降低数据更新速率或者在运放输出端加低通滤波。参考电压要用稳压源不要直接从 VCC 分压。P0 口必须接 10kΩ 上拉电阻否则 MOVX 写操作时高电平无法建立。如果非线性严重检查 0832 的 DI0~DI7 是否有一位虚焊。6. 进阶技巧用汇编做查表法波形生成与精度校准查表法是我在 51 上做波形生成时最常用的技巧。如果你想让 0832 输出一个正弦波不需要实时计算 sin 值而是预先在程序存储器里放一张 256 点的正弦表然后循环读表输出。这样 CPU 开销极小输出频率只受限于 MOVX 指令的执行速度。; 查表法输出正弦波 ; 正弦表放在程序存储器256 点幅值 0~255 SINE_OUT: MOV DPTR, #SINE_TAB ; 指向正弦表首地址 MOV R0, #00H ; 表索引 NEXT_POINT: MOV A, R0 MOVC A, ADPTR ; 查表 MOV R6, A ; 保存到 R6 MOV P2, #0BFH ; 选 0832 MOV DPTR, #0BFFFH MOV A, R6 MOVX DPTR, A ; 输出 INC R0 ; 索引加 1 MOV DPTR, #SINE_TAB ; 恢复表首地址 SJMP NEXT_POINT ; 循环 SINE_TAB: DB 128, 131, 134, 137, 140, 143, 146, 149 ; ... 后续 248 个点省略实际使用时需要补全这段代码的关键是 MOVC 指令它从程序存储器读数据。R0 做索引每次加 1到 255 后自动回绕到 0因为 R0 是 8 位寄存器。输出频率由循环时间决定在 12MHz 晶振下每次循环大约 20 个机器周期输出频率约为 12MHz/12/20/256 ≈ 195Hz。如果你想要更高频率可以减少表点数或者优化循环。精度校准是另一个实用技巧。0809 和 0832 都有增益误差和偏移误差你可以通过软件校准来补偿。具体做法是给 0809 输入一个已知电压比如 1.000V读回数字量计算实际增益再输入 0V读回数字量计算偏移。然后在程序里对每个采样值做(raw - offset) * gain的运算。在汇编里做乘除法比较麻烦但可以用查表法或者移位近似。我一般会在系统启动时做一次自校准用 0832 输出两个已知电压通过外部跳线送到 0809 的输入读回数字量后计算校准系数存到内部 RAM 里。这样即使更换芯片或温度变化也能保持较好的精度。校准系数不需要高精度8 位就够了因为 0809 本身也只有 8 位分辨率。最后说一个血泪经验汇编调试 AD/DA 时不要一上来就写完整的闭环程序。先写一个最简单的“启动转换-等待 EOC-读数据”的片段用 LED 或者示波器确认数据在变再写一个“写数据到 0832”的片段确认输出在变最后才把两者合并。我见过太多人直接把 AD 和 DA 接在一起结果数据不对查了半天发现是 0809 的通道选错了。分步验证虽然慢但能省下大量猜谜的时间。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑