AD转换之光敏电阻AIN2 ---- 学习笔记

一、逐次逼近式ADC的转换原理

AD转换之光敏电阻AIN2 ---- 学习笔记_第1张图片

逐次逼近式AD转换器与计数式A/D转换类似,只是数字量由“逐次逼近寄存器SAR”产生。SAR使用“对分搜索法”产生数字量,以8位数字量为例,SAR首先产生8位数字量的一半,即10000000B,试探模拟量Vi的大小,若Vn>Vi,清除最高位,若Vn

二、时序图与引脚

AD转换之光敏电阻AIN2 ---- 学习笔记_第2张图片

 

AD转换之光敏电阻AIN2 ---- 学习笔记_第3张图片

三、代码

3.1、main

/*
 实验现象:下载程序后数码管前4位显示光敏传感器检测的AD值
	1,单片机-->AD/DAC模块 管脚释义
		   		P34-->DI   DIN	  串行数据输入端,当CS为低电平时,数据在 DCLK上升沿锁存进来
				P35-->CS   CS	  片选信号,控制转换时序和使能串行输入输出寄存器,高电平时ADC掉电
				P36-->CL   DCLK	  时钟,外部时钟信号输入
				P37-->DO   DOUT	  串行数据输出端口。数据在DCLK的下降沿移出,当cs为高电平时为高阻态。
				           BUSY   忙时信号,当cs为高电平时为高阻态
						   LOVDD  数字电源输入端
						   AUX     ADC辅助输入通道
     2,单片机-->动态数码管模块
		   		J22-->J6
				P22-->J9(A)
				P23-->J9(B)
				P24-->J9(C)	

*/
#include "reg52.h"		 // 此文件中定义了单片机的一些特殊功能寄存器
#include "XPT2046.h"

typedef unsigned int u16;
typedef unsigned char u8;   // 数据类型的定义

sbit LSA = P2^2;    //这三个端口共同控制数码管的位选
sbit LSB = P2^3;
sbit LSC = P2^4;

u8 disp[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修饰的静态局部变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。
static修饰全局变量的时,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是extern外部声明也不可以
static修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。Static修饰的局部变量存放在全局数据区的静态变量区。*/
static u8 i; 
if(i==50)
{
i=0;
/*
 AIN0电位器:如果要检测转换电位器模拟信号,控制字命令寄存器值为0X94或者0XB4.
 如果要检测转换热敏电阻模拟信号,控制字命令寄存器值为0XD4.
  AIN2光敏电阻:如果要检测转换光敏电阻模拟信号,控制字命令寄存器值为0XA4.
 如果要检测转换AIN3通道上模拟信号,控制字命令寄存器值为0XE4.

*/
temp = Read_AD_Data(0xA4); // AIN2光敏电阻
}
 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();   // 数码管显示函数
   }
 }


 

3.3、XPT2046芯片控制引脚定义、函数、变量声明文件

#ifndef _XPT2046_H_
#define _XPT2046_H_

// 包含头文件
#include
#include

// 重定义关键字
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint
#define uint unsigned int 
#endif

#ifndef ulong
#define ulong unsigned long
#endif

// IO定义
sbit DOUT = P3^7;
sbit CLK  = P3^6;
sbit CS  = P3^5;	 
sbit DIN  = P3^4;

// 函数定义
uint Read_AD_Data(uchar cmd);
uint SPI_Read(void);
void SPI_Write(uchar dat);

 

3.3、XPT2046.c芯片控制

 #include"XPT2046.h"

// 初始化触摸函数
void SPI_Start(void)
{
  CLK=0;	// 时钟,外部时钟信号输入
  CS=1;	    // 片选信号,控制转换时序和使能串行输入输出寄存器,高电平时ADC掉电

  DIN=1;    // 串行数据输入端,当CS为低电平时,数据在 DCLK上升沿锁存进来
  CLK=1;
  CS=0;
}

/*写数据
CLK外部时钟 上升沿时   由DIN端口输入数据并锁存
*/ 
void SPI_Write(uchar dat)
{
 uchar i;    // 字符型变量
 CLK=0;		 // 外部时钟  低电平
 for(i=0;i<8;i++)
 {
 /*	 逐次逼近式AD转换原理
 	 逐次逼近式AD转换器与计数式A/D转换类似,只是数字量由“逐次逼近寄存器SAR”产生。
	 SAR使用“对分搜索法”产生数字量,以8位数字量为例,SAR首先产生8位数字量的一半,
	 即10000000B,试探模拟量Vi的大小,若Vn>Vi,清除最高位,若Vn> 7;  // 右移7位	 将dat的最高位赋给DIN
 dat<<=1;         //  dat=dat<<1 将保存在dat中的最高位移出 进行下次循环
 CLK = 0;
			   // 上升沿放置数据,如将数据传输至数据线
 CLK = 1;
 }
}

  /*读数据函数
  CLK 时钟信号输入端口  下降沿时(CLK=1 变为 CLK=0)	数据移出

  */
uint SPI_Read(void)
{
uint i, dat = 0;  // 定义整型变量
CLK = 0;
for(i=0;i<12;i++)
{
 dat <<=1;       // dat = dat << 1;  左移1位
 CLK=1;
               // 下降沿数据移出
 CLK =0;
 /*  
 与&&  and	  		 a && b    a  and  b	 
 或||  or            a || b    a   or  b
 非!                 !1=0 
 按位与(&)	         a & b     a  and b 
 按位或(|)           a | b     a  or  b
 
 */
 dat |= DOUT;     // dat = dat | DOUT    
}
 return dat;
}


/*cmd:读取的X或Y*/ 
uint Read_AD_Data(uchar cmd)
{
uchar i;        // 无符号的字符型变量
uint AD_Value;  // 整型变量
CLK =0;			// 外部时钟信号输入
CS = 0;	        //片选信号,控制转换时序和使能串行输入输出寄存器,高电平时ADC掉电(高电平不工作,低电平工作)
SPI_Write(cmd);
for(i=6;i>0;i--);	// 发送一个时钟周期,清除BUSY
CLK = 1;    // 下降沿移出数据
_nop_();    // 延时1us
_nop_();    // 延时1us
CLK = 0;
_nop_();    // 延时1us
_nop_();	// 延时1us
AD_Value = SPI_Read();
CS =1;
return AD_Value;
}

 

 

你可能感兴趣的:(单片机)