当前位置: 首页 > article >正文

江科大51单片机笔记【16】AD/DA转换(下)

写在前言


  此为博主自学江科大51单片机(B站)的笔记,方便后续重温知识

  在后面的章节中,为了防止篇幅过长和易于查找,我把一个小节分成两部分来发,上章节主要是关于本节课的硬件介绍、电路图、原理图等理论知识,主要是为下章节的代码部分打基础。

  我的单片机是24年12月在tb普中买的,型号是STC89C52,在原视频中引脚或接口不对应的我都会改正,保证在我的机子上能运行才发上来的,还有一些文字部分是我的理解,并非照搬,所以可能有理解不到位的现象。

  如有误或交流,敬请指点提问

如果上一节的运放、电路图、结构图看不懂没关系,只需要看懂下面这个时序图就可以写代码实现功能了

一、AD模数转换

先导入之前写好的Delay和LCD1602模块,然后新建XPT2046点c和点h文件

接下来就是对照这个时序把数据读出来

1.先定义引脚

#include <REGX52.H>

sbit XPT2046_CS=P3^5;
sbit XPT2046_DCLK=P3^6;
sbit XPT2046_DIN=P3^4;
sbit XPT2046_DOUT=P3^7;

 2.定义函数

给个参数(控制字),用于选择通道

并且定义一个变量ADAvalue,最后返回出来

 然后是根据上图对每个引脚先后赋值

首先把DCLK置0(初始化),CS置0,DIN赋值参数控制字的最高位
然后再给DCLK置1(上升沿),DIN就把最高位发出去,然后置0(下降沿),查看手册发现上下时间是ns级,所以不用延时

接下来就是同理依次把8个位发出去,用for循环实现

发出去之后就可以读数据了

接下来就是到图中这个位置,先给DCLK一个上升沿,一个下降沿,数据才会过来

进行一个判断,如果Dout为1,就让ADAValue把数据读出来(因为是16位所以或上0x8000)

然后对该过程循环16位,用for循环实现,因为只有12位是有数值的,后面都是零填充的,所以我们要在最后返回ADAValue的时候向右移位(如果选择8位读就移8位,12位读就移4位)

最后再把CS置高,结束这个时序,到这里就写完这个函数了

//XPT2046.c

#include <REGX52.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;
	XPT2046_CS=0;
	
	for(i=0;i<8;i++)
	{
		XPT2046_DIN=Command&(0x80>>i);
		XPT2046_DCLK=1;
		XPT2046_DCLK=0;
	}
	for(i=0;i<16;i++)
	{
		XPT2046_DCLK=0;
		XPT2046_DCLK=1;
		if(XPT2046_DOUT){ADValue|=(0x8000>>i);}
	}
	XPT2046_CS=1;
	if(Command&0x08)
	{
		return ADValue>>8;
	}
	else
	{
		return ADValue>>4;
	}
}
}

这里再讲一下命令字怎么写

S就是起始位,给1;A2A1A0是地址,选择通道;MODE就是模式选择位,=0是12位模式,=1是8位模式;SER/DFR也是选择模式,=1是单端模式,=0是差分模式,我们在这用单端模式;PD0和PD1表示掉电和内部参考电压配置的关系,若为11,处于供电状态,若为00,处于低功率模式(当PD1为0时关闭内部参考电压源,为1时打开,内部参考源作用即假设原本测量值是从0-5V,接到这就是2.5-5V)

在这里我们给1 A2 A1 A0 1 1 0 0,A2A1A0的选择要看下图

下图只看前面部分,A2A1A0控制测哪的电压

为了方便写代码,我们把上面这些值给宏定义,这里要根据开发板的原理图对应上图,以及前面教的命令字写出来,因为是要外部调用,所以写在.h文件里 

 我们定义不同的命令字,一个是8位,一个是12位,方便后面选择

8位是0-255,12位是0-4096,更精细

#ifndef __XPT0246_H_
#define __XPT0246_H_

#define XPT2046_XP_8       0X9C
#define XPT2046_YP_8        0XDC
#define XPT2046_VBAT_8        0XAC
#define XPT2046_AUX_8        0XEC

#define XPT2046_XP_12       0X94
#define XPT2046_YP_12       0XD4
#define XPT2046_VBAT_12       0XA4
#define XPT2046_AUX_12       0XE4


unsigned int XPT2046_ReadAD(unsigned char Command);


#endif

因为AUX接到了一个接口上,所以这里我们不读,只读其他三个

//main.c

#include <REGX52.H>
#include " Delay.h"
#include " LCD1602.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,5,ADValue,3);
 		ADValue=XPT2046_ReadAD(XPT2046_VBAT_8);
		LCD_ShowNum(2,9,ADValue,3);
		Delay(10);
	}
}

这里我需要把DS18B20拔掉才能显示正常,暂时还未找到原因 

#include <REGX52.H>
#include " Delay.h"
#include " LCD1602.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);
	}
}

 这样就可以调节我们电路板上的电阻,然后会把阻值通过AD转换后输出在LCD上

GR是光敏电阻,NTC是热敏电阻,AD1(ADJ)是可调电阻

二、 DA数模转换

接下是PWM,因为跟之前写过的直流电机调速原理是一样的,所以我们复制过来创建一个新的工程

首先是更改接口

sbit DA=P2^1;

然后是更改命名,可以点这里一键替代

然后把关于按键的部分删掉,在主函数里实现一个呼吸灯的效果

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

sbit DA=P2^1;

unsigned char Counter,Compare;
unsigned char i;

void main()
{

	Timer0_Init();
	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
{
	Key_Loop();
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;
	Counter%=100;
	if(Counter<Compare)
	{
		DA=1;
	}
	else
	{
		DA=0;
	}
}

其他部分都不需要改,这样就实现了呼吸灯的效果。


http://www.kler.cn/a/584559.html

相关文章:

  • Arbitrum之智能合约
  • Java 虚拟机优化指南:CMS垃圾回收器参数调优与性能监控工具详解
  • 【数据结构】初识集合框架及背后的数据结构(简单了解)
  • uniapp移动端图片比较器组件,仿英伟达官网rtx光追图片比较器功能
  • Java --- 根据身份证号计算年龄
  • 《基于大数据的营养果蔬推荐系统的设计与实现》开题报告
  • makefile详解
  • Discuz建站教程之论坛头部logo跳转链接怎么修改?
  • HCIA复习实验拓扑详细版
  • mysql下载与安装、关系数据库和表的创建
  • DeepSeek-R1:开源大模型的技术革命与行业影响分析
  • Python第二十课:生成对抗网络 | AI创造力觉醒
  • 基于SpringBoot的“校园周边美食探索及分享平台”的设计与实现(源码+数据库+文档+PPT)
  • 【每日学点HarmonyOS Next知识】上下拉动作、图片预览、组件边距、this获取、svg旋转
  • 工业物联网平台系列技术介绍-分类、聚类、逻辑回归
  • 中服云官网改版上线,全力聚焦工业物联网平台IIOT领域
  • 【第五节】windows sdk编程:windows 控件基础
  • WPS的Excel文档如何利用VB脚本批量替换超链接的内容
  • Flutter:跑马灯公告栏
  • 如何使用logrotete定时切割mysql的慢日志