• 基于51单片机的智能台灯设计


    基于51单片机的智能台灯

    (程序+PCB+原理图+设计报告)

    功能介绍

    具体功能:

    1.光敏电阻感应光亮,将信息处理给单片机,根据环境亮度调节亮度;

    2.使用E18- D80NK红外接近传感器,靠的太近,蜂鸣器会提醒报警;

    3.使用HC-SR501人体红外传感器,光亮不够且检测到人体时台灯自动亮;

    4.LED驱动电路采用3路串联、每路4颗的LED灯,可手动调节台灯亮度;

    5.可以设定学习时间;

    6.检测无人时(30秒)台灯自动熄灭 ,时间可调;

    1. /*************************************************
    2. * 名称 : 智能调光台灯
    3. * 功能 : (1)亮度不够且有人靠近时台灯自动亮;
    4. 2)靠的太近会提醒坐姿不正(蜂鸣器)
    5. 3)附近无人时台灯自动熄灭(30秒) 时间可调
    6. 4)根据环境亮度调节等亮度
    7. 5)可手动调节台灯亮度
    8. 6)设定学习时间
    9. ***********************************************************************/
    10. //头函数
    11. #include <reg52.h>
    12. #include <ADC0809.H>
    13. //宏定义
    14. #define uint unsigned int
    15. #define uchar unsigned char
    16. #define DUAN P0 //数码管段位
    17. unsigned char code tab[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28,0xff}; //0-9的显示码表 gc.debfa
    18. unsigned char code tab_dian[]={0x80,0x9b,0x42,0x0a,0x19,0x0c,0x04,0x9a,0x00,0x08,0xdf}; //带点0-9的显示码表
    19. uchar pdata tt[51]; //定义空数组用于AD0809取平均值
    20. uchar scale=20,rsd_sec; //定义占空比比例,热释电计时秒变量
    21. char min,sec; //定义计时分秒
    22. //位定义
    23. bit bdata flag_auto, //自动切换标志位
    24. ss, //闪烁标志位
    25. flag_bs, //报警位标志位
    26. flag_rsd, //热释电动作标志位
    27. flag_jiejin=1; //接近传感器标志位
    28. uchar flag_set=0; //设置变量:0 正常 1 调分 2 调秒
    29. uchar lum; //ad0809读出值
    30. //函数声明
    31. void delay(uchar i);
    32. //管脚声明
    33. sbit LED = P3^4; //PWM输出
    34. sbit change= P2^3; //自动模式切换按键
    35. sbit set = P2^2; //设置按键
    36. sbit add = P2^1; //加按键
    37. sbit sub = P2^0; //减按键
    38. sbit rsd = P3^6; //热释电
    39. sbit jiejin=P3^5; //接近开关
    40. sbit buzz=P3^7;
    41. sbit W0=P2^7; //数码管位端
    42. sbit W1=P2^6;
    43. sbit W2=P2^5;
    44. sbit W3=P2^4;
    45. /**********************************************************************
    46. * 名称 : display();
    47. * 功能 : 数码管显示
    48. * 输入 : 无
    49. * 输出 : 无
    50. ***********************************************************************/
    51. void display()
    52. {
    53. if(flag_set==0) //正常模式下
    54. {
    55. DUAN=tab[min/10]; //送入段码,秒数高位
    56. W0=0; //打开位地址
    57. delay(1); //小延时
    58. W0=1; //关闭位地址
    59. DUAN=tab_dian[min%10]; //送入段码,秒数低位
    60. W1=0;
    61. delay(1);
    62. W1=1;
    63. DUAN=tab[sec/10]; //送入段码,分钟数高位
    64. W2=0;
    65. delay(1);
    66. W2=1;
    67. DUAN=tab[sec%10]; //送入段码,分钟数高位
    68. W3=0;
    69. delay(1);
    70. W3=1;
    71. }
    72. else if(flag_set==1) //设置模式下闪烁相应位
    73. {
    74. if(ss==1) //闪烁标志 ss=1 正常显示
    75. {
    76. DUAN=~tab[min/10];
    77. W0=0;
    78. delay(1);
    79. W0=1;
    80. DUAN=~tab_dian[min%10];
    81. W1=0;
    82. delay(1);
    83. W1=1;
    84. }
    85. else //闪烁标志 ss=0 熄灭相应位 达到闪烁效果 ss在定时器里500ms取反一次
    86. {
    87. DUAN=~tab[10]; //
    88. W0=0;
    89. delay(1);
    90. W0=1;
    91. DUAN=~tab_dian[10];
    92. W1=0;
    93. delay(1);
    94. W1=1;
    95. }
    96. DUAN=~tab[sec/10];
    97. W2=0;
    98. delay(1);
    99. W2=1;
    100. DUAN=~tab[sec%10];
    101. W3=0;
    102. delay(1);
    103. W3=1;
    104. }
    105. else
    106. {
    107. DUAN=~tab[min/10];
    108. W0=0;
    109. delay(1);
    110. W0=1;
    111. DUAN=~tab_dian[min%10];
    112. W1=0;
    113. delay(1);
    114. W1=1;
    115. if(ss==1)
    116. {
    117. DUAN=~tab[sec/10];
    118. W2=0;
    119. delay(1);
    120. W2=1;
    121. DUAN=~tab[sec%10];
    122. W3=0;
    123. delay(1);
    124. W3=1;
    125. }
    126. else
    127. {
    128. DUAN=~tab[10];
    129. W2=0;
    130. delay(1);
    131. W2=1;
    132. DUAN=~tab[10];
    133. W3=0;
    134. delay(1);
    135. W3=1;
    136. }
    137. }
    138. }
    139. /**********************************************************************
    140. * 名称 : KEY();
    141. * 功能 : 按键控制
    142. * 输入 : 无
    143. * 输出 : 无
    144. ***********************************************************************/
    145. void KEY()
    146. {
    147. uint lum_mean,lum_all;
    148. uchar b,c;
    149. if(change==0) //自动切换按键按下
    150. {
    151. delay(10); //去抖
    152. if(change==0) //再次判断按键按下
    153. {
    154. buzz=0; //蜂鸣器鸣响
    155. flag_auto=!flag_auto; //自动模式标志位取反
    156. if(flag_auto==1) //当切换到手动模式时 首先将LED发光比例PWM设置在50%
    157. scale=20;
    158. }
    159. while(!change) display();buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
    160. }
    161. if(jiejin==0&&flag_jiejin==1) //接近传感器检测到障碍时 开启报警
    162. {
    163. buzz=0;
    164. flag_jiejin=0;
    165. }
    166. if(jiejin!=flag_jiejin) //接近传感器检测不到障碍时 关闭报警
    167. {
    168. buzz=1;
    169. flag_jiejin=1;
    170. }
    171. if(set==0) //设置键按下时
    172. {
    173. delay(10);
    174. if(set==0)
    175. {
    176. buzz=0;
    177. flag_set++; //设置变量++
    178. if(flag_set==3) //加到3时回复回正常模式
    179. flag_set=0;
    180. flag_bs=0; //按下设置 关闭报警
    181. }
    182. while(!set) display(); buzz=1;//等待按键释放 松开按键后关闭蜂鸣器、刷新显示
    183. }
    184. if(flag_set==1) //加键按键只有在设置状态(flag_set!=0)时按下才有效 调分
    185. {
    186. if(add==0) //加按键按下时
    187. {
    188. delay(10); //消抖
    189. if(add==0)
    190. {
    191. buzz=0; //蜂鸣器响
    192. min++; //++
    193. if(min>=60)
    194. min=0;
    195. }
    196. while(!add) display(); buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
    197. }
    198. if(sub==0) //减按键按下时
    199. {
    200. delay(10); //消抖
    201. if(sub==0)
    202. {
    203. buzz=0; //蜂鸣器响
    204. min--; //分--
    205. if(min>0)
    206. min=59;
    207. }
    208. while(!sub) display(); buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
    209. }
    210. }
    211. if(flag_set==2) //调秒
    212. {
    213. if(add==0) //加键按下
    214. {
    215. delay(10); //消抖
    216. if(add==0)
    217. {
    218. buzz=0; //蜂鸣器响
    219. sec++; //++
    220. if(sec>=60)
    221. sec=0;
    222. }
    223. while(!add) display(); buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
    224. }
    225. if(sub==0) //减键按下
    226. {
    227. delay(10);
    228. if(sub==0) //消抖
    229. {
    230. buzz=0; //蜂鸣器响
    231. sec--; //秒--
    232. if(sec<0)
    233. sec=59;
    234. }
    235. while(!sub) display(); buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
    236. }
    237. while(!sub);
    238. }
    239. if(flag_auto==0) //自动模式
    240. {
    241. if(flag_rsd==1) //且有人在范围内时 环境发光强度控制灯光变化
    242. {
    243. for(b=0;b<49;b++) //将空数组tt[]内数值整体左移一位
    244. {
    245. tt[b]=tt[b+1]; //将后一数值放到前一位置
    246. }
    247. tt[49]=ADC0809(); //将读出的ad0809数值放入tt[49]
    248. for(c=0;c<50;c++) //将tt[]内数值相加
    249. {
    250. lum_all=lum_all+tt[c];
    251. }
    252. lum_mean=lum_all/50; //将总数/50取出平均值
    253. // lum_all=0; //将总数清零
    254. if(lum_mean<=30) scale=1; //判断取出平均值大小 小于30 发光强度0%
    255. else if(lum_mean>=150) scale=41; //大于150 发光强度100%
    256. else scale=((lum_mean-30)/3)+1; //其他值时将其计算得到发光强度 (计算目的是为了得到一个1-41之间的数值 控制灯光变化)
    257. }
    258. else
    259. scale=1; //没有人在范围内时 将灯光亮度调至0%
    260. }
    261. else //手动模式下
    262. {
    263. if(flag_set==0) //正常模式下
    264. {
    265. if(add==0) //加键按下
    266. {
    267. delay(10);
    268. if(add==0)
    269. {
    270. // buzz=0; //蜂鸣器响
    271. scale++; //灯光比例++
    272. if(scale>=41)
    273. scale=41;
    274. display();
    275. }
    276. // while(!add) display(); buzz=1;
    277. }
    278. if(sub==0) //减键按下时
    279. {
    280. delay(10);
    281. if(sub==0)
    282. {
    283. // buzz=0; //蜂鸣器响
    284. scale--; //灯光比例--
    285. if(scale>1)
    286. scale=1;
    287. display();
    288. }
    289. // while(!sub) display(); buzz=1;
    290. }
    291. }
    292. }
    293. }
    294. /**********************************************************************
    295. * 名称 : init();
    296. * 功能 : 初始化定时器
    297. * 输入 : 无
    298. * 输出 : 无
    299. ***********************************************************************/
    300. void init()
    301. {
    302. TMOD=0x11; //工作方式1
    303. TH1=0x3c;
    304. TL1=0xb0; //T1赋初值50ms
    305. TH0=0xff;
    306. TL0=0xe7; //T0赋初值25us
    307. ET0=1;
    308. ET1=1; //打开中断允许开关
    309. EA=1; //中断总开关
    310. TR0=1; //开定时器0 开关
    311. TR1=0; //关定时器0 开关
    312. }
    313. /**********************************************************************
    314. * 名称 : main();
    315. * 功能 : 主函数
    316. * 输入 : 无
    317. * 输出 : 无
    318. ***********************************************************************/
    319. void main()
    320. {
    321. init(); //调用初始化函数
    322. flag_auto=1; //初始化手动模式
    323. rsd=0; //热释电引脚置低(有信号时时高电平)
    324. delay(500); //延时500ms后开机
    325. while(1) //大循环
    326. {
    327. KEY(); //调用按键函数
    328. display(); //调用显示函数
    329. }
    330. }
    331. /**********************************************************************
    332. * 名称 : delay();
    333. * 功能 : 延时函数:大约1ms
    334. * 输入 : 无
    335. * 输出 : 无
    336. ***********************************************************************/
    337. void delay(uchar i)
    338. {
    339. uchar j,k;
    340. for(j=i;j>0;j--)
    341. for(k=125;k>0;k--);
    342. }
    343. /**********************************************************************
    344. * 名称 : void time0() interrupt 1
    345. * 功能 : 定时器T0 中断服务函数:PWM脉冲发生函数
    346. * 输入 : 无
    347. * 输出 : 无
    348. ***********************************************************************/
    349. void time0() interrupt 1
    350. {
    351. uchar n;
    352. TH0=0xff;
    353. TL0=0xe7; //重新赋初值
    354. n++; //25us n++
    355. if(n>scale) //n<设置比例时,打开灯
    356. {
    357. LED=1;
    358. }
    359. else if(n<=scale)//n大于等于设置比例时 关闭灯
    360. {
    361. LED=0;
    362. }
    363. if(n==40) //n==4025us*40=1ms 1kHZ
    364. {
    365. n=0; //n=0
    366. }
    367. else ;
    368. }
    369. /**********************************************************************
    370. * 名称 : void time1() interrupt 3
    371. * 功能 : 定时器T1 中断服务函数:计时和闪烁控制 红外热释
    372. * 输入 : 无
    373. * 输出 : 无
    374. ***********************************************************************/
    375. void time1() interrupt 3
    376. {
    377. uchar m;
    378. TH1=0x3c;
    379. TL1=0xb0; //重新赋初值
    380. m++; //50ms m++
    381. if((m==10||m==20)&&flag_set!=0) //每过500ms 并且 在设置状态时
    382. {
    383. ss=!ss; //闪烁变量取反
    384. }
    385. if(m==20) //到达1s时
    386. {
    387. m=0; //m=0
    388. if(rsd==0) //热释电无信号时
    389. rsd_sec++; //热释电计时秒++
    390. if(rsd_sec<=30&&rsd==1) //热释电计时秒小于等于30 并且 热释电有信号时
    391. {
    392. rsd_sec=0; //将热释电秒清零
    393. flag_rsd=1; //标志位置1 控制AD0809采集数值 调节灯光亮度
    394. }
    395. else if(rsd_sec>30&&rsd==0) //热释电计时秒大于30 并且 热释电无信号时
    396. {
    397. flag_rsd=0; //标志位置0 停止ad0809转换 关闭灯光
    398. rsd_sec=0; //热释电计时秒清零
    399. }
    400. if(flag_set==0&&flag_bs==0&&((min+sec)!=0)) //正常模式下&&未报警&&定时时间不为零时
    401. {
    402. sec--;
    403. if(sec<0) //定时秒-- 小于0
    404. {
    405. sec=59; //复位到59
    406. min--; //分--
    407. }
    408. if(min<=0&&sec==0) //分和秒都减到零时
    409. {
    410. min=0;
    411. flag_bs=1;
    412. buzz=0; //蜂鸣器报警提示时间到
    413. }
    414. }
    415. // else buzz=1;
    416. }
    417. }

    硬件设计

    使用元器件:

    单片机:STC89C52;

    (注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

    LED;蜂鸣器;

    三极管;电阻;

    6*6轻触开关;

    7*7自锁开关;

    3.6寸数码管;

    人体感应模块;

    红外接近传感器;

    导线:若干;

    结构图:

    设计资料

    01 原理图

    本系统原理图采用Altium Designer19设计,具体如图!

    02 程序

    本设计使用软件keil5版本编程设计,资料里有安装教程,无需担心!具体如图!

    03 设计报告

    三千字设计报告,具体如下!

    04 设计资料

            资料获取请关注同名公众号,全部资料包括程序(含注释)、PCB电路图、AD原理图、设计报告、任务书、元件清单、结构图等。具体内容如下,全网最全! !

    点赞分享一起学习成长。

  • 相关阅读:
    [MySQL]-删库后恢复
    vue打开一个新窗口
    16.希尔排序
    GIS开发:gdal在nodejs中使用
    基于springboot的自助旅游服务平台
    【第十四篇】- Maven 自动化构建
    如何看待三测?天王级项目Aleo三测预期收益的深度解读
    从0到1带你搭建一个vue3.0项目(vue-cli脚手架版)
    vue+leaflet集成echarts实现动态轨迹图
    什么是MyBaties的输入映射与输出映射
  • 原文地址:https://blog.csdn.net/2401_82402501/article/details/138119572