AD/DA介绍

  • AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号
  • DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号
  • AD/DA转换打开了计算机与模拟信号的大门,极大的提高了计算机系统的应用范围,也为模拟信号数字化处理提供了可能

硬件电路模型

  • AD转换通常有多个输入通道,用多路选择开关连接至AD转换器,以实现AD多路复用的目的,提高硬件利用率
  • AD/DA与单片机数据传送可使用并口(速度快、原理简单),也可使用串口(接线少、使用方便)
  • 可将AD/DA模块直接集成在单片机内,这样直接写入/读出寄存器就可进行AD/DA转换,单片机的IO口可直接复用为AD/DA的通道

硬件电路

运算放大器

  • 运算放大器(简称“运放”)是具有很高放大倍数的放大电路单元。内部集成了差分放大器、电压放大器、功率放大器三级放大电路,是一个性能完备、功能强大的通用放大电路单元,由于其应用十分广泛,现已作为基本的电路元件出现在电路图中
  • 运算放大器可构成的电路有:电压比较器、反相放大器、同相放大器、电压跟随器、加法器、积分器、微分器等

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

运放电路

DA原理

  • T型电阻网络DA转换器:

  • 输出电压 V_O=((D7~D0))/256×(V_REF×R_fb)/R
  • 当Rfb=R时,V_O=((D7~D0))/256×V_REF
  • PWM型DA转换器:

  • 输出电压 V_O=(PWM占空比)×V_H
  • 逐次逼近型AD转换器:

  • 输出数字量 (D7~D0)=V_IN/V_REF ×256…… 结果取整

AD/DA性能指标

  • 分辨率:指AD/DA数字量的精细程度,通常用位数表示。例如,对于5V电源系统来说,8位的AD可将5V等分为256份,即数字量变化最小一个单位时,模拟量变化5V/256=0.01953125V,所以,8位AD的电压分辨率为0.01953125V,AD/DA的位数越高,分辨率就越高
  • 转换速度:表示AD/DA的最大采样/建立频率,通常用转换频率或者转换时间来表示,对于采样/输出高速信号,应注意AD/DA的转换速度

XPT2046

XPT2046时序

AD数模转换

main.c

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "XPT2046.h"

unsigned int ADValue;

void main(void)
{
    LCD_Init();
    LCD_ShowString(1,1,"ADJ  NTC  GR");
    while(1)
    {
        ADValue=XPT2046_ReadAD(XPT2046_XP);        //读取AIN0,可调电阻
        LCD_ShowNum(2,1,ADValue,3);                //显示AIN0
        ADValue=XPT2046_ReadAD(XPT2046_YP);        //读取AIN1,热敏电阻
        LCD_ShowNum(2,6,ADValue,3);                //显示AIN1
        ADValue=XPT2046_ReadAD(XPT2046_VBAT);    //读取AIN2,光敏电阻
        LCD_ShowNum(2,11,ADValue,3);            //显示AIN2
        Delay(100);
    }
}

XPT2046.c

#include <REGX52.H>
#include <INTRINS.H>

//引脚定义
sbit XPY2046_DIN=P3^4;
sbit XPY2046_CS=P3^5;
sbit XPY2046_DCLK=P3^6;
sbit XPY2046_DOUT=P3^7;

/**
  * @brief  ZPT2046读取AD值
  * @param  Command 命令字,范围:头文件内定义的宏,结尾的数字表示转换的位数
  * @retval AD转换后的数字量,范围:8位为0~255,12位为0~4095
  */
unsigned int XPT2046_ReadAD(unsigned char Command)
{
    unsigned char i;
    unsigned int Data=0;
    XPY2046_DCLK=0;
    XPY2046_CS=0;
    for(i=0;i<8;i++)
    {
        XPY2046_DIN=Command&(0x80>>i);
        XPY2046_DCLK=1;
        XPY2046_DCLK=0;
    }
    for(i=0;i<16;i++)
    {
        XPY2046_DCLK=1;
        XPY2046_DCLK=0;
        if(XPY2046_DOUT){Data|=(0x8000>>i);}
    }
    XPY2046_CS=1;
    return Data>>8;
}

XPY2046.h

#ifndef __XPT2046_H__
#define __XPT2046_H__

#define XPT2046_VBAT    0xAC
#define XPT2046_AUX        0xEC
#define XPT2046_XP        0x9C    //0xBC
#define XPT2046_YP        0xDC

unsigned int XPT2046_ReadAD(unsigned char Command);

#endif

DA数模转换

main.c

#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"

sbit DA=P2^1;

unsigned char Counter,Compare;    //计数值和比较值,用于输出PWM
unsigned char i;

void main()
{
    Timer0_Init();
    while(1)
    {
        for(i=0;i<100;i++)
        {
            Compare=i;            //设置比较值,改变PWM占空比
            Delay(10);
        }
        for(i=100;i>0;i--)
        {
            Compare=i;            //设置比较值,改变PWM占空比
            Delay(10);
        }
    }
}

void Timer0_Routine() interrupt 1
{
    TL0 = 0x9C;        //设置定时初值
    TH0 = 0xFF;        //设置定时初值
    Counter++;
    Counter%=100;    //计数值变化范围限制在0~99
    if(Counter<Compare)    //计数值小于比较值
    {
        DA=1;        //输出1
    }
    else                //计数值大于比较值
    {
        DA=0;        //输出0
    }
}

参考资料

51单片机入门教程-2020版 程序全程纯手打 从零开始入门\_哔哩哔哩\_bilibili

最后修改:2023 年 10 月 21 日
如果觉得我的文章对你有用,请随意赞赏