C51学习归纳13 --- AD/DA转换

AD/DA转换实现了计算机和模拟信号的连接,扩展了计算机的应用场景,为模拟信号数字化提供了底层支持。

AD转换通常是多个输入通道,使用多路选择器连接到AD开关,实现AD多路复用的目的,提高利用率。

AD/DA转换可以使用串口(快速、简单),串口(线少,方便)。

我们可以将AD/DA模块化,直接集成在单片机中,这样就可以直接写入/读取寄存器实现AD/DA转换。

一、AD/DA原理

本节将会用到AD芯片2046,涉及到SPI时序。XPT芯片,可以直接完成AD转换,我们只需要学会读取寄存器的值就ok。

CS是片选,是否工作。DCLK是时钟,发出规律的波形。DIN,数据输入(主机发送),在DCLK的上升沿输入。DOUT,数据输出(从机接收),在DCLK的下降沿输出。

DA的实现方法1:T型电阻网络DA转换器

通过控制D0~7的值,决定开关的闭合。

DA的实现方法2:PWM型DA转换器

对PWM波进行低通滤波,获取平均值,红棉的电压跟随器是为了让电路具备更强的驱动能力。

AD的实现方法:逐次逼近型AD转换器

IN0~7是8个通道,提高AD模块的利用率,每次用DAC输出一个模拟值和输入的模拟值对比,不断调整,知道二者几乎相等,此时两者的数字信号的值也应该一样,实现了由已知推断未知的功能。

二、AD转换案例 --- 读取热敏、可调、光敏电阻的值

我们先说明为什么这个是AD转换,因为电阻分压是一个连续的值,我们用数字的形式表现此刻的大小,所以是AD转换。

我们用到2046芯片,所以要先使用SPI写时序。

复制代码
#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;
}

一开始直接对引脚定义,方便使用和阅读。我们的任务就是从P3_7读出数据。第一个for循环是写入控制命令,因为是串行,所以每次只能读取一位,我们要循环8次,上升沿读入。第二个for循环,我们要连续读出16位数据,这是SPI规定的,所以我们循环16次,每次下降沿读出一位。最后结束时,停用芯片。为什么将最后的数据右移8位?因为如果我们在设置Command的时候设置为8位模式,16的后8位将用0填充,所以我们要右移8位。

Command的值的设置,需要参考手册。

复制代码
#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

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

三、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
	}
}

对DAC模块的端口P2_1直接输入,我们的数字信号,PWM,经过低通滤波,获得平均值得到了我们最终的模拟输出。

实现呼吸灯效果。

相关推荐
蓝桉~MLGT23 分钟前
中级软考(软件工程师)通关秘籍——核心知识点图表全汇总与扩展解析
学习·软件工程
fengci.33 分钟前
CTF+随机困难题目
android·开发语言·前端·学习·php
一尘之中35 分钟前
系统架构设计师知识体系综述:从核心概念到职业成长
学习·系统架构·ai写作
你怎么知道我是队长36 分钟前
计算机系统基础22---计算机的基本组成---IO控制方式
单片机·嵌入式硬件
Daydream.V36 分钟前
Transform学习
学习
風清掦42 分钟前
【STM32学习笔记-12】Unix 时间戳、BKP 备份寄存器与 RTC 实时时钟
笔记·stm32·单片机·嵌入式硬件·学习·实时音视频·unix
python零基础入门小白1 小时前
Transformer、Token、RAG全解析,一篇读懂大模型核心机制!
人工智能·深度学习·学习·语言模型·大模型·transformer·产品经理
hoiii1871 小时前
基于STM32的扫地机器人源码工程
stm32·单片机·机器人
我是发哥哈2 小时前
东莞AI培训主流方案横向评测:5大选型维度解析
大数据·人工智能·学习·机器学习·chatgpt·ai编程
千寻girling2 小时前
机器学习 | 感知机 | 尚硅谷学习
人工智能·学习·机器学习