找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3357|回复: 2
收起左侧

单片机智能台灯源程序

[复制链接]
ID:724521 发表于 2020-4-8 09:04 | 显示全部楼层 |阅读模式
066c16b3e1e4537156ac44cc78cb470.png

单片机源程序如下:
  1. /**********************************************************************
  2. * 名称 : 智能调光台灯
  3. * 功能 : (1)亮度不够且有人靠近时台灯自动亮;
  4.          (2)靠的太近会提醒坐姿不正(蜂鸣器)
  5.          (3)附近无人时台灯自动熄灭(30秒)  时间可调
  6.          (4)根据环境亮度调节等亮度
  7.                                  (5)可手动调节台灯亮度
  8.                                  (6)设定学习时间
  9. * 备注 :

  10. ***********************************************************************/

  11. //头函数
  12. #include <reg52.h>                                                                                                                                                                                                  
  13. #include <ADC0809.H>

  14. //宏定义
  15. #define uint unsigned int
  16. #define uchar unsigned char
  17. #define DUAN P0                                  //数码管段位

  18.                                                                                                                                                                                                                        
  19. unsigned char code tab[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28,0xff};       //0-9的显示码表      gc.debfa         
  20. unsigned char code tab_dian[]={0x80,0x9b,0x42,0x0a,0x19,0x0c,0x04,0x9a,0x00,0x08,0xdf};  //带点0-9的显示码表           
  21. uchar pdata tt[51];                    //定义空数组用于AD0809取平均值

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

  24. //位定义
  25. bit bdata flag_auto,                //自动切换标志位
  26.           ss,                                //闪烁标志位
  27.                   flag_bs,                        //报警位标志位
  28.                   flag_rsd,                        //热释电动作标志位
  29.                   flag_jiejin=1;    //接近传感器标志位

  30. uchar flag_set=0;                        //设置变量:0 正常  1 调分  2 调秒
  31. uchar lum;                                        //ad0809读出值

  32. //函数声明
  33. void delay(uchar i);

  34. //管脚声明
  35. sbit LED = P3^4;        //PWM输出
  36. sbit change= P2^3;        //自动模式切换按键
  37. sbit set = P2^2;        //设置按键
  38. sbit add = P2^1;        //加按键
  39. sbit sub = P2^0;        //减按键
  40. sbit rsd = P3^6;    //热释电
  41. sbit jiejin=P3^5;   //接近开关
  42. sbit buzz=P3^7;

  43. sbit W0=P2^7;                //数码管位端
  44. sbit W1=P2^6;
  45. sbit W2=P2^5;
  46. sbit W3=P2^4;

  47. /**********************************************************************
  48. * 名称 : display();
  49. * 功能 : 数码管显示
  50. * 输入 : 无
  51. * 输出 : 无
  52. ***********************************************************************/          
  53. void display()
  54. {
  55.         if(flag_set==0)                           //正常模式下
  56.         {
  57.                 DUAN=tab[min/10];           //送入段码,秒数高位
  58.                 W0=0;                                   //打开位地址
  59.                 delay(1);                           //小延时
  60.                 W0=1;                                   //关闭位地址
  61.                 DUAN=tab_dian[min%10]; //送入段码,秒数低位
  62.                 W1=0;
  63.                 delay(1);
  64.                 W1=1;
  65.                 DUAN=tab[sec/10];           //送入段码,分钟数高位
  66.                 W2=0;
  67.                 delay(1);
  68.                 W2=1;
  69.                 DUAN=tab[sec%10];           //送入段码,分钟数高位
  70.                 W3=0;
  71.                 delay(1);
  72.                 W3=1;
  73.         }
  74.         else if(flag_set==1)           //设置模式下闪烁相应位
  75.         {
  76.                 if(ss==1)                           //闪烁标志  ss=1 正常显示
  77.                 {
  78.                         DUAN=~tab[min/10];
  79.                         W0=0;
  80.                         delay(1);
  81.                         W0=1;
  82.                         DUAN=~tab_dian[min%10];
  83.                         W1=0;
  84.                         delay(1);
  85.                         W1=1;
  86.                 }
  87.                 else                                   //闪烁标志  ss=0 熄灭相应位 达到闪烁效果         ss在定时器里500ms取反一次
  88.                 {
  89.                         DUAN=~tab[10];           //
  90.                         W0=0;
  91.                         delay(1);
  92.                         W0=1;
  93.                         DUAN=~tab_dian[10];
  94.                         W1=0;
  95.                         delay(1);
  96.                         W1=1;
  97.                 }
  98.                 DUAN=~tab[sec/10];
  99.                 W2=0;
  100.                 delay(1);
  101.                 W2=1;
  102.                 DUAN=~tab[sec%10];
  103.                 W3=0;
  104.                 delay(1);
  105.                 W3=1;
  106.         }
  107.         else
  108.         {
  109.                
  110.                 DUAN=~tab[min/10];
  111.                 W0=0;
  112.                 delay(1);
  113.                 W0=1;
  114.                 DUAN=~tab_dian[min%10];
  115.                 W1=0;
  116.                 delay(1);
  117.                 W1=1;
  118.                 if(ss==1)
  119.                 {
  120.                         DUAN=~tab[sec/10];
  121.                         W2=0;
  122.                         delay(1);
  123.                         W2=1;
  124.                         DUAN=~tab[sec%10];
  125.                         W3=0;
  126.                         delay(1);
  127.                         W3=1;
  128.                 }
  129.                 else
  130.                 {
  131.                         DUAN=~tab[10];
  132.                         W2=0;
  133.                         delay(1);
  134.                         W2=1;
  135.                         DUAN=~tab[10];
  136.                         W3=0;
  137.                         delay(1);
  138.                         W3=1;
  139.                 }
  140.         }
  141. }

  142. /**********************************************************************
  143. * 名称 : KEY();
  144. * 功能 : 按键控制
  145. * 输入 : 无
  146. * 输出 : 无
  147. ***********************************************************************/
  148. void KEY()
  149. {
  150.         uint lum_mean,lum_all;
  151.         uchar b,c;
  152.         if(change==0)                                  //自动切换按键按下
  153.         {
  154.                 delay(10);                                  //去抖
  155.                 if(change==0)                          //再次判断按键按下
  156.                 {
  157.                         buzz=0;                                  //蜂鸣器鸣响
  158.                         flag_auto=!flag_auto; //自动模式标志位取反
  159.                         if(flag_auto==1)          //当切换到手动模式时  首先将LED发光比例PWM设置在50%
  160.                         scale=20;
  161.                        
  162.                 }
  163.                 while(!change) display();buzz=1; //等待按键释放  松开按键后关闭蜂鸣器、刷新显示
  164.         }
  165.         if(jiejin==0&&flag_jiejin==1) //接近传感器检测到障碍时  开启报警
  166.         {
  167.                 buzz=0;
  168.                 flag_jiejin=0;
  169.         }
  170.         if(jiejin!=flag_jiejin)              //接近传感器检测不到障碍时  关闭报警
  171.         {
  172.                 buzz=1;
  173.                 flag_jiejin=1;
  174.         }
  175.         if(set==0)                                      //设置键按下时
  176.         {
  177.                 delay(10);
  178.                 if(set==0)
  179.                 {
  180.                         buzz=0;
  181.                         flag_set++;                          //设置变量++
  182.                         if(flag_set==3)                  //加到3时回复回正常模式
  183.                         flag_set=0;
  184.                         flag_bs=0;                          //按下设置 关闭报警
  185.                        
  186.                 }
  187.                 while(!set) display(); buzz=1;//等待按键释放  松开按键后关闭蜂鸣器、刷新显示
  188.         }
  189.         if(flag_set==1)                                          //加键按键只有在设置状态(flag_set!=0)时按下才有效          调分
  190.         {                                                                 
  191.                 if(add==0)                                          //加按键按下时
  192.                 {
  193.                         delay(10);                                  //消抖
  194.                         if(add==0)
  195.                         {
  196.                                 buzz=0;                                  //蜂鸣器响
  197.                                 min++;                                  //分++
  198.                                 if(min>=60)
  199.                                 min=0;
  200.                                
  201.                         }
  202.                         while(!add) display(); buzz=1;         //等待按键释放  松开按键后关闭蜂鸣器、刷新显示
  203.                 }
  204.                 if(sub==0)                                          //减按键按下时
  205.                 {
  206.                         delay(10);                                  //消抖
  207.                         if(sub==0)
  208.                         {
  209.                                 buzz=0;                                  //蜂鸣器响
  210.                                 min--;                                  //分--
  211.                                 if(min>0)
  212.                                 min=59;
  213.                                
  214.                         }
  215.                         while(!sub) display(); buzz=1;         //等待按键释放  松开按键后关闭蜂鸣器、刷新显示
  216.                 }
  217.         }
  218.         if(flag_set==2)                                        //调秒
  219.         {                                                               
  220.                 if(add==0)                                        //加键按下
  221.                 {                                               
  222.                         delay(10);                                //消抖
  223.                         if(add==0)
  224.                         {
  225.                                 buzz=0;                                //蜂鸣器响
  226.                                 sec++;                                //秒++
  227.                                 if(sec>=60)
  228.                                 sec=0;
  229.                                
  230.                         }
  231.                         while(!add) display(); buzz=1;          //等待按键释放  松开按键后关闭蜂鸣器、刷新显示
  232.                 }
  233.                 if(sub==0)                                         //减键按下
  234.                 {
  235.                         delay(10);
  236.                         if(sub==0)                                 //消抖
  237.                         {
  238.                                 buzz=0;                                 //蜂鸣器响
  239.                                 sec--;                                 //秒--
  240.                                 if(sec<0)
  241.                                 sec=59;
  242.                                
  243.                         }
  244.                         while(!sub) display();        buzz=1;          //等待按键释放  松开按键后关闭蜂鸣器、刷新显示
  245.                 }
  246.                 while(!sub);
  247.         }
  248.                
  249.         if(flag_auto==0)                                        //自动模式
  250.         {
  251.                 if(flag_rsd==1)                                        //且有人在范围内时        环境发光强度控制灯光变化
  252.                 {
  253.                         for(b=0;b<49;b++)                         //将空数组tt[]内数值整体左移一位
  254.                         {
  255.                                 tt[b]=tt[b+1];                        //将后一数值放到前一位置
  256.                         }
  257.                         tt[49]=ADC0809();                        //将读出的ad0809数值放入tt[49]
  258.                         for(c=0;c<50;c++)                        //将tt[]内数值相加
  259.                         {
  260.                                 lum_all=lum_all+tt[c];
  261.                         }
  262.                         lum_mean=lum_all/50;                //将总数/50取出平均值
  263. //                        lum_all=0;                                        //将总数清零
  264.                                
  265.                         if(lum_mean<=30) scale=1;                           //判断取出平均值大小  小于30  发光强度0%
  266.                         else if(lum_mean>=150) scale=41;           //大于150  发光强度100%
  267.                         else scale=((lum_mean-30)/3)+1;                   //其他值时将其计算得到发光强度 (计算目的是为了得到一个1-41之间的数值 控制灯光变化)
  268.                 }
  269.                 else
  270.                 scale=1;                                         //没有人在范围内时 将灯光亮度调至0%
  271.         }
  272.         else                                                           //手动模式下
  273.         {
  274.                 if(flag_set==0)                                 //正常模式下
  275.                 {
  276.                         if(add==0)                                 //加键按下
  277.                         {
  278.                                 delay(10);
  279.                                 if(add==0)
  280.                                 {
  281.                                 //        buzz=0;           //蜂鸣器响
  282.                                         scale++;                  //灯光比例++
  283.                                         if(scale>=41)
  284.                                         scale=41;
  285.                                         display();
  286.                                 }
  287.                         //        while(!add) display();        buzz=1;
  288.                         }
  289.                         if(sub==0)                                  //减键按下时
  290.                         {
  291.                                 delay(10);
  292.                                 if(sub==0)
  293.                                 {
  294.                                 //        buzz=0;                           //蜂鸣器响
  295.                                         scale--;                   //灯光比例--
  296.                                         if(scale>1)
  297.                                         scale=1;
  298.                                         display();
  299.                                 }
  300.                 //                while(!sub) display(); buzz=1;
  301.                         }
  302.                 }
  303.         }
  304. }

  305. /**********************************************************************
  306. * 名称 : init();
  307. * 功能 : 初始化定时器
  308. * 输入 : 无
  309. * 输出 : 无
  310. ***********************************************************************/

  311. void init()
  312. {
  313.         TMOD=0x11;           //工作方式1
  314.         TH1=0x3c;
  315.         TL1=0xb0;           //T1赋初值50ms
  316.         TH0=0xff;
  317.         TL0=0xe7;           //T0赋初值25us          
  318.         ET0=1;
  319.         ET1=1;                   //打开中断允许开关
  320.         EA=1;                   //中断总开关
  321.         TR0=1;                   //开定时器0 开关
  322.         TR1=0;                   //关定时器0 开关
  323. }

  324. /**********************************************************************
  325. * 名称 : main();
  326. * 功能 : 主函数
  327. * 输入 : 无
  328. * 输出 : 无
  329. ***********************************************************************/
  330. void main()
  331. {
  332.         init();                  //调用初始化函数
  333.         flag_auto=1;  //初始化手动模式
  334.         rsd=0;                  //热释电引脚置低(有信号时时高电平)
  335.         delay(500);          //延时500ms后开机

  336.         while(1)          //大循环
  337.         {
  338.                 KEY();                 //调用按键函数
  339.                 display();         //调用显示函数
  340.         }
  341. }

  342. /**********************************************************************
  343. * 名称 : delay();
  344. * 功能 : 延时函数:大约1ms
  345. * 输入 : 无
  346. * 输出 : 无
  347. ***********************************************************************/
  348. void delay(uchar i)
  349. {
  350.   uchar j,k;
  351.   for(j=i;j>0;j--)
  352.     for(k=125;k>0;k--);
  353. }

  354. /**********************************************************************
  355. * 名称 : void time0() interrupt 1
  356. * 功能 : 定时器T0 中断服务函数:PWM脉冲发生函数
  357. * 输入 : 无
  358. * 输出 : 无
  359. ***********************************************************************/
  360. void time0() interrupt 1
  361. {
  362.         uchar n;
  363.         TH0=0xff;
  364.         TL0=0xe7;                 //重新赋初值
  365.         n++;                         //每25us  n++
  366.         if(n>scale)                 //n<设置比例时,打开灯
  367.         {
  368.                 LED=1;
  369.         }
  370.         else if(n<=scale)//n大于等于设置比例时 关闭灯
  371.         {
  372.                 LED=0;
  373.         }
  374.         if(n==40)                 //n==40  :25us*40=1ms   1kHZ
  375.         {
  376.                 n=0;                 //n=0
  377.         }
  378.         else ;       
  379. }

  380. /**********************************************************************
  381. ……………………

  382. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
智能台灯.rar (246.46 KB, 下载次数: 75)
回复

使用道具 举报

ID:171111 发表于 2020-5-5 11:32 | 显示全部楼层
程序里的 码表代码 没看懂是用共阴还是共阳的数码管呢? 请教下
回复

使用道具 举报

ID:797466 发表于 2020-8-11 20:52 来自手机 | 显示全部楼层
接5伏,是共阳
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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