13949浏览
查看: 13949|回复: 3

[项目] 定时器(四位数码管)

[复制链接]
本帖最后由 丄帝De咗臂 于 2015-6-12 21:34 编辑

【简介】定时器可以让我们更有时间观念,可以帮助我们更合力地管理时间。这里我使用四位数码管实现定时功能。该定时提醒器在工作时,从规定时间倒计时至0停止。主要练习四位数码管的使用,以及Arduino的计时功能。四位数码管只显示小时和分钟:(一)从左至右,第一个和第二个数码管显示小时,第三个和第四个数码管显示分钟(二)为提倡节约用电,小时和分钟不同时显示,而是闪烁显示,闪烁间隔为1秒,也借此显示出秒的功能(三)可通过上下两个干簧管调整时间,上面的为加一小时,下面的为减一分钟。最后完成图如下
定时器(四位数码管)图3

【器材】Arduino Nano,共阳四位数码管,干簧管×2,面包板,面包线
【原理】电路原理图如下

定时器(四位数码管)图4


【接线】接线示意图如下

定时器(四位数码管)图5

【程序】代码程序如下

  1. /*24小时倒计时提醒器,能显示“小时”和“分钟”,“小时”和“分钟”每秒各轮流亮灭一次,显示出“秒”的功能,节省电能。
  2. 同时10小时、10分钟在0状态时,自动熄灭,以节省电能,同时有利于观察时间。程序带有时间范围限定功能,防止时钟计时器向上、下溢出:定时器内部时钟控制在24小时至48小时范围内,当显示0小时0分钟时,定时器提示灯(D13)点亮,同时接通继电器触发控制电路工作*/
  3. //设置8段笔画,采用超高亮度4位共阳极数码管
  4. int a = 15;   //设置A1口连接数码管a段
  5. int b = 19;   //设置A5口连接数码管b段
  6. int c = 7;    //设置D7口连接数码管c段
  7. int d = 5;    //设置D5口连接数码管d段
  8. int e = 4;    //设置D4口连接数码管e段
  9. int f = 16;   //设置A2口连接数码管f段
  10. int g = 8;    //设置D8口连接数码管g段
  11. int dp = 6;   //设置D6口连接数码管dp段
  12. int d1=14;    //设置A0口连接第一个数码管共阳极,该数码管显示小时十位
  13. int d2=17;    //设置A3口连接第二个数码管共阳极,该数码管显示小时个位
  14. int d3=18;    //设置A4口连接第三个数码管共阳极,该数码管显示分钟十位
  15. int d4=9;     //设置D9口连接第四个数码管共阳极,该数码管显示分钟个位
  16. //定义变量一天为69120000,一秒为800,和现实时间比对后所得数据。
  17. long oneDay =69120000;
  18. long n;       //定义时间的自变量
  19. long aCount=0;//辅助计时器
  20. //改用此数值对时钟进行调整,最小单位分钟用48000~60000,可以变成毫秒、秒
  21. unsigned int oneMinute = 48000;
  22. int dela = 19; //此处数值对时钟的时进行微调,下同
  23. int delb = 19;
  24. int delc = 20;
  25. int deld = 20;
  26. /*采用变量:oneMinute = 48000;要比直接用48000运行速度慢;注释符号//越多,运行速度越慢。程序中的时钟调整必须在不改变程序其他代码和段落的情况下进行。目前最好的结果是int dela = 19;int delb = 19;int delc = 20;int deld = 20;*/
  27. //以下用数组赋值,程序很简洁,小数点不用
  28. byte segs[7] = { a, b, c, d, e, f, g };//除了小数点的7笔划段
  29. byte seven_seg_digits[10][7] =
  30. {
  31.   { 1,1,1,1,1,1,0 },//设置数码管显示0的数组
  32.   { 0,1,1,0,0,0,0 },//设置数码管显示1的数组
  33.   { 1,1,0,1,1,0,1 },//设置数码管显示2的数组
  34.   { 1,1,1,1,0,0,1 },//设置数码管显示3的数组
  35.   { 0,1,1,0,0,1,1 },//设置数码管显示4的数组
  36.   { 1,0,1,1,0,1,1 },//设置数码管显示5的数组
  37.   { 1,0,1,1,1,1,1 },//设置数码管显示6的数组
  38.   { 1,1,1,0,0,0,0 },//设置数码管显示7的数组
  39.   { 1,1,1,1,1,1,1 },//设置数码管显示8的数组
  40.   { 1,1,1,1,0,1,1 } //设置数码管显示9的数组  
  41. };
  42. //********************************中断处理函数********************************//
  43. void addhour()    //上面的干簧管触发,进行加1小时
  44. {   
  45.    digitalWrite(13,HIGH);//D13口置高电位
  46.    digitalWrite(3, HIGH);//D3口置高电位
  47.    aCount=0;             //辅助计时器归0
  48.    digitalWrite(10, LOW);//因为重新设置时间,则报警停止
  49.    digitalWrite(12, LOW);//同上
  50.    n=n+2880000;          //1分钟为48000,乘以60即1小时为2880000
  51.                          //加1小时,即 +2880000
  52.    if (n>2*oneDay)  n=n-oneDay;
  53. }
  54. void cutmin()     //下面的干簧管触发,进行减1分钟
  55. {
  56.    digitalWrite(1, HIGH);//D1口置高电位
  57.    digitalWrite(2, HIGH);//D2口置高电位
  58.    aCount=0;             //辅助计时器归0
  59.    digitalWrite(10, LOW);//因为重新设置时间,则报警停止
  60.    digitalWrite(12, LOW);//同上
  61.    n=n-48000;  //1分钟为48000,减少1分钟,即 -48000
  62.    //当时间变量n减少到00:01时,再往下减1分钟,则n<0,这时定时器内部时钟就应重新从24小时开始,往下减。
  63.    if (n<oneDay) n=n+oneDay;
  64.    digitalWrite(10, LOW);//重新设置时间,则报警停止
  65.    digitalWrite(12, LOW);//同上
  66. }
  67. //***********************************子函数**************************************//
  68. void dispDec(int x) //开启小数点
  69. {
  70.   digitalWrite(dp, LOW);  //小数点点亮
  71. }
  72. void clearLEDs()//清屏函数
  73. {
  74.   digitalWrite(a, HIGH); //数码管所有管脚熄灭
  75.   digitalWrite(b, HIGH);
  76.   digitalWrite(c, HIGH);
  77.   digitalWrite(d, HIGH);
  78.   digitalWrite(e, HIGH);
  79.   digitalWrite(f, HIGH);
  80.   digitalWrite(g, HIGH);
  81.   digitalWrite(dp, HIGH);
  82. }
  83. void lightSegments(int x)//点亮对应数字的数码管
  84. {
  85.   for (int i = 0; i < 7; i++)
  86.   {
  87. //点亮数字数组取反,点亮共阳极数码管
  88.     digitalWrite(segs[i], !seven_seg_digits[x][i]);  
  89.   }
  90. }
  91. void pickDigit(int x)   //定义pickDigit(x),其作用是开启哪一位数码管
  92. {
  93.   digitalWrite(d1, LOW);//初始设置第一位位数码管熄灭
  94.   digitalWrite(d2, LOW);//初始设置第二位位数码管熄灭
  95.   digitalWrite(d3, LOW);//初始设置第三位位数码管熄灭
  96.   digitalWrite(d4, LOW);//初始设置第四位位数码管熄灭
  97.   switch(x)
  98.   {
  99.   case 1:
  100. //第一个数码管为小时十位,每秒闪烁一次,小于10小时熄灭
  101.     digitalWrite(d1, n%800<400&&(n/48000/60)%24>9);
  102.     break;
  103.   case 2:
  104. //第二个数码管为小时个位,每秒闪烁一次
  105.     digitalWrite(d2, n%800<400);
  106.     break;
  107.   case 3:
  108. //第三个数码管为分钟十位,每秒闪烁一次,小于10分钟熄灭;
  109. //1分钟时,还有10秒为0分时,从显示1变成现实01
  110.     digitalWrite(d3, n%800>400&&(n/48000/10%6)>0||(n%oneDay<56000));
  111.     break;
  112.   default:
  113. //第四个数码管为分钟个位,每秒闪烁一次
  114.     digitalWrite(d4, n%800>400);
  115.     break;
  116.   }
  117. }
  118. //*****************************初始化函数*****************************//
  119. void setup()
  120. {
  121.   for (int i=4; i<20; i++)
  122.   {
  123.     pinMode(i, OUTPUT);   //设置D4到D19引脚为输出模式
  124.     digitalWrite(i, HIGH);//四位共阳数码管都熄灭
  125.   }
  126.   pinMode(2, INPUT);      //内置上拉电阻,中断函数0
  127.   pinMode(3, INPUT);      //内置上拉电阻,中断函数1
  128.   digitalWrite(2, HIGH);  //内置上拉电阻
  129.   digitalWrite(3, HIGH);  //内置上拉电阻
  130.                           //设置引脚D13为输出模式(上面的for循环已设置)
  131.   digitalWrite(13,LOW);   //设置成加1小时的中断函数的地端
  132.   pinMode(1, OUTPUT);     //设置引脚D1为输出模式
  133.   digitalWrite(1,LOW);    //设置成减1分钟的中断函数的地端
  134.   digitalWrite(10, LOW);  //5V直流继电器线圈初始:不接通
  135.   digitalWrite(12, LOW);  //5V直流继电器线圈初始:不接通
  136.   n=oneDay+25920000;      //开机时间初始化设置为:8 小时59分
  137. //下面是两个干簧管按钮,触发相应的中断函数,调整时间
  138.   attachInterrupt(1,addhour, LOW); //加1小时的中断函数;接D13
  139.   attachInterrupt(0, cutmin, LOW); //减1分钟的中断函数,接 D1
  140. }
  141. //*******************************主函数*******************************//
  142. void loop()
  143. {
  144.   aCount++;//计数累加
  145.   if (aCount>300)       //要等待0.375秒恢复中断开关的接地端功能
  146.   {
  147.   digitalWrite(13, LOW);//800=1秒,300=0.375秒
  148.   digitalWrite(1, LOW); //800=1秒,300=0.375秒
  149.   }
  150. /*以下是钟表的最关键代码——24小时进制的实现
  151. 为了实现24小时进制,通过尝试得到上面的代码,其原理是从原来的60分钟进制1小时得来的;在小时的基础上,除以10*/
  152.    clearLEDs();           //数码管清屏
  153.     pickDigit(1);          //小时十位数码管,采用1天24小时
  154. //通过n除以48000再除以60再取除以24的余数再除以10来获取小时十位的数值并点亮数码管显示
  155.     lightSegments((n/48000/60)%24/10);
  156.     delayMicroseconds(dela);//微调时钟快慢
  157.     clearLEDs();            //数码管清屏
  158.     pickDigit(2);           //小时个位数码管
  159. //通过n除以48000再除以60再取除以24的余数再取除以10的余数来获取小时个位的数值并点亮数码管显示
  160.     lightSegments((n/48000/60)%24%10);
  161.     dispDec(2);             //点亮小数点
  162.     delayMicroseconds(delb);//微调时钟快慢
  163.     clearLEDs();            //数码管清屏
  164.     pickDigit(3);           //分钟十位数码管
  165. //通过n除以48000再除以10再取除以6的余数来获取分钟十位的数值并点亮数码管显示
  166.     lightSegments((n/48000/10)%6);
  167.     delayMicroseconds(delc);//微调时钟快慢
  168.     clearLEDs();            //数码管清屏
  169.     pickDigit(4);           //分钟个位数码管
  170. //通过n除以48000再取除以10的余数来获取分钟个位的数值并点亮数码管显示
  171.     lightSegments((n/48000)%10);
  172.     delayMicroseconds(deld);//微调时钟快慢
  173.     n--;//倒计时的时钟源,每次循环减一
  174.     if (n%oneDay==oneMinute)  //这是倒计时终点的提醒功能,从0:1——0:0就报警
  175.     {                        
  176.        digitalWrite(10, HIGH);//启动5V直流继电器
  177.        digitalWrite(12, HIGH);//启动5V直流继电器
  178.     }
  179. }
复制代码

【效果】最终效果展示两个图

(一)显示小时

定时器(四位数码管)图1

(二)显示分钟

定时器(四位数码管)图2

【拓展】利用继电器加上蜂鸣器,可实现定时报警功能,程序留给各位喽:-)



丄帝De咗臂  高级技匠
 楼主|

发表于 2015-6-12 21:10:14

本帖最后由 丄帝De咗臂 于 2015-6-12 21:26 编辑

这个里面用到了中断,是因为有两个干簧管按钮,触发相应的中断函数,调整时间。因为arduino运行速度快,不使用中断,按一下可能会触发很多次。
回复

使用道具 举报

大连林海  初级技神

发表于 2015-6-13 14:23:28

哈哈 你也应该当这个版主 ``
回复

使用道具 举报

丄帝De咗臂  高级技匠
 楼主|

发表于 2015-6-13 16:51:02

大连林海 发表于 2015-6-13 14:23
哈哈 你也应该当这个版主 ``

{:2_35:}
回复

使用道具 举报

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

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail