STC89C51之AD模数转换 ---- 自学笔记

一、AD 模数转换及其相关名词解释

  • A模拟信号
  • D数字信号
  • AD模数转换 模拟信号转换为数字信号

二、A\D转换器的主要技术指标

2.1、分辨率

ADC的分辨率是指使输出数字量变化一个相邻数码所需输入模拟电压的变化量,常用二机制的位数表示,例如12位ADC的分辨率就是12位,或者说分辨率位满刻度的1/(2^12)。一个10V满刻度的12位ADC能分辨输入电压变化最小值是10v*1/(2^12)=2.4mv

xpT2046

2.2、量化误差

量化过程:ADC把模拟量变为数字量,用数字量近似表示模拟量这个过程为量化。

要准确的表示模拟量,ADC的位数需要很大、甚至无穷大。

量化误差:一个分辨率有限的ADC的阶梯状态转换特性曲线与具有无限分辨率的ADC转换特性曲线(直线)之间的最大偏差

2.3、偏移误差

  • 偏移误差:输入信号为零时,输出信号不为零的值,所以有时又称位零值误差。
  • 假定ADC没有非线性误差,则其转换特性曲线各阶梯中点的连线必定是直线,这条直线与横轴相交点所对的输入电压就是偏移误差。

2.4、满刻度误差

又称增益误差,ADC的满刻度误差是指满刻度输出数码所对应的实际输入电压与理想输入电压之差。

2.5、线性度

线性度有时又称非线性度,它是转换器实际的转换特性与理想直线的最大偏差。

2.6、绝对精度

  • 在一个转换器中,任何数码所对应的实际模拟量输入与理论模拟输入之差的最大值,又称绝对精度。
  • 对于ADC而言,可以在每一个阶段的水平中点进行测量,它包括了所有的误差。

2.7、转换速率

  • ADC的转换速率是能够重复进行数据转换的速度,即每秒转换的次数。而完成一次A/D转换所需的时间(包括稳定时间),则是转换速率的倒数。
  • A/D转换器的转换速度主要取决与转换电路的类型,不同类型A/D转换器的转换速度相差很大。
  1. 双积分型A/D转换器的转换速度最慢,需几百毫秒左右。

  1. 逐次逼近式A/D转换器的转换速度较慢,需要几十微秒。

 

 逐次逼近式AD转换器与计数式A/D转换类似,只是数字量由“逐次逼近寄存器SAR”产生。SAR使用“对分搜索法”产生数字量,以8位数字量为例,SAR首先产生8位数字量的一半,即10000000B,试探模拟量Vi的大小,若Vn>Vi,清除最高位,若Vn<Vi,保留最高位。在最高位确定后,SAR又以对分搜索法确定次高位,即以低7位的一半y1000000B(y为已确定位) 试探模拟量Vi的大小。在bit6确定后,SAR以对分搜索法确定bit5位,即以低6位的一半yy100000B(y为已确定位) 试探模拟量的大小。重复这一过程,直到最低位bit0被确定,转换结束。

并行比较型A/D转换器的转换速度最快,仅需几十纳秒。

 

 

三、XPT2046芯片

3.1、原理图

3.2、封装形式

 

3.3、引脚功能

 

3.4、时序图

 

 

 

四、程序

4.1、主函数(main.c)

 

   /*
数码管前4位显示电位器检测的AD值,范围是0-4095(2的12次方4096),一般达不到最大,这个受供电电压的影响

		   1,单片机-->AD/DAC模块
		   		P34-->DI
				P35-->CS
				P36-->CL
				P37-->DO
		   2,单片机-->动态数码管模块
		   		J22-->J6
				P22-->J9(A)
				P23-->J9(B)
				P24-->J9(C)	
*/

#include "reg52.h"
#include "XPT2046.h"
typedef unsigned int u16;	   //对数据类型进行声明定义
typedef unsigend char u8;

sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
	u8 disp[4];	 // 八位数码管显示前4位
	u8 code smgduan[10]	=	={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // 显示0~9的数字

	void delay(u16 i)		   //  延时函数
	{
	while(i--);
	}

	  
void datapros(){	// 数据处理函数
	  u16 temp;
	  static u8 i;
	  if(i=50)
	  {
	  i=0;
	  temp = Read_AD_Data(0x94);	// AIN0电位器  如果要检测转换电位器模拟信号,控制字命令寄存器值为0X94或者0XB4.

	  }
	  i++;
	disp[0]=smgduan[temp/1000];//千位
	disp[1]=smgduan[temp%1000/100];//百位
	disp[2]=smgduan[temp%1000%100/10];	// 十位
	disp[3]=smgduan[temp%1000%100%10];	//个位	
	  }


void DigDisplay()	 //  数码管显示函数
	  {		
	  
	  	u8 i;
		for(i=0;i<4;i++)
		 {
		    switch(i) // 位选,选择点亮的数码管
			{
			case(0): 
			   LSA=1;LSB=1;LSC=1;break;  //   显示第0位
			case(1):
			   LSA=0;LSB=1;LSC=1;break;  //   显示第1位
			case(2):
			   LSA=1;LSB=0;LSC=1;break;  //   显示第2位
			case(3):
			   LSA=0;LSB=0;LSC=1;break;  //  显示第3位
			}
			 P0=disp[i];  // 发送数据
			 delay(100);  // 间隔一段时间扫描
			 P0=0x00;	  // 消隐
		 }
	  }


	  void main() // 主函数  程序执行的入口
	  {
	     while(1)
	  {
	     datapros();
	     DigDisplay();
	  }
	  }

如果要检测转换电位器模拟信号,控制字命令寄存器值为0X94或者0XB4.

如果要检测转换热敏电阻模拟信号,控制字命令寄存器值为0XD4.

如果要检测转换光敏电阻模拟信号,控制字命令寄存器值为0XA4.

如果要检测转换AIN3通道上模拟信号,控制字命令寄存器值为0XE4.

4.2、XTP2046芯片使用函数头文件

#ifndef _XPT2046_H_		 // 外部文件引用此文件的名称定义
#define _XPT2046_H_

// 包含头文件
#include<reg52.h>
#include<intrins.h>

// 关键字重定义
#ifndef uchar                //  如果uchar没有被定义
#define uchar unsigned char  //  那么就把它定义为char类型
#endif		                 //  结束标志

#ifndef uint 
#define unint  unsigned int
#endif     

#ifndef ulong
#define ulong  unsigned long
#endif

// IO口定义
sbit DOUT = P3^7;  // 输出
sbit CLK  = P3^6;  // 时钟
sbit DIN  = P3^4;  // 输入
sbit CS   = P3^5;  // 片选

// XPT2046.c文件中函数的声明
uint Read_AD_Date(uchar cmd);  
uint SPI_Read(void);
void SPI_Write(uchar dat);

#endif   // XPT2046.h文件声明结束

4.3、XTP2046使用函数

#include "XPT2046.h"
// 写入函数
void SPI_Write(uchar dat)	// dat :写入数据
{
uchar i=1;
CLK =0;
for(i=0;i<8;i++){	// 1字节 = 8bit 
DIN =dat >> 7; //右移7位

dat <<=1;      // 左移移位  
CLK=0;	       // 上升沿放置数据至数据线

CLk=1;
	   }
}

// dat:读取数据
uint SPI_Rea(void)
{
uint ,i,dat=0;
CLK=0;
for(i=0;i<12;i++)	 // 接收到
{
dat<<-1;
CLk=1;
CLK=0;

dat|=DOUT;	  // dat = dat | DOUT
}
  return dat;
}

uint Read_AD_Data(uchar cmd)
{

   	uchar i;
	uint AD_Value;   // int类型 AD_Value
	CLK = 0;         // 低电平
	CS  = 0;         // 低电平
	SPI_Write(cmd);  cmd写入SPI_Wri
	for(i=6; i>0; i--); 	//延时等待转换结果
	CLK = 1;	  //发送一个时钟周期,清除BUSY
	_nop_();      // 延迟一个指令周期
	_nop_();       // 延迟一个指令周期
	CLK = 0;
	_nop_(); // 延迟一个指令周期
	_nop_(); // 延迟一个指令周期
	AD_Value=SPI_Read();
	CS = 1;
	return AD_Value;	
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旭日初扬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值