找回密码
 立即注册

QQ登录

只需一步,快速开始

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

Arduino电子闹钟源码

[复制链接]
ID:302246 发表于 2018-6-6 18:31 | 显示全部楼层 |阅读模式
Arduino的电子闹钟,可以设置时间,蜂鸣器报警,播放葫芦娃,使用超声波模块,当手与超声波一定距离的时候关掉闹钟。
代码复制到IDE下载即可。

Arduino单片机源程序如下:
  1. #include <EEPROM.h>
  2. #include <SR04.h>

  3. //葫芦娃对应的乐谱
  4. #define NOTE_D0 -1
  5. #define NOTE_D1 262
  6. #define NOTE_D2 293
  7. #define NOTE_D3 329
  8. #define NOTE_D4 349
  9. #define NOTE_D5 392
  10. #define NOTE_D6 440
  11. #define NOTE_D7 494
  12. #define NOTE_DL1 147
  13. #define NOTE_DL2 165
  14. #define NOTE_DL3 175
  15. #define NOTE_DL4 196
  16. #define NOTE_DL5 221
  17. #define NOTE_DL6 248
  18. #define NOTE_DL7 278
  19. #define NOTE_DH1 523
  20. #define NOTE_DH2 586
  21. #define NOTE_DH3 658
  22. #define NOTE_DH4 697
  23. #define NOTE_DH5 783
  24. #define NOTE_DH6 879
  25. #define NOTE_DH7 987
  26. //以上部分是定义是把每个音符和频率值对应起来,其实不用打这么多,但是都打上了,后面可以随意编写D调的各种歌,我这里用NOTE_D+数字表示音符,NOTE_DH+数字表示上面有点的那种音符,NOTE_DL+数字表示下面有点的那种音符。这样后面写起来比较好识别。
  27. #define WHOLE 1
  28. #define HALF 0.5
  29. #define QUARTER 0.25
  30. #define EIGHTH 0.25
  31. #define SIXTEENTH 0.625
  32. //这部分是用英文对应了拍子,这样后面也比较好看
  33. int tune[] =
  34. {
  35.   NOTE_DH1,NOTE_D6,NOTE_D5,NOTE_D6,NOTE_D0,
  36.   NOTE_DH1,NOTE_D6,NOTE_D5,NOTE_DH1,NOTE_D6,NOTE_D0,NOTE_D6,
  37.   NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D6,NOTE_D0,NOTE_D6,
  38.   NOTE_DH1,NOTE_D6,NOTE_D5,NOTE_DH1,NOTE_D6,NOTE_D0,
  39.   NOTE_D1,NOTE_D1,NOTE_D3,
  40.   NOTE_D1,NOTE_D1,NOTE_D3,NOTE_D0,
  41.   NOTE_D6,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D6,
  42.   NOTE_D5,NOTE_D1,NOTE_D3,NOTE_D0,
  43.   NOTE_DH1,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D6,
  44.   NOTE_D5,NOTE_D1,NOTE_D2,NOTE_D0,
  45.   NOTE_D7,NOTE_D7,NOTE_D5,NOTE_D3,
  46.   NOTE_D5,
  47.   NOTE_DH1,NOTE_D0,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D5,NOTE_D6,NOTE_D6,
  48.   NOTE_D0,NOTE_D5,NOTE_D1,NOTE_D3,NOTE_D0,
  49.   NOTE_DH1,NOTE_D0,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D5,NOTE_D6,NOTE_D6,
  50.   NOTE_D0,NOTE_D5,NOTE_D1,NOTE_D2,NOTE_D0,
  51.   NOTE_D3,NOTE_D3,NOTE_D1,NOTE_DL6,
  52.   NOTE_D1,
  53.   NOTE_D3,NOTE_D5,NOTE_D6,NOTE_D6,
  54.   NOTE_D3,NOTE_D5,NOTE_D6,NOTE_D6,
  55.   NOTE_DH1,NOTE_D0,NOTE_D7,NOTE_D5,
  56.   NOTE_D6,
  57. };//这部分就是整首曲子的音符部分,用了一个序列定义为tune,整数
  58. float duration[]=
  59. {
  60.   1,1,0.5,0.5,1,
  61.   0.5,0.5,0.5,0.5,1,0.5,0.5,
  62.   0.5,1,0.5,1,0.5,0.5,
  63.   0.5,0.5,0.5,0.5,1,1,
  64.   1,1,1+1,
  65.   0.5,1,1+0.5,1,
  66.   1,1,0.5,0.5,1,
  67.   0.5,1,1+0.5,1,
  68.   0.5,0.5,0.5,0.5,1+1,
  69.   0.5,1,1+0.5,1,
  70.   1+1,0.5,0.5,1,
  71.   1+1+1+1,
  72.   0.5,0.5,0.5+0.25,0.25,0.5+0.25,0.25,0.5+0.25,0.25,
  73.   0.5,1,0.5,1,1,
  74.   0.5,0.5,0.5+0.25,0.25,0.5+0.25,0.25,0.5+0.25,0.25,
  75.   0.5,1,0.5,1,1,
  76.   1+1,0.5,0.5,1,
  77.   1+1+1+1,
  78.   0.5,1,0.5,1+1,
  79.   0.5,1,0.5,1+1,
  80.   1+1,0.5,0.5,1,
  81.   1+1+1+1
  82. };//这部分是整首曲子的接拍部分,也定义个序列duration,浮点(数组的个数和前面音符的个数是一样的,一一对应么)
  83. //LCD初始化
  84. #include <LiquidCrystal.h>
  85. LiquidCrystal lcd=LiquidCrystal(2,3,4,5,6,7,8);
  86. // 初始 化按键
  87. int ring=A3;
  88. int set=A0;  //选择端口
  89. int add=A1;     //加
  90. int minus=A2;    //减
  91. //设置参数
  92. int jy=0,jmonth=0,jd=0,jh=0,jm=0,js=0;//      进位
  93. int year=0,month=0,day=0,hour=0,minute=0,second=0;//   当前时间
  94. int YEAR=2018,MONTH=4,DAY=12,HOUR=18,MINUTE=10,SECOND=00;// 初始设定时间
  95. int moving=0,ring_moving=0;// 设置时间的移动
  96. int ring_hour=0,ring_minute=0,jr=0;//闹钟时间
  97. unsigned long seconds=0;//读取程序运行时间
  98. unsigned long b=1,secondcomp=0,exsecond=0;
  99. //蜂鸣器模块定义
  100. int length;//这里定义一个变量,后面用来表示共有多少个音符
  101. int tonePin=9;//蜂鸣器的pin
  102. int a=0;
  103. //超声波模块管脚参数
  104. int echo=13;
  105. int trig=12;
  106. SR04 target=SR04(echo,trig);
  107. long distance=0;

  108. //共同体设置,把 无符号长整 分4个字节存入 EEPROM
  109. union data
  110. {
  111.   float renewtime;
  112.   byte difference[4];
  113. };
  114. data col;
  115. void Time_Lcd(int rol,int raw,int number)// 标准格式 在lcd 显示时间
  116. {
  117.   lcd.setCursor(rol,raw);
  118.   if(number<10)// 如果小于 10,输出 为 0X
  119.   {
  120.     lcd.print(0);
  121.   }
  122.   lcd.print(number);
  123. }
  124. //显示具体的时间
  125. void time()
  126. {
  127.   if(SECOND<=0) SECOND=0;
  128.   second=(secondcomp+seconds+SECOND+exsecond)%60;
  129.   Time_Lcd(6,1,second);
  130.   jm=(seconds+SECOND)/60;
  131.   if(MINUTE<=0) MINUTE=0;
  132.   minute=(jm+MINUTE)%60;
  133.   Time_Lcd(3,1,minute);
  134.   jh=(jm+MINUTE)/60;
  135.   if(HOUR<=0) HOUR=0;
  136.   hour=(jh+HOUR)%24;
  137.   Time_Lcd(0,1,hour);
  138.   lcd.setCursor(2,1);
  139.   lcd.print(":");
  140.   lcd.setCursor(5,1);
  141.   lcd.print(":");
  142.   lcd.setCursor(8,1);
  143.   lcd.print(" ");
  144.   lcd.setCursor(4,0);
  145.   lcd.print("-");
  146.   lcd.setCursor(7,0);
  147.   lcd.print("-");
  148. }
  149. //算出当月一共多少个月
  150. int DAYS(int year,int month)
  151. {
  152.   if(year%4==0&&year%100!=0||year%400==0)
  153.   {
  154.      switch(month){
  155.      case 1:case 3:case 5:case 7:case 8:case 10:case 12: return 31;break;
  156.      case 2:return 29;break;
  157.      case 4:case 6:case 9:case 11: return 30;break;}
  158.   }
  159.   else
  160.   {
  161.      switch(month){
  162.       case 1:case 3:case 5:case 7:case 8:case 10:case 12: return 31;break;
  163.       case 2:return 28;break;
  164.       case 4:case 6:case 9:case 11: return 30;break;}
  165.   }
  166. }
  167. //设置后的天数,考虑进一个月或者天数为 0,退一个月的情况
  168. void Day()
  169. {
  170.   if(DAY<=0) DAY=0;
  171.   int day=0;
  172.   int exdays=0;
  173.   int days=DAYS(year,month);
  174.   if(month==1) exdays=DAYS(year-1,12);
  175.   else exdays=(year,month-1);
  176.   jd=(HOUR+jh)/24;
  177.   day=(jd+DAY)%(days+1);
  178.   if((jd+DAY)==0)
  179.   {
  180.     jmonth--;
  181.     DAY=exdays;
  182.   }
  183.   if((jd+DAY)==(days+1))
  184.   {
  185.     jmonth++;
  186.     DAY=DAY-days;
  187.   }
  188.   Time_Lcd(8,0,day);
  189. }
  190. //设置后的月数,考虑  0月退一年的情况
  191. void Month()
  192. {
  193.   if(MONTH<=0) MONTH=0;
  194.   month=(MONTH+jmonth)%12;
  195.   if(month==0&&(MONTH+jmonth)!=0) month=12;
  196.   jy=(jmonth+MONTH-1)/12;
  197.   if((MONTH+jmonth)==0)
  198.   {
  199.     month=12;
  200.     jy--;
  201.   }
  202.   Time_Lcd(5,0,month);
  203. }
  204. //设置 年
  205. void Year()
  206. {
  207.   if(YEAR<=0) YEAR=0;  
  208.   year=(jy+YEAR)%10000;
  209.   lcd.setCursor(0,0);
  210.   if(year<1000)
  211.   {
  212.     lcd.print("0");
  213.   }
  214.   if(year<100)
  215.   {
  216.     lcd.print("00");
  217.   }
  218.   if(year<10)
  219.   {
  220.     lcd.print("000");
  221.   }
  222.   lcd.print(year);
  223. }

  224. // 显示时间汇总
  225. //设置闹钟,移动光标到对应的时间位置
  226. void Set_Clock()   //按键选择
  227. {
  228.   if(digitalRead(set)==LOW)
  229.   {  
  230.     lcd.setCursor(9, 1);  lcd.print("SetTime");
  231.     while(1)
  232.     {      
  233.         if(digitalRead(set)==LOW)
  234.         {
  235.            delay(10);
  236.            if(digitalRead(set)==LOW)
  237.              moving++;  
  238.          }
  239.         seconds = millis()/1000;
  240.         Show_Time();
  241.         if(moving == 1)
  242.            Set_Time(0, 1, HOUR);  //设置小时
  243.         if(moving == 2)
  244.            Set_Time(3, 1, MINUTE);     //分钟
  245.         if(moving == 3)
  246.            Set_Time(6, 1, SECOND);    //秒
  247.         if(moving== 4)
  248.            Set_Time(8, 0, DAY);      //天
  249.         if(moving== 5)
  250.            Set_Time(5, 0, MONTH);      // 月
  251.         if(moving== 6)            
  252.            Set_Time(2, 0, YEAR);       // 年
  253.         if(moving >= 7)  
  254.         {
  255.            moving = 0;
  256.           lcd.setCursor(9,1);
  257.           lcd.print("       ");
  258.           break;
  259.         }
  260.     }
  261.         delay(50);
  262.   }  
  263. }
  264. //光标闪烁,显示正在设置哪一位
  265. void Cursor_Blink(int col,int raw)
  266. {
  267.   lcd.setCursor(col,raw);
  268.   lcd.cursor();
  269.     delay(100);     
  270.     lcd.noCursor();
  271.     delay(100);  
  272. }
  273. //更改初始时间
  274. void Set_Time(int col, int row, int &TIME)   //通过按键设置时间
  275. {
  276.    Cursor_Blink(col, row);
  277.    if(digitalRead(add) == LOW)
  278.    {
  279.        delay(10);
  280.        if(digitalRead(add) == LOW)
  281.            TIME ++;
  282.        Show_Time();      
  283.    }  
  284.    if(digitalRead(minus) == LOW)
  285.    {
  286.        delay(10);
  287.        if(digitalRead(minus) == LOW)
  288.            TIME --;
  289.        Show_Time();
  290.     }  
  291. }
  292. //光标闪烁,显示正在设置哪一位

  293. //更改初始时间

  294. void Show_Time()
  295. {
  296.   time();
  297.   Day();
  298.   Month();
  299.   Year();
  300. }
  301. //设置闹铃时间,原理同上
  302. void Set_Ring()
  303. {
  304.    if(digitalRead(ring)==LOW)
  305.   {  
  306.     lcd.setCursor(0,0);  lcd.print("  set RINGTime  ");
  307.     lcd.setCursor(0,1);
  308.     lcd.print("   ");
  309.     Time_Lcd(2,1,ring_hour);
  310.     lcd.print(":");
  311.     Time_Lcd(5,1,ring_minute);   
  312.     lcd.print("   ");
  313.     while(1)
  314.     {      
  315.         if(digitalRead(ring)==LOW)
  316.         {
  317.            delay(10);
  318.            if(digitalRead(ring)==LOW)
  319.              ring_moving++;  
  320.          }
  321.         if(ring_moving == 1)
  322.            Set_RingHour();      //SetHour
  323.         if(ring_moving == 2)
  324.            Set_RingMinute();    //SetMinute
  325.         if(ring_moving >= 3)  
  326.         {
  327.            ring_moving = 0;
  328.           lcd.setCursor(10,0);
  329.            lcd.print("    ");
  330.            break;
  331.         }
  332.     }
  333.     delay(100);
  334.   }  
  335. }
  336. void Set_RingHour()   //通过按键设置时间
  337. {
  338.    Cursor_Blink(2,1);
  339.    if(digitalRead(add) == LOW)
  340.    {
  341.        delay(10);
  342.        if(digitalRead(add) == LOW)
  343.            ring_hour++;
  344.        ring_hour=ring_hour%24;
  345.        Time_Lcd(2,1,ring_hour);   
  346.        Time_Lcd(5,1,ring_minute);
  347.    }  
  348.    if(digitalRead(minus) == LOW)
  349.    {
  350.        delay(10);
  351.        if(digitalRead(minus) == LOW)
  352.            ring_hour--;
  353.        Time_Lcd(2,1,ring_hour);  
  354.        Time_Lcd(5,1,ring_minute);
  355.     }  
  356. }
  357. void Set_RingMinute()   //通过按键设置时间
  358. {
  359.    Cursor_Blink(5,1);
  360.    if(digitalRead(add) == LOW)
  361.    {
  362.        delay(10);
  363.        if(digitalRead(add) == LOW)
  364.        {
  365.            ring_minute++;
  366.            ring_minute=ring_minute%60;
  367.            if(ring_minute==0)  ring_hour++;
  368.            ring_hour=ring_hour%24;
  369.        }
  370.        Time_Lcd(2,1,ring_hour);
  371.        Time_Lcd(5,1,ring_minute);   
  372.    }  
  373.    if(digitalRead(minus) == LOW)
  374.    {
  375.        delay(10);
  376.        if(digitalRead(minus) == LOW)
  377.            ring_minute--;
  378.        ring_minute=ring_minute%60;
  379.        Time_Lcd(2,1,ring_hour);
  380.        Time_Lcd(5,1,ring_minute);  
  381.     }  
  382. }
  383. void showdistance() //超声波测量距离
  384. {
  385.   distance=target.Distance();
  386. }
  387. void music()//控制蜂鸣器
  388. {
  389.   length = sizeof(tune)/sizeof(tune[0]);//这里用了一个sizeof函数,可以查出tone序列里有多少个音符
  390.   for(int x=0;x<length;x++)
  391.   {
  392.     distance=target.Distance();
  393.     if(distance<10)
  394.     {
  395.       break;
  396.     }
  397.     tone(tonePin,tune[x]);//此函数依次播放tune序列里的数组,即每个音符
  398.     delay(200*duration[x]);//每个音符持续的时间,即节拍duration,400是调整时间的越大,曲子速度越慢,越小曲子速度越快,自己掌握吧
  399.     noTone(tonePin);//停止当前音符,进入下一音符
  400.   }
  401. }
  402. void Ring()//闹铃
  403. {
  404.   if(hour==ring_hour&&minute==ring_minute&&second==0)
  405.       music();
  406. }
  407. void setup() {
  408.   // put your setup code here, to run once:
  409.   lcd.begin(16,2);
  410.   digitalWrite(add, HIGH);
  411.   digitalWrite(minus, HIGH);
  412.   digitalWrite(set, HIGH);  
  413.   digitalWrite(ring,HIGH);
  414.   pinMode(tonePin,OUTPUT);//设置蜂鸣器的pin为输出模式
  415.   for(int i=0;i<4;i++)
  416.   col.difference[i]=EEPROM.read(i);
  417.   exsecond=col.renewtime;
  418. }
  419. void loop() {
  420.   // put your main code here, to run repeatedly:
  421.   seconds=millis()/1000;
  422.   if(seconds==900*b+(b-1)) {secondcomp++;b++;}//补偿误差
  423.   Show_Time();
  424.   Set_Clock();
  425.   Set_Ring();
  426.   Ring();
  427.   col.renewtime=seconds;
  428.   for(int i=0;i<4;i++)
  429.   EEPROM.write(i, col.difference[i]);
  430. }
复制代码

所有资料51hei提供下载:
电子闹钟.docx (16.28 KB, 下载次数: 55)

评分

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

查看全部评分

回复

使用道具 举报

ID:850685 发表于 2020-11-28 14:38 来自手机 | 显示全部楼层
这个实物怎么接线呀
回复

使用道具 举报

ID:138707 发表于 2023-7-30 12:28 | 显示全部楼层
这个实物怎么接线呀,同问
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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