先给大家看下效果
数码管会随光照强度而变化,可以拿手电筒照射 光敏电阻看数码管数值变化
项目工程如下:
首配置一下IIC协议 这个比较基础代码如下:
首先是.c文件
#include "iic.h"
#define DELAY_TIME 5
//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//I2C总线启动信号
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//I2C总线停止信号
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//I2C总线发送一个字节数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//I2C总线接收一个字节数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
// pcf8591内有四个通道,如下:
// 0:AIN0电压输入(0x00)
// 1:光敏电阻(0x01)
// 2:运算放大器(0x02)
// 3:滑动变阻器(0x03)
//---------------------------------------
// AD转换:直接读取pcf8591内寄存器数据(不依赖EEPROM)
unsigned char ad_read(unsigned char add){
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90); // 选中8591芯片,写指令
IIC_WaitAck();
IIC_SendByte(add); // 配置寄存器,选择哪个通道
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91); // 选中8591,读指令
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
//-------------------------------------------
// 读取数据
unsigned char eeprom_read(unsigned char add){
unsigned char temp;
IIC_Start();
IIC_SendByte(0xA0); // 选中eeprom芯片,写指令
IIC_WaitAck();
IIC_SendByte(add); // 选择哪个地址
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xA1); // 选中eeprom,读指令
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
// 写入数据
void eeprom_write(unsigned char add, unsigned char dat){
IIC_Start();
IIC_SendByte(0xA0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_Stop();
}
iic.h文件如下:
#ifndef __IIC__H__
#define __IIC__H__
#include "stc15f2k60s2.h"
#include "intrins.h"
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
unsigned char ad_read(unsigned char add);
unsigned char eeprom_read(unsigned char add);
void eeprom_write(unsigned char add, unsigned char dat);
#endif
然后在建一个use.c文件来放置各种函数方便直接在主函数main中调用
#include "use.h"
// 第0到9位是数字0到9, 第10到18位是带小数点的0到9,最后是关闭显示
uchar code tab[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10, 0xff};
uchar dspbuf[8]={20, 20, 20, 20, 20, 20, 20, 20};
uchar dspcom=0;
void system_init(void){
hc138(1, 0x00); //关闭蜂鸣器
hc138(2, 0xff); //关闭LED
timer_init();
}
void timer_init(void){
TMOD=0x01; //定时器1 12分频
TH0=(65536-1000)/256; //1ms
TL0=(65536-1000)%256;
TR0=1;
ET0=1;
EA=1;
}
void hc138(uchar mode, uchar dat){
P0=dat;
switch(mode){
case 1:P2=P2&0x1f|0xa0;break;// 蜂鸣器
case 2:P2=P2&0x1f|0x80;break;// LED
case 3:P2=P2&0x1f|0xe0;break;// 数码管段选
case 4:P2=P2&0x1f|0xc0;break;// 数码管位选
}
P2&=0x1f;
}
void re_dsp(uchar *arr){
uchar i;
for(i=0;i<8;i++){
*(dspbuf+i)=*(arr+i);//更新数码表
}
}
void digital(void){
hc138(3, 0xff);
hc138(4, 1<=8){
dspcom=0;
}
}
然后是use.h
#ifndef __USE__H__
#define __USE__H__
#include
#include
#include
#include
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
void system_init(void);
void timer_init(void);
void hc138(uchar mode, uchar dat);
void re_dsp(uchar *arr);
void digital(void);
#endif
最后就是main函数
#include "use.h"
bit show_flag=0;
bit adc_flag=0;
uchar dsp[8]={20, 20, 20, 20, 20, 20, 20, 20};
uchar light=0;
void show(void);
void main(void){
system_init();
while(1){
if(show_flag==1){
show_flag=0;
show();
}
if(adc_flag==1){
adc_flag=0;
light=ad_read(0x01);//读取光敏电压
light=ad_read(0x01);
if(light<=80){
eeprom_write(0x00, 0);
}else{
eeprom_write(0x00, 1);
}
}
re_dsp(dsp);
}
}
void show(void){
//更新数码表
uchar cache_light=light;
cache_light=(float)cache_light/255*500;
dsp[0]=cache_light/100+10;
dsp[1]=cache_light%100/10;
dsp[2]=cache_light%10;
dsp[3]=dsp[4]=dsp[5]=dsp[6]=20;
dsp[7]=eeprom_read(0x00);
}
void timer_0(void) interrupt 1 {
static uint count=0, adc_cnt=0;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
digital();//刷新数码管
if(++adc_cnt>=200){ //0.2s读取光敏电压
adc_cnt=0;
adc_flag=1;
}
if(++count>=500){ //0.5s更新数码表
count=0;
show_flag=1;
}
}
最后呢将程序烧录进去就行啦!