STC89C52单片机学习——第36节: [16-2] AD模数转换&DA数模转换

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做!

本文写于:2025.03.24

51单片机学习——第36节: [16-2] AD模数转换&DA数模转换

前言

   本次笔记是用来记录我的学习过程,同时把我需要的困难和思考记下来,有助于我的学习,同时也作为一种习惯,可以督促我学习,是一个激励自己的过程,让我们开始51单片机的学习之路。
   欢迎大家给我提意见,能给我的嵌入式之旅提供方向和路线,现在作为小白,我就先学习51单片机了,就跟着B站上的江协科技开始学习了.
   在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习笔记内容,因为我之前有一个开发板,我大概率会用我的板子模仿着来做.让我们一起加油!
   另外为了增强我的学习效果:每次笔记把我不知道或者问题在后面提出来,再下一篇开头作为解答!

开发板说明

   本人采用的是慧净的开发板,因为这个板子是我N年前就买的板子,索性就拿来用了。不再另外购买视频中的普中开发板了。
   原理图如下
在这里插入图片描述
视频中的都用这个开发板来实现,如果有资源就利用起来。
仔细看了看:开发板的晶振为:11.0592Mhz;12Mhz晶振是用来给CH340G芯片外置晶振;

下图是实物图
在这里插入图片描述

引用

51单片机入门教程-2020版 程序全程纯手打 从零开始入门
还参考了下图中的书籍:
手把手教你学51单片机(C语言版)
在这里插入图片描述
STC89C52手册
在这里插入图片描述

一、数模转换

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

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;		//不初始化也没问题
	XPT2046_CS=0;
	
	//命令字8位发送出去
	for(i=0;i<8;i++)
	{
	XPT2046_DIN=Command&(0x80>>i);
	XPT2046_DCLK=1;			//满足时序>1.5us
	XPT2046_DCLK=0;
	}
	
	
}
//可以加一段延迟,也可不加
	//调用时序连续读两个字节
	
	for(i=0;i<16;i++)
	{
	XPT2046_DCLK=1;			//下降沿后数据放到线上
	XPT2046_DCLK=0;
	if(XPT2046_DOUT){ADValue|=(0x8000>>i);}
	}
	XPT2046_CS=1;
	
	return ADValue;

Command怎么写?
起始位:第一位即S位,控制字的首位必须是1,即S=1,

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
测+IN就是1 001 8位:1 单端:1 00 ;1001 1100 :0x9C


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

读取值是错误的

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


unsigned int ADValue;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"ADJ");
	
	while(1)
	{
		ADValue=XPT2046_ReadAD( XPT2046_XP);
		LCD_ShowNum(2,1,ADValue,4);
		Delay(10);
		
	
	}
}

if(Command&0x08)
	{
	return ADValue>>8;
	}
	else
	{
	return ADValue>>4;
	}
#ifndef __XPT2046_H__
#define __XPT2046_H__


#define XPT2046_XP_8  0x9C//0x8C
#define XPT2046_YP_8   0xDC
#define XPT2046_VBAT_8   0xAC
#define XPT2046_AUX_8   0xEC


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


unsigned int XPT2046_ReadAD(unsigned char Command);


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


unsigned int ADValue;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"ADJ  NTC  RG ");
	
	while(1)
	{
		ADValue=XPT2046_ReadAD( XPT2046_XP_8);
		LCD_ShowNum(2,1,ADValue,3);
	
		ADValue=XPT2046_ReadAD( XPT2046_YP_8);
		LCD_ShowNum(2,6,ADValue,3);
		
		ADValue=XPT2046_ReadAD( XPT2046_VBAT_8);
		LCD_ShowNum(2,11,ADValue,3);
		Delay(10);
	
	}
}

DA
本身就是PWM,只不过是加了一个低通滤波
在这里插入图片描述

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Timer0.h"
#include "Nixie.h"
#include "Init.h"

unsigned char Counter,Compare,i;



sbit DA= P2^1;



void main()
{
	Timer0_Init();

	DianZhengGuan();
	Compare=5;
	while(1)
	{
		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	//跳转到这里,触发中断
{
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;			//定时器定时递增
	Counter%=100;			//周期清零
	if(Counter<Compare)	//比较
	{
	 DA=1;		//给1转
	}
	else
	{
	 DA=0;
	}
	
}

PCF8591 ADC芯片(I2C)

在这里插入图片描述

PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I²C总线接口。PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

ADC实现

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

void PCF8591_WriteAD(unsigned char Command,float Data)
{
	
	I2C_Start();
	I2C_SendByte(PCF8591_ADDRESS);
	I2C_ReceiveAck();
	
	I2C_SendByte(Command);
	I2C_ReceiveAck();

	I2C_SendByte(255*(Data/5.0));
	I2C_ReceiveAck();
	I2C_Stop();
	
	
	
}

在这里插入图片描述

#include <REGX52.H>
#include "I2C.h"

#define PCF8591_ADDRESS  0x90	//写地址



unsigned char PCF8591_ReadAD(unsigned char Command)
{
	unsigned char ADValue=0;
	
	
	I2C_Start();
	I2C_SendByte(PCF8591_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(Command);
	I2C_ReceiveAck();
	I2C_Stop();
	
	
	I2C_Start();
	I2C_SendByte(PCF8591_ADDRESS|0x01);
	I2C_ReceiveAck();
	ADValue=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return ADValue;
}

在这里插入图片描述

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "I2C.h"
#include "PCF8591.h"
#include "Init.h"

unsigned char  ADValue;
float Temp;
void main()
{
	
	LCD_Init();
	LCD_ShowString(1,1,"R   R   T   S  ");
	Nixie_OFF();
	DianZhengGuan();
	
	
	while(1)
	{
	
		ADValue=PCF8591_ReadAD(chan1);
		LCD_ShowNum(2,1,ADValue,3);
		
		Temp=(5.0*ADValue/255);
		PCF8591_WriteAD(0x40,Temp);
	
	
		Delay(10);

	}
}

实验现象

ADC实验电阻控制LED灯的亮灭(模拟输出)

问题

1、这个芯片的自加一通道未能实现,不知道为什么尝试了很久!

总结

本节课主要学了了AD和DA,在上一节课明白了原理后,进行了实验,本次的ADC芯片,是IIC通信,不知道为什么自增的未能实现,不知道哪里出来问题,我用数组存数据,应该可以呀!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值