一、概述
1.光敏电阻简介
光敏电阻(photoresistor or light-dependent resistor,后者缩写为ldr)或光导管(photoconductor),常用的制作材料为硫化镉,另外还有硒、硫化铝、硫化铅和硫化铋等材料。这些制作材料具有在特定波长的光照射下,其阻值迅速减小的特性。这是由于光照产生的载流子都参与导电,在外加电场的作用下作漂移运动,电子奔向电源的正极,空穴奔向电源的负极,从而使光敏电阻器的阻值迅速下降。
光敏电阻是用硫化镉或硒化镉等半导体材料制成的特殊电阻器,其工作原理是基于内光电效应。光照愈强,阻值就愈低,随着光照强度的升高,电阻值迅速降低,亮电阻值可小至1KΩ以下。光敏电阻对光线十分敏感,其在无光照时,呈高阻状态,暗电阻一般可达1.5MΩ。光敏电阻的特殊性能,随着科技的发展将得到极其广泛应用。 [1]
光敏电阻器是利用半导体的光电导效应制成的一种电阻值随入射光的强弱而改变的电阻器,又称为光电导探测器;入射光强,电阻减小,入射光弱,电阻增大。还有另一种入射光弱,电阻减小,入射光强,电阻增大。
光敏电阻器一般用于光的测量、光的控制和光电转换(将光的变化转换为电的变化)。常用的光敏电阻器硫化镉光敏电阻器,它是由半导体材料制成的。光敏电阻器对光的敏感性(即光谱特性)与人眼对可见光(0.4~0.76)μm的响应很接近,只要人眼可感受的光,都会引起它的阻值变化。设计光控电路时,都用白炽灯泡(小电珠)光线或自然光线作控制光源,使设计大为简化。
2.ADC数模转换
数模转换器,又称D/A转换器,简称DAC,它是把数字量转变成模拟的器件。D/A转换器基本上由4个部分组成,即权电阻网络、运算放大器、基准电源和模拟开关。模数转换器中一般都要用到数模转换器,模数转换器即A/D转换器,简称ADC,它是把连续的模拟信号转变为离散的数字信号的器件。
3.XPT2046 芯片介绍
二、工作原理
1.光敏电阻工作原理
光敏电阻的工作原理是基于内光电效应。在半导体光敏材料两端装上电极引线,将其封装在带有透明窗的管壳里就构成光敏电阻,为了增加灵敏度,两电极常做成梳状。用于制造光敏电阻的材料主要是金属的硫化物、硒化物和碲化物等半导体。通常采用涂敷、喷涂、烧结等方法在绝缘衬底上制作很薄的光敏电阻体及梳状欧姆电极,接出引线,封装在具有透光镜的密封壳体内,以免受潮影响其灵敏度。入射光消失后,由光子激发产生的电子—空穴对将复合,光敏电阻的阻值也就恢复原值。在光敏电阻两端的金属电极加上电压,其中便有电流通过,受到一定波长的光线照射时,电流就会随光强的增大而变大,从而实现光电转换。光敏电阻没有极性,纯粹是一个电阻器件,使用时既可加直流电压,也加交流电压。半导体的导电能力取决于半导体导带内载流子数目的多少。
2.ADC转换原理
三、实验程序
1.参考代码
main.c
#include "regx52.h"
#include "LCD1602.h"
#include "stdio.h"
#include "xpt2046.h"
#include "delay.h"
sbit LED1 = P2^0;
unsigned int light_value = 0;
void main()
{
lcd1602_init();
while(1)
{
char buf[20] = {0};
light_value = xpt2046_read_adc_value(0xA4);
sprintf(buf,"value=%4d",light_value);
lcd1602_show_string(1,0,buf);
Delay1_ms(100);
if(light_value < 100)
LED1 = 0;
else
LED1 = 1;
}
}
xtp2046.c
#include "xpt2046.h"
#include "intrins.h"
/*******************************************************************************
* 函 数 名 : xpt2046_wirte_data
* 函数功能 : XPT2046写数据
* 输 入 : dat:写入的数据
* 输 出 : 无
*******************************************************************************/
void xpt2046_wirte_data(u8 dat)
{
u8 i;
CLK = 0;
_nop_();
for(i=0;i<8;i++)//循环8次,每次传输一位,共一个字节
{
DIN = dat >> 7;//先传高位再传低位
dat <<= 1;//将低位移到高位
CLK = 0;//CLK由低到高产生一个上升沿,从而写入数据
_nop_();
CLK = 1;
_nop_();
}
}
/*******************************************************************************
* 函 数 名 : xpt2046_read_data
* 函数功能 : XPT2046读数据
* 输 入 : 无
* 输 出 : XPT2046返回12位数据
*******************************************************************************/
u16 xpt2046_read_data(void)
{
u8 i;
u16 dat=0;
CLK = 0;
_nop_();
for(i=0;i<12;i++)//循环12次,每次读取一位,大于一个字节数,所以返回值类型是u16
{
dat <<= 1;
CLK = 1;
_nop_();
CLK = 0; //CLK由高到低产生一个下降沿,从而读取数据
_nop_();
dat |= DOUT;//先读取高位,再读取低位。
}
return dat;
}
/*******************************************************************************
* 函 数 名 : xpt2046_read_adc_value
* 函数功能 : XPT2046读AD数据
* 输 入 : cmd:指令
* 输 出 : XPT2046返回AD值
*******************************************************************************/
u16 xpt2046_read_adc_value(u8 cmd)
{
u8 i;
u16 adc_value=0;
CLK = 0;//先拉低时钟
CS = 0;//使能XPT2046
xpt2046_wirte_data(cmd);//发送命令字
for(i=6; i>0; i--);//延时等待转换结果
CLK = 1;
_nop_();
CLK = 0;//发送一个时钟,清除BUSY
_nop_();
adc_value=xpt2046_read_data();
CS = 1;//关闭XPT2046
return adc_value;
}
#ifndef _xpt2046_H
#define _xpt2046_H
#include "regx52.h"
typedef unsigned int u16;
typedef unsigned char u8;
typedef unsigned long u32;
//管脚定义
sbit DOUT = P3^7; //输出
sbit CLK = P3^6; //时钟
sbit DIN = P3^4; //输入
sbit CS = P3^5; //片选
//函数声明
u16 xpt2046_read_adc_value(u8 cmd);
#endif
LCD1602.c
#include "LCD1602.h"
#include "regx52.h"
#include "delay.h"
void lcd1602_write_cmd(unsigned char cmd)
{
LCD1602_RS=0;
LCD1602_RW=0;
LCD1602_EN=0;
LCD1602_DATAPORT=cmd;
LCD1602_EN=1;
Delay1_ms(1);
LCD1602_EN=0;
Delay1_ms(1);
}
void lcd1602_write_data(unsigned char dat)
{
LCD1602_RS=1;
LCD1602_RW=0;
LCD1602_EN=0;
LCD1602_DATAPORT=dat;
LCD1602_EN=1;
Delay1_ms(1);
LCD1602_EN=0;
Delay1_ms(1);
}
void lcd1602_init()
{
lcd1602_write_cmd(0x38);//数据长度为8、2行显示、5*7点阵
//显示功能打开、无光标、光标不闪烁
lcd1602_write_cmd(0x0c);
//写入新数据后光标右移、文字保持不动
lcd1602_write_cmd(0x06);
lcd1602_write_cmd(0x01);
}
void lcd1602_show_string(unsigned char x,unsigned char y,unsigned char*str)
{
if(y==0)
lcd1602_write_cmd(0x80+0x00+x);
if(y==1)
lcd1602_write_cmd(0x80+0x40+x);
while(*str != '\0')
{
lcd1602_write_data(*str);
str++;
}
}
#include "regx52.h"
#ifndef _LCD1602_H_
#define _LCD1602_H_
sbit LCD1602_RS = P2^6;
sbit LCD1602_RW = P2^5;
sbit LCD1602_EN = P2^7;
#define LCD1602_DATAPORT P0
void lcd1602_init();
void lcd1602_show_string(unsigned char x,unsigned char y,unsigned char*str);
#endif
另外还有delay函数的模块
#include "delay.h"
#include "intrins.h"
//延时函数
void Delay1_ms(unsigned int a) //@11.0592MHz
{
unsigned char i, j;
for(a;a>0;a--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
四、实验现象
编译成功后将程序烧录到开发板上,插上LCD1602模块
如果亮度value值大于100,LED1灭
覆盖住光敏电阻,亮度value值小于100,LED1亮
(文章内容取自51单片机开发板资料)