灯光控制器
#include<reg52.h>
#include<intrins.h> //提供系统中的一些函数,像_nop()_ 空操作函数
#include<math.h>
//shuma.h是数码管扫描驱动,定义着数码管的扫描函数
//数码管的段码0~A
unsigned char code shuma[]={0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F ,0x77,0x7C,0x39,0x5E,0x79,0x71,0x76 };
unsigned char code shuma1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef };//电压整数部分显示码
unsigned char code shuma2[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f };//电压小数部分显示码
unsigned char vol,ta,ge;
unsigned char second=0,//数码管第一位和第二位组成累计的时间,数据存在second中 ,0~99s
on_off=0,//,第三位是开关次数,数据存在data_3中,0~9次
bright=0,//第四位为亮度等级,数据存在data_4中,0~9级
my_bright=0x05;
//my_bright为程序中定义的亮度等级,当亮度小于程序中的亮度等级时就会驱动继电器
sbit delay_on=P3^5;//此引脚用于驱动继电器
sbit ctrl_1=P1^5;//锁存器1的使能端
sbit ctrl_2=P1^6;//锁存器2的使能端
sbit wei1=P0^0;//数码管位选1
sbit wei2=P0^1;//数码管位选2
sbit wei3=P0^2;//数码管位选3
sbit wei4=P0^3;//数码管位选4
sbit wei5=P0^4;//数码管位选5
sbit wei6=P0^5;//数码管位选6
void delay()//延时函数
{
unsigned char i,j;
for(i=0;i<30;i++)
for(j=0;j<20;j++);
}
//数码管显示子程序,即数码管显示驱动
void screen(char wei,char led_data)
{
switch(wei)
{
case 1:
P0=0x00;
ctrl_1=1;ctrl_2=0;
P0=led_data;
ctrl_1=0;ctrl_2=0;
P0=0xff;
ctrl_1=0;ctrl_2=1;
wei1=0;wei2=1;wei3=1;wei4=1;wei5=1;wei6=1;
ctrl_1=0;ctrl_2=0;break;
case 2:P0=0x00;
ctrl_1=1;ctrl_2=0;
P0=led_data;
ctrl_1=0;ctrl_2=0;
P0=0xff;
ctrl_1=0;ctrl_2=1;
wei1=1;wei2=0;wei3=1;wei4=1;wei5=1;wei6=1;
ctrl_1=0;ctrl_2=0;break;
case 3:P0=0x00;
ctrl_1=1;ctrl_2=0;
P0=led_data;
ctrl_1=0;ctrl_2=0;
P0=0xff;
ctrl_1=0;ctrl_2=1;
wei1=1;wei2=1;wei3=0;wei4=1;wei5=1;wei6=1;
ctrl_1=0;ctrl_2=0;break;
case 4:P0=0x00;
ctrl_1=1;ctrl_2=0;
P0=led_data;
ctrl_1=0;ctrl_2=0;
P0=0xff;
ctrl_1=0;ctrl_2=1;
wei1=1;wei2=1;wei3=1;wei4=0;wei5=1;wei6=1;
ctrl_1=0;ctrl_2=0;break;
case 5:P0=0x00;
ctrl_1=1;ctrl_2=0;
P0=led_data;
ctrl_1=0;ctrl_2=0;
P0=0xff;
ctrl_1=0;ctrl_2=1;
wei1=1;wei2=1;wei3=1;wei4=1;wei5=0;wei6=1;
ctrl_1=0;ctrl_2=0;break;
case 6:P0=0x00;
ctrl_1=1;ctrl_2=0;
P0=led_data;
ctrl_1=0;ctrl_2=0;
P0=0xff;
ctrl_1=0;ctrl_2=1;
wei1=1;wei2=1;wei3=1;wei4=1;wei5=1;wei6=0;
ctrl_1=0;ctrl_2=0;break;
default:;
}
}
//数码管整体扫描函数
void disp()
{
screen(1,shuma[second/10]); //显示时间的十位
delay();
screen(2,shuma[second%10]); //显示时间的各位
delay();
screen(3,shuma[on_off]); //显示开关次数
delay();
screen(4,shuma[bright]); //显示灯光的量的等级
delay();
screen(5,shuma1[vol]);
delay();
screen(6,shuma2[ge]);
delay();
}
//rom.h是52单片机中自带的伪EEPROM,扇区删除和擦写,在此没有存储数据可以完全忽略,
//此头文件的意义在于掉电保存数据,在此没有用上
#include"rom.h"
//int.h中定义着中断初始化函数和中断服务函数,具体见int.h
sbit ADC0809_clk=P1^3;
unsigned char num1=0,num2=0,num4=0;
//定时器0初始化函数
void time0_init()
{
TMOD=0x21; //设置TO,T1定时器
TH0=(65536-45872)/256; //装初值晶振定时50ms数为45872
TL0=(65536-45872)%256;
TH1=200; //装初值晶振定时50ms数为45872
TL1=200;
EA=1; //开总中断
ET0=1; //开启定时器T0中断
ET1=1; //开启定时器T1中断
TR0=1; //启动定时器0
TR1=1; //启动定时器1
ADC0809_clk=0;
}
void T0_time()interrupt 1 //定时器T0,中断序号为1
{
num1++;
if(num1==2) //如果到了2次,说明0.1秒的时间到
{
num1=0; //然后把num2清零重新再计2次
num2++;
if(num2==10)
{
num2=0;
if(second>=99)
second=0;
else
second++; //秒信号产生
}
}
TH0=(65536-45872)/256; //重装定时器初值
TL0=(65536-45872)%256;
TR0=1;
}
void T1_time()interrupt 3 //定时器T0,中断序号为1
{
ADC0809_clk=~ADC0809_clk; //产生0809的时钟
/*if(num4<=9) num4++;
else
{
while(1)
{
P0=shuma[num4];
P2=0x07;
}
} */
}
//0809.h中定义着0809 的初始化函数,和读取0809中的数据函数
unsigned char data0809=0;
sbit start=P1^0;//启动0809引脚
sbit EOC=P1^1;//转换结束标志位
sbit OE=P1^2;//0809使能端
//clk时钟在int.h中定义
void s0809_init()//0809初始化
{
start=0;
_nop_();
_nop_();
_nop_();
OE=0;
}
void s0809()
{
start=1;
_nop_();
_nop_();
_nop_();
start=0;
_nop_();
_nop_();
_nop_();
while(!EOC) //等待0809 中的数据,当转换完成后,EOC就会变高,就会跳出循环
{
disp();//等待0809数据的时候,要继续数码管扫描
};
OE=1;
_nop_();
_nop_();
_nop_();
data0809=P2;//从0809中读取数据
bright=data0809/26%10;//将光度等级划分成10个等级
vol=data0809*5/256;//电压的整数部分
ta=data0809*5%256;
ge=ta%10;//电压的小数部分
OE=0;
}
void main()
{
bit flag=0;
time0_init();//定时器初始化
s0809_init();//0809初始化
while(1)
{
s0809();//检测0809的标志位,查看是否转换完毕,若转换完则读取转化数据,否则等待
if(data0809/26%10<my_bright)//my_bright是自己定义的等级值,若光线等级大于这个值时就关灯,
//小于时就开灯
{
unsigned char i;
i=second;
while(1)
{
disp();
if(second-i>=1)//开关灯延时,1可以换成2或者其他数据,当灯光亮度和自定义的亮度不同时
//就会延时1或者其他数据之后再改变
break;//跳出循环
}
if(flag==0)
{
if(on_off<9) //开关次数,当开关次数小于9次时,开关次数就加一,当大于或者等于9时就不变,始终在第三位数码管上显示9
on_off++;
second=0;//秒计数值清零
}
flag=1;delay_on=1;//启动继电器
}
else
{
flag=0;delay_on=0;//关闭继电器
}
};
}嘿嘿牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛牛
图很赞