单片机-蓝桥杯 用光敏电阻测量光照强度并显示在数码管上。

先给大家看下效果

单片机-蓝桥杯 用光敏电阻测量光照强度并显示在数码管上。_第1张图片

 数码管会随光照强度而变化,可以拿手电筒照射 光敏电阻看数码管数值变化

项目工程如下

首配置一下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;
	}
}

最后呢将程序烧录进去就行啦!

你可能感兴趣的:(单片机,蓝桥杯,c语言)