教学用,基于51单片机的智能台灯,有兴趣的朋友们可以看看
单片机源程序如下:
- /**********************************************************************
- * 名称 : 智能调光台灯
- * 功能 : (1)亮度不够且有人靠近时台灯自动亮;
- (2)靠的太近会提醒坐姿不正(蜂鸣器)
- (3)附近无人时台灯自动熄灭(30秒) 时间可调
- (4)根据环境亮度调节等亮度
- (5)可手动调节台灯亮度
- (6)设定学习时间
- * 备注 :
- ***********************************************************************/
- //头函数
- #include <reg52.h>
- #include <ADC0809.H>
- //宏定义
- #define uint unsigned int
- #define uchar unsigned char
- #define DUAN P0 //数码管段位
-
- unsigned char code tab[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28,0xff}; //0-9的显示码表 gc.debfa
- unsigned char code tab_dian[]={0x80,0x9b,0x42,0x0a,0x19,0x0c,0x04,0x9a,0x00,0x08,0xdf}; //带点0-9的显示码表
- uchar pdata tt[51]; //定义空数组用于AD0809取平均值
- uchar scale=20,rsd_sec; //定义占空比比例,热释电计时秒变量
- char min,sec; //定义计时分秒
- //位定义
- bit bdata flag_auto, //自动切换标志位
- ss, //闪烁标志位
- flag_bs, //报警位标志位
- flag_rsd, //热释电动作标志位
- flag_jiejin=1; //接近传感器标志位
- uchar flag_set=0; //设置变量:0 正常 1 调分 2 调秒
- uchar lum; //ad0809读出值
- //函数声明
- void delay(uchar i);
- //管脚声明
- sbit LED = P3^4; //PWM输出
- sbit change= P2^3; //自动模式切换按键
- sbit set = P2^2; //设置按键
- sbit add = P2^1; //加按键
- sbit sub = P2^0; //减按键
- sbit rsd = P3^6; //热释电
- sbit jiejin=P3^5; //接近开关
- sbit buzz=P3^7;
- sbit W0=P2^7; //数码管位端
- sbit W1=P2^6;
- sbit W2=P2^5;
- sbit W3=P2^4;
- /**********************************************************************
- * 名称 : display();
- * 功能 : 数码管显示
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void display()
- {
- if(flag_set==0) //正常模式下
- {
- DUAN=tab[min/10]; //送入段码,秒数高位
- W0=0; //打开位地址
- delay(1); //小延时
- W0=1; //关闭位地址
- DUAN=tab_dian[min%10]; //送入段码,秒数低位
- W1=0;
- delay(1);
- W1=1;
- DUAN=tab[sec/10]; //送入段码,分钟数高位
- W2=0;
- delay(1);
- W2=1;
- DUAN=tab[sec%10]; //送入段码,分钟数高位
- W3=0;
- delay(1);
- W3=1;
- }
- else if(flag_set==1) //设置模式下闪烁相应位
- {
- if(ss==1) //闪烁标志 ss=1 正常显示
- {
- DUAN=~tab[min/10];
- W0=0;
- delay(1);
- W0=1;
- DUAN=~tab_dian[min%10];
- W1=0;
- delay(1);
- W1=1;
- }
- else //闪烁标志 ss=0 熄灭相应位 达到闪烁效果 ss在定时器里500ms取反一次
- {
- DUAN=~tab[10]; //
- W0=0;
- delay(1);
- W0=1;
- DUAN=~tab_dian[10];
- W1=0;
- delay(1);
- W1=1;
- }
- DUAN=~tab[sec/10];
- W2=0;
- delay(1);
- W2=1;
- DUAN=~tab[sec%10];
- W3=0;
- delay(1);
- W3=1;
- }
- else
- {
-
- DUAN=~tab[min/10];
- W0=0;
- delay(1);
- W0=1;
- DUAN=~tab_dian[min%10];
- W1=0;
- delay(1);
- W1=1;
- if(ss==1)
- {
- DUAN=~tab[sec/10];
- W2=0;
- delay(1);
- W2=1;
- DUAN=~tab[sec%10];
- W3=0;
- delay(1);
- W3=1;
- }
- else
- {
- DUAN=~tab[10];
- W2=0;
- delay(1);
- W2=1;
- DUAN=~tab[10];
- W3=0;
- delay(1);
- W3=1;
- }
- }
- }
- /**********************************************************************
- * 名称 : KEY();
- * 功能 : 按键控制
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void KEY()
- {
- uint lum_mean,lum_all;
- uchar b,c;
- if(change==0) //自动切换按键按下
- {
- delay(10); //去抖
- if(change==0) //再次判断按键按下
- {
- buzz=0; //蜂鸣器鸣响
- flag_auto=!flag_auto; //自动模式标志位取反
- if(flag_auto==1) //当切换到手动模式时 首先将LED发光比例PWM设置在50%
- scale=20;
-
- }
- while(!change) display();buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
- }
- if(jiejin==0&&flag_jiejin==1) //接近传感器检测到障碍时 开启报警
- {
- buzz=0;
- flag_jiejin=0;
- }
- if(jiejin!=flag_jiejin) //接近传感器检测不到障碍时 关闭报警
- {
- buzz=1;
- flag_jiejin=1;
- }
- if(set==0) //设置键按下时
- {
- delay(10);
- if(set==0)
- {
- buzz=0;
- flag_set++; //设置变量++
- if(flag_set==3) //加到3时回复回正常模式
- flag_set=0;
- flag_bs=0; //按下设置 关闭报警
-
- }
- while(!set) display(); buzz=1;//等待按键释放 松开按键后关闭蜂鸣器、刷新显示
- }
- if(flag_set==1) //加键按键只有在设置状态(flag_set!=0)时按下才有效 调分
- {
- if(add==0) //加按键按下时
- {
- delay(10); //消抖
- if(add==0)
- {
- buzz=0; //蜂鸣器响
- min++; //分++
- if(min>=60)
- min=0;
-
- }
- while(!add) display(); buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
- }
- if(sub==0) //减按键按下时
- {
- delay(10); //消抖
- if(sub==0)
- {
- buzz=0; //蜂鸣器响
- min--; //分--
- if(min>0)
- min=59;
-
- }
- while(!sub) display(); buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
- }
- }
- if(flag_set==2) //调秒
- {
- if(add==0) //加键按下
- {
- delay(10); //消抖
- if(add==0)
- {
- buzz=0; //蜂鸣器响
- sec++; //秒++
- if(sec>=60)
- sec=0;
-
- }
- while(!add) display(); buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
- }
- if(sub==0) //减键按下
- {
- delay(10);
- if(sub==0) //消抖
- {
- buzz=0; //蜂鸣器响
- sec--; //秒--
- if(sec<0)
- sec=59;
-
- }
- while(!sub) display(); buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
- }
- while(!sub);
- }
-
- if(flag_auto==0) //自动模式
- {
- if(flag_rsd==1) //且有人在范围内时 环境发光强度控制灯光变化
- {
- for(b=0;b<49;b++) //将空数组tt[]内数值整体左移一位
- {
- tt[b]=tt[b+1]; //将后一数值放到前一位置
- }
- tt[49]=ADC0809(); //将读出的ad0809数值放入tt[49]
- for(c=0;c<50;c++) //将tt[]内数值相加
- {
- lum_all=lum_all+tt[c];
- }
- lum_mean=lum_all/50; //将总数/50取出平均值
- // lum_all=0; //将总数清零
-
- if(lum_mean<=30) scale=1; //判断取出平均值大小 小于30 发光强度0%
- else if(lum_mean>=150) scale=41; //大于150 发光强度100%
- else scale=((lum_mean-30)/3)+1; //其他值时将其计算得到发光强度 (计算目的是为了得到一个1-41之间的数值 控制灯光变化)
- }
- else
- scale=1; //没有人在范围内时 将灯光亮度调至0%
- }
- else //手动模式下
- {
- if(flag_set==0) //正常模式下
- {
- if(add==0) //加键按下
- {
- delay(10);
- if(add==0)
- {
- // buzz=0; //蜂鸣器响
- scale++; //灯光比例++
- if(scale>=41)
- scale=41;
- display();
- }
- // while(!add) display(); buzz=1;
- }
- if(sub==0) //减键按下时
- {
- delay(10);
- if(sub==0)
- {
- // buzz=0; //蜂鸣器响
- scale--; //灯光比例--
- if(scale>1)
- scale=1;
- display();
- }
- // while(!sub) display(); buzz=1;
- }
- }
- }
- }
- /**********************************************************************
- * 名称 : init();
- * 功能 : 初始化定时器
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void init()
- {
- TMOD=0x11; //工作方式1
- TH1=0x3c;
- TL1=0xb0; //T1赋初值50ms
- TH0=0xff;
- TL0=0xe7; //T0赋初值25us
- ET0=1;
- ET1=1; //打开中断允许开关
- EA=1; //中断总开关
- TR0=1; //开定时器0 开关
- TR1=0; //关定时器0 开关
- }
- /**********************************************************************
- * 名称 : main();
- * 功能 : 主函数
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void main()
- {
- init(); //调用初始化函数
- flag_auto=1; //初始化手动模式
- rsd=0; //热释电引脚置低(有信号时时高电平)
- delay(500); //延时500ms后开机
- while(1) //大循环
- {
- KEY(); //调用按键函数
- display(); //调用显示函数
- }
- }
- /**********************************************************************
- * 名称 : delay();
- * 功能 : 延时函数:大约1ms
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void delay(uchar i)
- {
- uchar j,k;
- for(j=i;j>0;j--)
- for(k=125;k>0;k--);
- }
- /**********************************************************************
- * 名称 : void time0() interrupt 1
- * 功能 : 定时器T0 中断服务函数:PWM脉冲发生函数
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void time0() interrupt 1
- {
- uchar n;
- TH0=0xff;
- TL0=0xe7; //重新赋初值
- n++; //每25us n++
- if(n>scale) //n<设置比例时,打开灯
- {
- LED=1;
- }
- else if(n<=scale)//n大于等于设置比例时 关闭灯
- {
- LED=0;
- }
- if(n==40) //n==40 :25us*40=1ms 1kHZ
- {
- n=0; //n=0
- }
- else ;
- }
- /**********************************************************************
- * 名称 : void time1() interrupt 3
- * 功能 : 定时器T1 中断服务函数:计时和闪烁控制 红外热释
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void time1() interrupt 3
- {
- uchar m;
- TH1=0x3c;
- TL1=0xb0; //重新赋初值
- m++; //50ms m++
- if((m==10||m==20)&&flag_set!=0) //每过500ms 并且 在设置状态时
- {
- ss=!ss; //闪烁变量取反
- }
- if(m==20) //到达1s时
- {
- m=0; //m=0
- if(rsd==0) //热释电无信号时
- rsd_sec++; //热释电计时秒++
- if(rsd_sec<=30&&rsd==1) //热释电计时秒小于等于30 并且 热释电有信号时
- {
- rsd_sec=0; //将热释电秒清零
- flag_rsd=1; //标志位置1 控制AD0809采集数值 调节灯光亮度
- }
- else if(rsd_sec>30&&rsd==0) //热释电计时秒大于30 并且 热释电无信号时
- {
- flag_rsd=0; //标志位置0 停止ad0809转换 关闭灯光
- rsd_sec=0; //热释电计时秒清零
- }
- if(flag_set==0&&flag_bs==0&&((min+sec)!=0)) //正常模式下&&未报警&&定时时间不为零时
- {
- sec--;
- if(sec<0) //定时秒-- 小于0时
- {
- sec=59; //复位到59秒
- min--; //分--
- }
- if(min<=0&&sec==0) //分和秒都减到零时
- {
- min=0;
- flag_bs=1;
- buzz=0; //蜂鸣器报警提示时间到
- }
- }
- // else buzz=1;
- }
- }
复制代码
所有资料51hei提供下载:
智能台灯.rar
(244.17 KB, 下载次数: 125)
|