51单片机中的AD/DA模块

目录

一、什么是AD转换

二、什么是DA转换

三、相关硬件电路

​编辑​编辑​编辑​编辑四、运算放大器

​编辑​编辑​编辑五、XPT2046芯片介绍


 

一、什么是AD转换

ADC(analog to digital converter)也称为模数转换器,是指一个将模拟信号转变为数字信号。单片机在采集模拟信号时,通常都需要在前端加上 A/D 芯片。

fc556c6c686b41619c51781dfdb0252b.png3973213284a0487fae42f4ad7df58dce.png

1. 采样:采样是指在一定时间间隔内获取模拟信号的离散样本。采样频率决定了每秒采样的样本数,通常以赫兹(Hz)为单位。

2. 量化和编码:量化是将连续的模拟信号幅度值转换为离散的数字值。通过将模拟信号幅度值映射到离散级别上,实现对模拟信号的离散表示;编码将量化后的样本值表示为二进制数据,以便将其存储或传输。常用的编码方法包括二进制编码和压缩编码。

二、什么是DA转换

DAC(Digital to analog converter)即数字模拟转换器,它可以将数字信号转换为模拟信号。它的功能与 ADC 相反。在常见的数字信号系统中,大部分传感器信号被转化成电压信号,而 ADC 把电压模拟信号转换成易于计算机存储处理的数字编码,由计算机处理完成后,再由 DAC 输出电压模拟信号,该电压模拟信号常常用来驱动某些执行器件,使人类易于感知。如音频信号的采集及还原就是这样一个过程。

821ec3db3b56462d89b2ded5fb742846.png942c48cf0e164700881447f02cc51606.png1. 数字数据:数字数据通常以二进制形式表示,并存储在计算机系统或其他数字设备中。

2. 重构:DA转换器通过重构技术将数字数据转换为连续的模拟信号。重构过程中,数字样本被插值和滤波,使其变得连续且光滑。

3. 输出模拟信号:DA转换器的输出是通过模拟电路和滤波器处理后的连续模拟信号。输出信号的连续性和精确性取决于DA转换器的性能。

三、相关硬件电路

db35281f520c40f8a31ae40b89fba5bf.png6a4baac4e2b0429ead774a38d2175e60.pnge7b0a0b590b443f58888deb310a2aacb.png0ddc19ccf2cd49a0af51ff28218d509a.png四、运算放大器

50d2bde0b46c4c3c93565a3dc79210b9.png51feaf4840784369817c8b895c5cc620.png30dc14f82e62424f914b61944482abd4.png五、XPT2046芯片介绍

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 采用微小的封装形式:TSSOP16,QFN-16 和 VFBGA-48。工作温度范围为-40℃~+85℃。与ADS7846、TSC2046、AK4182A 完全兼容。f11a9e759ade4f54b2678e98cec7cba9.png

对DIN进行剖析:

1.起始位——第一位,即 S 位。控制字的首位必须是 1,即 S=1。在 XPT2046 的 DIN 引脚检测到起始位前,所有的输入将被忽略。

2.地址——接下来的 3 位(A2、A1 和 A0)选择多路选择器的现行通道,触摸屏驱动和参考源输入。

3.模式选择位,用于设置 ADC 的分辨率。MODE=0,下一次的转换将是 12 位模式;MODE=1,下一次的转换将是 8 位模式。

4.SER/ ——DFR ——SER/ —— DFR 位控制参考源模式,选择单端模式(SER/ —— DFR =1),或者差分模式(SER/ ——DFR =0)。在X坐标、Y坐标和触摸压力测量中,为达到最佳性能,首选差分工作模式。参考电压来自开关驱动器的电压。在单端模式下,转换器的参考电压固定为VREF相对于GND引脚的电压。(在此学习中,X-直接接地,所以我们只需在单端模式下读取X+即可)

5.低功率模式选择位。若为 11,器件总处于供电状态;若为 00,器件在变换之间处于低功率模式。(此处我们选用00)

*模式选择位插图

4d180ad231eb4fcab37f9eced2945eb4.png

1.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  XPT2046读取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++)//此循环依次将DIN中的八位发出去
	{
		XPY2046_DIN=Command&(0x80>>i);
		XPY2046_DCLK=1;//上升沿后DIN发出数据
		XPY2046_DCLK=0;//下降沿后循环8次
	}
	for(i=0;i<16;i++)//此循环依次将DOUT中的16位读出来
	{
		XPY2046_DCLK=1;
		XPY2046_DCLK=0;//先给上升沿再给下降沿数据才会到DOUT
		if(XPY2046_DOUT){Data|=(0x8000>>i);}
	}
	XPY2046_CS=1;
    if(Command&0x08)
    {
    return Data>>8;//当DIN中的MODE=1,DOUT读取八位而时序中有16位且后八位为零填充 所以右移八位目的是只读取前八位
    }
    else
    {
    return Data>>4;//当DIN中的MODE=0,DOUT读取十二位而时序中有16位且后4位为零填充 所以右移4位目的是只读取前十二位
    }
    
}

2.XPT2046.h

#ifndef __XPT2046_H__
#define __XPT2046_H__
//分别对VBAT、AUX、XP、YP进行测量
#define XPT2046_VBAT_8	0xAC
#define XPT2046_AUX_8	0xEC
#define XPT2046_XP_8		0x9C//0x8C  
#define XPT2046_YP_8		0xDC        

#define XPT2046_VBAT_12	0xA4
#define XPT2046_AUX_12	0xE4
#define XPT2046_XP_12		0x94//0x84
#define XPT2046_YP_12		0xD4  

unsigned int XPT2046_ReadAD(unsigned char Command);

#endif

(1).AD模数转换代码

#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_8);		//读取AIN0,可调电阻
		LCD_ShowNum(2,1,ADValue,3);				//显示AIN0
		ADValue=XPT2046_ReadAD(XPT2046_YP_8);		//读取AIN1,热敏电阻
		LCD_ShowNum(2,6,ADValue,3);				//显示AIN1
		ADValue=XPT2046_ReadAD(XPT2046_VBAT_8);	//读取AIN2,光敏电阻
		LCD_ShowNum(2,11,ADValue,3);			//显示AIN2
		Delay(100);
	}
}

现象:调节可调电阻时屏幕的ADJ值会发生变化,相应的热敏电阻和光敏电阻与其一样

(2).DA模数转换代码

#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
	}
}

现象:AD/DA模块的灯会以呼吸灯形式呈现

 

  • 2
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基于51单片机实现18650电池电压采样并输出电量百分比的程序,供您参考: ``` #include <reg51.h> #define ADC_RES_MAX 1023 // ADC采样最大值 #define V_REF 3.3 // 参考电压为3.3V #define V_BAT_MAX 4.2 // 电池最大电压为4.2V #define V_BAT_MIN 3.0 // 电池最小电压为3.0V #define V_BAT_WARN 3.5 // 电池电量过低警告阈值为3.5V unsigned int ADC_Value; // 定义全局变量,用于存储采样结果 void ADC_Init() { ADC_CONTR = 0x87; // 设置ADC工作模式 } void ADC_ISR() interrupt 5 { ADCCON1 &= ~0x40; // 关闭ADCADC_Value = (unsigned int)ADC_RES * 256 + ADC_RESL; // 读取采样结果 ADCCON1 |= 0x40; // 重新开启ADC断 } void main() { unsigned char battery_percent; // 定义电量百分比变量 ADC_Init(); // 初始化ADC模块 EA = 1; // 开启总ADCCON1 |= 0x40; // 启动ADC转换 while (1) { // 计算电池电压对应的采样值 unsigned int adc_res = ADC_Value * V_REF / ADC_RES_MAX; // 计算电池电压值 float v_bat = adc_res * V_BAT_MAX / V_REF; // 计算电池电量百分比 battery_percent = (v_bat - V_BAT_MIN) * 100 / (V_BAT_MAX - V_BAT_MIN); // 如果电量过低,输出警告信息 if (v_bat < V_BAT_WARN) { // 在这里可以将警告信息输出到串口或LCD等外设 } // 在这里可以将电量百分比输出到串口或LCD等外设 } } ``` 在上面的代码,我们首先定义了一些常量,例如 ADC 采样最大值、参考电压、电池最大电压、电池最小电压等。然后通过 `ADC_Init()` 函数初始化 ADC 模块,并通过 `ADC_ISR()` 函数定义 ADC 断服务程序。在主程序,我们启动 ADC 转换,并在一个无限循环读取和处理采样结果。 在循环,我们首先计算电池电压对应的 ADC 采样值,然后根据电压值计算电池电量百分比。如果电量过低,则可以输出警告信息。最后,我们可以将电量百分比输出到串口或 LCD 等外设上。 需要注意的是,由于不同的电池类型和容量,电池电压和电量百分比之间的关系可能会有所不同。因此,在实际应用,需要根据具体的电池规格和特性进行调整和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值