找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10456|回复: 7
打印 上一主题 下一主题
收起左侧

单片机智能视力保护器(智能台灯)的仿真和程序源码

  [复制链接]
跳转到指定楼层
楼主
ID:363148 发表于 2018-7-2 15:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
智能台灯电路原理图如下:


仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. //宏定义          重命名作用将unsigned int、unsigned char变为unit、uchar
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. #define DUAN P0          //用DUAN标识代表P0口  
  5. //头函数
  6. #include <reg52.h>                                                                                                                                                                                                  
  7. #include <ADC0809.h>
  8.                                                                                                                                                                                                                        
  9. unsigned char code tab[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28,0xff}; //数字0-9的编码//gc.debfa         
  10. unsigned char code tab_dian[]={0x80,0x9b,0x42,0x0a,0x19,0x0c,0x04,0x9a,0x00,0x08,0xdf}; //带点的数字0-9的编码//gc.debfa         
  11. uchar pdata tt[51];                   //定义空数组用于AD0809取平均值

  12. uchar scale=20,rsd_sec;                //定义占空比比例,热释电计时秒变量
  13. char min,sec;                                //定义计时分秒

  14. bit bdata flag_auto,ss,flag_bs,flag_rsd,flag_jiejin=1;          //位定义自动切换的,闪烁标志,报警位标志,热释电动作标志,接近传感器标志
  15. uchar flag_set=0;                        //设置变量:0 正常  1 调分  2 调秒
  16. uchar lum;                                        //ad0809读出值

  17. //函数声明
  18. void delay(uchar i);   //延时函数

  19. //管脚声明
  20. sbit LED = P3^4;        //灯光控制输出
  21. sbit change= P2^3;          //自动模式切换按键
  22. sbit set = P2^2;         //设置按键
  23. sbit add = P2^1;        //加按键
  24. sbit sub = P2^0;        //减按键
  25. sbit rsd = P3^6;   //热释电
  26. sbit jiejin=P3^5;  //接近开关
  27. sbit buzz=P3^7;           //蜂鸣器

  28. sbit W0=P2^7;
  29. sbit W1=P2^6;
  30. sbit W2=P2^5;
  31. sbit W3=P2^4;          //数码管位端
  32. /***********显示函数*************/
  33. void display()
  34. {
  35.         if(flag_set==0)                         //正常模式下
  36.         {
  37.                 DUAN=tab[min/10];          //送入段码
  38.                 W0=0;                                  //打开位地址
  39.                 delay(1);                          //小延时
  40.                 W0=1;                                  //关闭位地址
  41.                 DUAN=tab_dian[min%10]; //下同
  42.                 W1=0;
  43.                 delay(1);
  44.                 W1=1;
  45.                 DUAN=tab[sec/10];
  46.                 W2=0;
  47.                 delay(1);
  48.                 W2=1;
  49.                 DUAN=tab[sec%10];
  50.                 W3=0;
  51.                 delay(1);
  52.                 W3=1;
  53.         }
  54.         else if(flag_set==1)                 //设置模式下闪烁相应位
  55.         {
  56.                 if(ss==1)                                 //闪烁标志  ss=1 正常显示
  57.                 {
  58.                         DUAN=~tab[min/10];
  59.                         W0=0;
  60.                         delay(1);
  61.                         W0=1;
  62.                         DUAN=~tab_dian[min%10];
  63.                         W1=0;
  64.                         delay(1);
  65.                         W1=1;
  66.                 }
  67.                 else                                           //闪烁标志  ss=0 熄灭相应位 达到闪烁效果         ss在定时器里500ms取反一次
  68.                 {
  69.                         DUAN=~tab[10];
  70.                         W0=0;
  71.                         delay(1);
  72.                         W0=1;
  73.                         DUAN=~tab_dian[10];
  74.                         W1=0;
  75.                         delay(1);
  76.                         W1=1;
  77.                 }
  78.                 DUAN=~tab[sec/10];
  79.                 W2=0;
  80.                 delay(1);
  81.                 W2=1;
  82.                 DUAN=~tab[sec%10];
  83.                 W3=0;
  84.                 delay(1);
  85.                 W3=1;
  86.         }
  87.         else
  88.         {
  89.                
  90.                 DUAN=~tab[min/10];
  91.                 W0=0;
  92.                 delay(1);
  93.                 W0=1;
  94.                 DUAN=~tab_dian[min%10];
  95.                 W1=0;
  96.                 delay(1);
  97.                 W1=1;
  98.                 if(ss==1)
  99.                 {
  100.                         DUAN=~tab[sec/10];
  101.                         W2=0;
  102.                         delay(1);
  103.                         W2=1;
  104.                         DUAN=~tab[sec%10];
  105.                         W3=0;
  106.                         delay(1);
  107.                         W3=1;
  108.                 }
  109.                 else
  110.                 {
  111.                         DUAN=~tab[10];
  112.                         W2=0;
  113.                         delay(1);
  114.                         W2=1;
  115.                         DUAN=~tab[10];
  116.                         W3=0;
  117.                         delay(1);
  118.                         W3=1;
  119.                 }
  120.         }
  121. }
  122. /*****************按键函数*****************/
  123. void KEY()
  124. {
  125.         uint lum_mean,lum_all;
  126.         uchar b,c;
  127.         if(change==0)                                  //自动切换按键按下
  128.         {
  129.                 delay(10);                                  //按键去抖
  130.                 if(change==0)                          //再次判断按键按下
  131.                 {
  132.                         buzz=0;                                  //蜂鸣器鸣响
  133.                         flag_auto=!flag_auto; //自动模式标志位取反
  134.                         if(flag_auto==1)          //当切换到手动模式时  首先将LED发光比例设置在50%
  135.                         scale=20;
  136.                        
  137.                 }
  138.                 while(!change) display();buzz=1; //按键释放  松开按键后关闭蜂鸣器  display()显示输出函数
  139.         }
  140.         if(jiejin==0&&flag_jiejin==1)         //接近传感器检测到障碍时  开启报警
  141.         {
  142.                 buzz=0;
  143.                 flag_jiejin=0;
  144.         }
  145.         if(jiejin!=flag_jiejin)                          //接近传感器检测不到障碍时  关闭报警
  146.         {
  147.                 buzz=1;
  148.                 flag_jiejin=1;
  149.         }
  150.         if(set==0)                                                  //设置键按下时
  151.         {
  152.                 delay(10);
  153.                 if(set==0)
  154.                 {
  155.                         buzz=0;
  156.                         flag_set++;                                  //设置变量++
  157.                         if(flag_set==3)                          //加到3时回复回正常模式
  158.                         flag_set=0;
  159.                         flag_bs=0;                                 //按下设置 关闭报警
  160.                        
  161.                 }
  162.                 while(!set) display(); buzz=1;        //按键释放
  163.         }
  164.         if(flag_set==1)                                          //加键按键只有在设置状态(flag_set!=0)时按下才有效
  165.         {                                                                  //调分时
  166.                 if(add==0)                                          //加按键按下时
  167.                 {
  168.                         delay(10);
  169.                         if(add==0)
  170.                         {
  171.                                 buzz=0;
  172.                                 min++;                                  //分++
  173.                                 if(min>=60)
  174.                                 min=0;
  175.                                
  176.                         }
  177.                         while(!add) display(); buzz=1;
  178.                 }
  179.                 if(sub==0)                                          //减按键按下时
  180.                 {
  181.                         delay(10);
  182.                         if(sub==0)
  183.                         {
  184.                                 buzz=0;
  185.                                 min--;                                  //分--
  186.                                 if(min>0)
  187.                                 min=59;
  188.                                
  189.                         }
  190.                         while(!sub) display(); buzz=1;
  191.                 }
  192.         }
  193.         if(flag_set==2)
  194.         {                                                                //调秒时
  195.                 if(add==0)                                        //加键按下
  196.                 {
  197.                         delay(10);
  198.                         if(add==0)
  199.                         {
  200.                                 buzz=0;
  201.                                 sec++;                                 //秒++
  202.                                 if(sec>=60)
  203.                                 sec=0;
  204.                                
  205.                         }
  206.                         while(!add) display(); buzz=1;
  207.                 }
  208.                 if(sub==0)                                         //减键按下
  209.                 {
  210.                         delay(10);
  211.                         if(sub==0)
  212.                         {
  213.                                 buzz=0;
  214.                                 sec--;                                 //秒--
  215.                                 if(sec<0)
  216.                                 sec=59;
  217.                                
  218.                         }
  219.                         while(!sub) display();        buzz=1;
  220.                 }
  221.                 while(!sub);
  222.         }
  223.                
  224.         if(flag_auto==0)                                        //自动模式时
  225.         {
  226.                 if(flag_rsd==1)                                        //且有人在范围内时
  227.                 {
  228.                         for(b=0;b<49;b++)                         //将空数组tt【】内数值整体左移一位
  229.                         {
  230.                                 tt[b]=tt[b+1];                        //将后一数值放到前一位置
  231.                         }
  232.                         tt[49]=ADC0809();                        //将读出的ad0809数值放入tt【49】
  233.                         for(c=0;c<50;c++)                        //将tt【】内数值相加
  234.                         {
  235.                                 lum_all=lum_all+tt[c];
  236.                         }
  237.                         lum_mean=lum_all/50;                //将总数/50取出平均值
  238. //                        lum_all=0;                                        //将总数清零
  239.                                
  240.                         if(lum_mean<=30) scale=1;                           //判断取出平均值大小  小于30  发光强度0%
  241.                         else if(lum_mean>=150) scale=41;           //大于150  发光强度100%
  242.                         else scale=((lum_mean-30)/3)+1;                   //其他值时将其计算得到发光强度 (计算目的是为了得到一个1-41之间的数值 控制灯光变化)
  243.                 }
  244.                 else
  245.                 scale=1;                                         //没有人在范围内时 将灯光亮度调至0%
  246.         }
  247.         else                                                        //手动模式下
  248.         {
  249.                 if(flag_set==0)                                 //正常模式下
  250.                 {
  251.                         if(add==0)                                 //加键按下
  252.                         {
  253.                                 delay(10);
  254.                                 if(add==0)
  255.                                 {
  256.                                 //        buzz=0;
  257.                                         scale++;                  //灯光比例++
  258.                                         if(scale>=41)
  259.                                         scale=41;
  260.                                         display();
  261.                                 }
  262.                         //        while(!add) display();        buzz=1;
  263.                         }
  264.                         if(sub==0)                                  //减键按下时
  265.                         {
  266.                                 delay(10);
  267.                                 if(sub==0)
  268.                                 {
  269.                                 //        buzz=0;
  270.                                         scale--;                   //灯光比例--
  271.                                         if(scale>1)
  272.                                         scale=1;
  273.                                         display();
  274.                                 }
  275.                 //                while(!sub) display(); buzz=1;
  276.                         }
  277.                 }
  278.         }
  279. }
  280. /*********定时器初始化函数**********/
  281. void init()
  282. {
  283.         TMOD=0x11;           //工作方式
  284.         TH1=0x3c;
  285.         TL1=0xb0;           //T1赋初值50ms
  286.         TH0=0xff;
  287.         TL0=0xe7;                //T0赋初值25us          
  288.         ET0=1;
  289.         ET1=1;                   //打开中断允许开关
  290.         EA=1;                   //中断总开关
  291.         TR0=1;
  292.         TR1=0;                   //定时器定时开关
  293. }

  294. /****************主函数**********************/
  295. void main()
  296. {
  297.         init();                  //调用初始化函数
  298.         flag_auto=1;  //初始化手动模式
  299.         rsd=0;                  //热释电引脚置低(有信号时时高电平)
  300.         delay(500);          //延时500ms后开机

  301.         while(1)                   //循环
  302.         {
  303.                 KEY();                 //调用按键函数
  304.                 display();        //调用显示函数
  305.         }
  306. }
  307. /*****************延时函数:大约1ms************************/
  308. void delay(uchar i)
  309. {
  310.   uchar j,k;
  311.   for(j=i;j>0;j--)
  312.     for(k=125;k>0;k--);
  313. }
  314. /******************定时器T0服务函数:脉冲发生函数*******************/
  315. void time0() interrupt 1
  316. {
  317.         uchar n;
  318.         TH0=0xff;
  319.         TL0=0xe7;                 //重新赋初值
  320.         n++;                         //每25us  n++
  321.         if(n>scale)                 //n<设置比例时,打开灯
  322.         {
  323.                 LED=1;
  324.         }
  325.         else if(n<=scale)//n大于等于设置比例时 关闭灯
  326.         {
  327.                 LED=0;
  328.         }
  329.         if(n==40)                 //n==40  :25us*40=1ms   1kHZ
  330.         {
  331.                 n=0;                 //n=0
  332.         }
  333.         else ;       
  334. }
  335. /********************定时器T0服务函数:计时和闪烁控制********************/
  336. void time1() interrupt 3
  337. {
  338.         uchar m;
  339.         TH1=0x3c;
  340.         TL1=0xb0;                 //重新赋初值
  341.         m++;                         //50ms  m++
  342.         if((m==10||m==20)&&flag_set!=0)          //每过500ms  并且 在设置状态时
  343.         {
  344.                 ss=!ss;                                                  //闪烁变量取反
  345.         }
  346.         if(m==20)                                                  //到达1s时
  347.         {
  348.                 m=0;                                                  //m=0
  349.                 if(rsd==0)                                          //热释电无信号时
  350.                 rsd_sec++;                                          //热释电计时秒++
  351.                 if(rsd_sec<=30&&rsd==1)                  //热释电计时秒小于等于30 并且 热释电有信号时
  352.                 {
  353.                         rsd_sec=0;                                  //将热释电秒清零
  354.                         flag_rsd=1;                                  //标志位置1 控制AD0809采集数值 调节灯光亮度
  355.                 }
  356.                 else if(rsd_sec>30&&rsd==0)          //热释电计时秒大于30 并且 热释电无信号时
  357.                 {
  358.                         flag_rsd=0;                                  //标志位置0 停止ad0809转换 关闭灯光
  359.                         rsd_sec=0;                                  //热释电计时秒清零
  360.                 }
  361.                 if(flag_set==0&&flag_bs==0&&((min+sec)!=0))                 //正常模式下&&未报警&&定时时间不为零时
  362.                 {
  363.                         sec--;
  364.                         if(sec<0)                                                                         //定时秒--  小于0时
  365.                         {
  366.                                 sec=59;                                                                         //复位到59秒
  367.                                 min--;                                                                         //分--
  368.                         }
  369.                         if(min<=0&&sec==0)                                                         //分和秒都减到零时
  370.                         {
  371.                                 min=0;
  372.                                 flag_bs=1;
  373.                                 buzz=0;                                                                         //蜂鸣器报警提示时间到
  374.                         }
  375.                 }
  376. //                else buzz=1;       
  377.         }       
  378. }
复制代码

所有资料51hei提供下载:
智能台灯.zip (103.2 KB, 下载次数: 305)



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:239426 发表于 2019-2-4 14:34 | 只看该作者
感谢楼主,好东西
回复

使用道具 举报

板凳
ID:500244 发表于 2019-4-2 16:40 | 只看该作者
坑人,没结果
回复

使用道具 举报

地板
ID:532547 发表于 2019-6-1 20:49 | 只看该作者
oh那尼 发表于 2019-2-4 14:34
感谢楼主,好东西

好东西
回复

使用道具 举报

5#
ID:551342 发表于 2019-6-2 20:08 | 只看该作者
我怎么运行不出来啊
回复

使用道具 举报

6#
ID:532547 发表于 2019-6-5 14:54 | 只看该作者
oh那尼 发表于 2019-2-4 14:34
感谢楼主,好东西

可以描述一下台灯工作的完整流程吗?十分感谢!
回复

使用道具 举报

7#
ID:563999 发表于 2019-6-16 22:59 | 只看该作者
这个代码好像用不起欸
回复

使用道具 举报

8#
ID:1011865 发表于 2022-3-25 10:14 来自手机 | 只看该作者
楼主,电压是多少
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表