51单片机从零开始入门教程(模数转换篇)

51单片机从零开始入门教程(模数转换篇)本文介绍了 AD DA 转换器的功能 如模拟 数字 A D 和数字 模拟 D A 转换 以及运算放大器在电路中的应用

大家好,欢迎来到IT知识分享网。

参考教程:[16-1] AD/DA_哔哩哔哩_bilibili

温馨提示:本篇大多数原理可以不必深究,底层已经将复杂的部分封装好了,写代码的时候照着手册写就可以了。

1、AD/DA介绍:

(1)AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号。(根据前面的学习,单片机看起来只能读取引脚当前是处于高电平还是低电平,并不能读取引脚的实际电压值,但是借助ADC模数转换器,单片机可以直接获取引脚的电压值,而不仅仅是单调的1/0)

(2)DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号。(根据前面的学习,单片机看起来只能将引脚置为高电平或是低电平,也就是说只能提供数字信号,但是借助PWM调制,单片机可以给引脚提供模拟信号,而不仅仅是单调的1/0)

(3)AD/DA转换打开了计算机与模拟信号的大门,极大的提高了计算机系统的应用范围,也为模拟信号数字化处理提供了可能。

2、硬件电路模型:

(1)AD转换通常有多个输入通道,用多路选择开关连接至AD转换器,以实现AD多路复用的目的,提高硬件利用率。

(2)AD/DA与单片机数据传送可使用并口(速度快、原理简单),也可使用串口(接线少、使用方便)。

(3)可将AD/DA模块直接集成在单片机内,这样直接写入/读出寄存器就可进行AD/DA转换,单片机的IO口可直接复用为AD/DA的通道。

51单片机从零开始入门教程(模数转换篇)

3、运算放大器:

(1)运算放大器(简称“运放”)是具有很高放大倍数的放大电路单元。内部集成了差分放大器、电压放大器、功率放大器三级放大电路,是一个性能完备、功能强大的通用放大电路单元,由于其应用十分广泛,现已作为基本的电路元件出现在电路图中。

(2)运算放大器可构成的电路有:电压比较器、反相放大器、同相放大器、电压跟随器、加法器、积分器、微分器等。

(3)运算放大器电路的分析方法:虚短、虚断(负反馈条件下)。

51单片机从零开始入门教程(模数转换篇)

(4)四种运放电路:

①电压比较器:

51单片机从零开始入门教程(模数转换篇)

②反向放大器:

51单片机从零开始入门教程(模数转换篇)

③同向放大器:

51单片机从零开始入门教程(模数转换篇)

④电压跟随器:

51单片机从零开始入门教程(模数转换篇)

4、XPT2046是一款4线制电阻式触摸屏控制器,内含12位分率125KHz转换速率逐步逼近型A/D转换器除XPT2046支持从1.5V到5.25V的低电压I/O接口。XPT2046能通过执行两次A/D转换查出被按的屏幕位置,除此之外,还可以测量加在触摸屏上的压力。内部自带2.5V参考电压,可以作为辅助输入、温度测量和电池监测之用,电池监测的电压范围可以从0V到6V。XPT2046片内集成有一个温度传感器。在2.7V的典型工作状态下,关闭参考电压,功耗可小于0.75mW。XPT2046采用微小的封装形式:TSSOP-16,QFN-16和VFBGA-48。工作温度范围为-40C~+85C。与ADS7846、TSC2046、AK4182A完全兼容。

5、XPT2046的时序及命令字:(重点,与写程序密切相关)

51单片机从零开始入门教程(模数转换篇)

(1)给XPT2046发送命令字,XPT2046收到命令后通过DOUT将相应管脚的模拟信号转换为数字信号,然后将数字信号格式的数据一位一位传到主机,不过通过DOUT传到主机的二进制数据为了凑够两个字节,低8位或低4位(取决于分辨率)会使用0填充,软件需要用位移运算符处理一下再转换成十进制数据

(2)8位命令字的含义

51单片机从零开始入门教程(模数转换篇)

(3)单端模式输入配置

51单片机从零开始入门教程(模数转换篇)

51单片机从零开始入门教程(模数转换篇)

(4)性能指标:

分辨率:指AD/DA数字量的精细程度,通常用位数表示。例如,对于5V电源系统来说,8位的AD可将5V等分为256份,即数字量变化最小一个单位时,模拟量变化5V/256=0.0V,所以,8位AD的电压分辨率为0.0V,AD/DA的位数越高,分辨率就越高

②转换速度:表示AD/DA的最大采样/建立频率,通常用转换频率或者转换时间来表示,对于采样/输出高速信号,应注意AD/DA的转换速度。

6、AD模数转换:

(1)该项目需要用到液晶屏模块的代码以及延时函数。

(2)添加缺失的代码文件,然后进行编译,按照主函数中的注释进行调试。

①XPT2046.h文件:

#ifndef __XPT2046_H__ #define __XPT2046_H__ //命令字宏定义(需要对照手册) //全部选择单端输入方式,2位为1 //XP就是X+,YP就是Y+(对应开发板原理图) //8位转换分辨率 #define XPT2046_XP_8 0x9C //1001 1100(1000 1100也可以) #define XPT2046_YP_8 0xDC //1101 1100 #define XPT2046_VBAT_8 0xAC //1010 1100 #define XPT2046_AUX_8 0xEC //1110 1100 //12位转换分辨率 #define XPT2046_XP_12 0x94 //1001 0100(1000 0100也可以) #define XPT2046_YP_12 0xD4 //1101 0100 #define XPT2046_VBAT_12 0xA4 //1010 0100 #define XPT2046_AUX_12 0xE4 //1110 0100 unsigned int XPT2046_ReadAD(unsigned char Command); #endif

②XPT2046.c文件:

#include <REGX52.H> #include "Delay.h" sbit XPT2046_CS = P3^5; sbit XPT2046_DCLK = P3^6; sbit XPT2046_DIN = P3^4; sbit XPT2046_DOUT = P3^7; unsigned int XPT2046_ReadAD(unsigned char Command) { unsigned char i; unsigned int ADVAlue = 0; XPT2046_DCLK = 0; //初始时DCLK为0 XPT2046_CS = 0; //初始时CS取反为1,所以CS为0 for(i = 0; i < 8; i++) //写入8位命令 { XPT2046_DIN = Command & (0x80 >> i); //把命令一位一位地写在DIN上 XPT2046_DCLK = 1; //DCLK上升沿写入一位命令 XPT2046_DCLK = 0; //为下一个上升沿做准备 } Delay(10); for(i = 0; i < 16; i++) //读DOUT的16位数据 { XPT2046_DCLK = 1; //DCLK上升沿,AD往DOUT上发一位数据 XPT2046_DCLK = 0; //为下一个上升沿做准备 if(XPT2046_DOUT) { ADVAlue |= (0x8000 >> i); //把DOUT上的数据一位一位地读进来 } } Delay(10); XPT2046_CS = 1; //读过程结束,CS置为1 //DOUT传来的二进制数据为了凑够两个字节,低8位或低4位会使用0填充(Zero Filled) //所以得到的二进制数据需要把低位的0去掉才能转换为十进制数据 if(Command & 0x08) //判断命令字的第三位 return ADVAlue >> 8; //选择8位转换分辨率的处理 else return ADVAlue >> 4; //选择12位转换分辨率的处理 }

③main.c文件:

#include <REGX52.H> #include "LCD1602.h" #include "Delay.h" #include "XPT2046.h" unsigned int ADValue = 0; void main() { LCD_Init(); LCD_ShowString(1,1,"ADJ NTC RG"); while(1) { /* ADValue = XPT2046_ReadAD(XPT2046_XP_12); //读取X+的电压 //转动AD/DA模块的电位器 //理论上选择8位转换分辨率最大值为0255,12位转换分辨率最大值为4095 LCD_ShowNum(2,1,ADValue,4); */ ADValue = XPT2046_ReadAD(XPT2046_XP_8); //读取X+的电压 LCD_ShowNum(2,1,ADValue,3); ADValue = XPT2046_ReadAD(XPT2046_YP_8); //读取Y+的电压 LCD_ShowNum(2,6,ADValue,3); ADValue = XPT2046_ReadAD(XPT2046_VBAT_8); //读取VABT的电压 LCD_ShowNum(2,11,ADValue,3); Delay(10); } }

7、DA数模转换:

(1)该项目就是之前实现过的呼吸灯,需要延时函数,然后在main.c文件中添加如下代码,进行编译。

#include <REGX52.H> #include "Timer0.h" #include "Delay.h" sbit DA = P2^1; //LED2接收模拟信号 unsigned char Counter, Compare, i; void main() { Timer0_Init(); Compare = 0; while(1) { //本例就是之前实现过的呼吸灯 //在主函数中不断改变自设的比较值,这样定时器0写出来的方波脉冲占空比会不断变化,从而实现PWM调制(数模转换),产生模拟信号 for(i=0;i<100;i++) { Compare = i; Delay(10); } for(i=100;i>0;i--) { Compare = i; Delay(10); } } } void Timer0_Routine() interrupt 1 //CPU响应中断后执行的函数 { Counter++; Counter %= 100; if(Counter < Compare) //计数器和自设比较值比较 { DA = 1; //计数器低于比较值,输出高电平 } else { DA = 0; //计数器高于比较值,输出低电平 } //每次中断结束都要重置计数单元 TL0 = 0xA4; //设置定时初值 TH0 = 0xFF; //设置定时初值 }

(2)将生成的.hex文件下载到开发板中,观察第二盏LED灯的现象。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/133512.html

(0)
上一篇 2025-07-22 16:00
下一篇 2025-07-22 16:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信