定时器(四位数码管)
本帖最后由 丄帝De咗臂 于 2015-6-12 21:34 编辑【简介】定时器可以让我们更有时间观念,可以帮助我们更合力地管理时间。这里我使用四位数码管实现定时功能。该定时提醒器在工作时,从规定时间倒计时至0停止。主要练习四位数码管的使用,以及Arduino的计时功能。四位数码管只显示小时和分钟:(一)从左至右,第一个和第二个数码管显示小时,第三个和第四个数码管显示分钟(二)为提倡节约用电,小时和分钟不同时显示,而是闪烁显示,闪烁间隔为1秒,也借此显示出秒的功能(三)可通过上下两个干簧管调整时间,上面的为加一小时,下面的为减一分钟。最后完成图如下
【器材】Arduino Nano,共阳四位数码管,干簧管×2,面包板,面包线
【原理】电路原理图如下
【接线】接线示意图如下
【程序】代码程序如下
/*24小时倒计时提醒器,能显示“小时”和“分钟”,“小时”和“分钟”每秒各轮流亮灭一次,显示出“秒”的功能,节省电能。
同时10小时、10分钟在0状态时,自动熄灭,以节省电能,同时有利于观察时间。程序带有时间范围限定功能,防止时钟计时器向上、下溢出:定时器内部时钟控制在24小时至48小时范围内,当显示0小时0分钟时,定时器提示灯(D13)点亮,同时接通继电器触发控制电路工作*/
//设置8段笔画,采用超高亮度4位共阳极数码管
int a = 15; //设置A1口连接数码管a段
int b = 19; //设置A5口连接数码管b段
int c = 7; //设置D7口连接数码管c段
int d = 5; //设置D5口连接数码管d段
int e = 4; //设置D4口连接数码管e段
int f = 16; //设置A2口连接数码管f段
int g = 8; //设置D8口连接数码管g段
int dp = 6; //设置D6口连接数码管dp段
int d1=14; //设置A0口连接第一个数码管共阳极,该数码管显示小时十位
int d2=17; //设置A3口连接第二个数码管共阳极,该数码管显示小时个位
int d3=18; //设置A4口连接第三个数码管共阳极,该数码管显示分钟十位
int d4=9; //设置D9口连接第四个数码管共阳极,该数码管显示分钟个位
//定义变量一天为69120000,一秒为800,和现实时间比对后所得数据。
long oneDay =69120000;
long n; //定义时间的自变量
long aCount=0;//辅助计时器
//改用此数值对时钟进行调整,最小单位分钟用48000~60000,可以变成毫秒、秒
unsigned int oneMinute = 48000;
int dela = 19; //此处数值对时钟的时进行微调,下同
int delb = 19;
int delc = 20;
int deld = 20;
/*采用变量:oneMinute = 48000;要比直接用48000运行速度慢;注释符号//越多,运行速度越慢。程序中的时钟调整必须在不改变程序其他代码和段落的情况下进行。目前最好的结果是int dela = 19;int delb = 19;int delc = 20;int deld = 20;*/
//以下用数组赋值,程序很简洁,小数点不用
byte segs = { a, b, c, d, e, f, g };//除了小数点的7笔划段
byte seven_seg_digits =
{
{ 1,1,1,1,1,1,0 },//设置数码管显示0的数组
{ 0,1,1,0,0,0,0 },//设置数码管显示1的数组
{ 1,1,0,1,1,0,1 },//设置数码管显示2的数组
{ 1,1,1,1,0,0,1 },//设置数码管显示3的数组
{ 0,1,1,0,0,1,1 },//设置数码管显示4的数组
{ 1,0,1,1,0,1,1 },//设置数码管显示5的数组
{ 1,0,1,1,1,1,1 },//设置数码管显示6的数组
{ 1,1,1,0,0,0,0 },//设置数码管显示7的数组
{ 1,1,1,1,1,1,1 },//设置数码管显示8的数组
{ 1,1,1,1,0,1,1 } //设置数码管显示9的数组
};
//********************************中断处理函数********************************//
void addhour() //上面的干簧管触发,进行加1小时
{
digitalWrite(13,HIGH);//D13口置高电位
digitalWrite(3, HIGH);//D3口置高电位
aCount=0; //辅助计时器归0
digitalWrite(10, LOW);//因为重新设置时间,则报警停止
digitalWrite(12, LOW);//同上
n=n+2880000; //1分钟为48000,乘以60即1小时为2880000
//加1小时,即 +2880000
if (n>2*oneDay)n=n-oneDay;
}
void cutmin() //下面的干簧管触发,进行减1分钟
{
digitalWrite(1, HIGH);//D1口置高电位
digitalWrite(2, HIGH);//D2口置高电位
aCount=0; //辅助计时器归0
digitalWrite(10, LOW);//因为重新设置时间,则报警停止
digitalWrite(12, LOW);//同上
n=n-48000;//1分钟为48000,减少1分钟,即 -48000
//当时间变量n减少到00:01时,再往下减1分钟,则n<0,这时定时器内部时钟就应重新从24小时开始,往下减。
if (n<oneDay) n=n+oneDay;
digitalWrite(10, LOW);//重新设置时间,则报警停止
digitalWrite(12, LOW);//同上
}
//***********************************子函数**************************************//
void dispDec(int x) //开启小数点
{
digitalWrite(dp, LOW);//小数点点亮
}
void clearLEDs()//清屏函数
{
digitalWrite(a, HIGH); //数码管所有管脚熄灭
digitalWrite(b, HIGH);
digitalWrite(c, HIGH);
digitalWrite(d, HIGH);
digitalWrite(e, HIGH);
digitalWrite(f, HIGH);
digitalWrite(g, HIGH);
digitalWrite(dp, HIGH);
}
void lightSegments(int x)//点亮对应数字的数码管
{
for (int i = 0; i < 7; i++)
{
//点亮数字数组取反,点亮共阳极数码管
digitalWrite(segs, !seven_seg_digits);
}
}
void pickDigit(int x) //定义pickDigit(x),其作用是开启哪一位数码管
{
digitalWrite(d1, LOW);//初始设置第一位位数码管熄灭
digitalWrite(d2, LOW);//初始设置第二位位数码管熄灭
digitalWrite(d3, LOW);//初始设置第三位位数码管熄灭
digitalWrite(d4, LOW);//初始设置第四位位数码管熄灭
switch(x)
{
case 1:
//第一个数码管为小时十位,每秒闪烁一次,小于10小时熄灭
digitalWrite(d1, n%800<400&&(n/48000/60)%24>9);
break;
case 2:
//第二个数码管为小时个位,每秒闪烁一次
digitalWrite(d2, n%800<400);
break;
case 3:
//第三个数码管为分钟十位,每秒闪烁一次,小于10分钟熄灭;
//1分钟时,还有10秒为0分时,从显示1变成现实01
digitalWrite(d3, n%800>400&&(n/48000/10%6)>0||(n%oneDay<56000));
break;
default:
//第四个数码管为分钟个位,每秒闪烁一次
digitalWrite(d4, n%800>400);
break;
}
}
//*****************************初始化函数*****************************//
void setup()
{
for (int i=4; i<20; i++)
{
pinMode(i, OUTPUT); //设置D4到D19引脚为输出模式
digitalWrite(i, HIGH);//四位共阳数码管都熄灭
}
pinMode(2, INPUT); //内置上拉电阻,中断函数0
pinMode(3, INPUT); //内置上拉电阻,中断函数1
digitalWrite(2, HIGH);//内置上拉电阻
digitalWrite(3, HIGH);//内置上拉电阻
//设置引脚D13为输出模式(上面的for循环已设置)
digitalWrite(13,LOW); //设置成加1小时的中断函数的地端
pinMode(1, OUTPUT); //设置引脚D1为输出模式
digitalWrite(1,LOW); //设置成减1分钟的中断函数的地端
digitalWrite(10, LOW);//5V直流继电器线圈初始:不接通
digitalWrite(12, LOW);//5V直流继电器线圈初始:不接通
n=oneDay+25920000; //开机时间初始化设置为:8 小时59分
//下面是两个干簧管按钮,触发相应的中断函数,调整时间
attachInterrupt(1,addhour, LOW); //加1小时的中断函数;接D13
attachInterrupt(0, cutmin, LOW); //减1分钟的中断函数,接 D1
}
//*******************************主函数*******************************//
void loop()
{
aCount++;//计数累加
if (aCount>300) //要等待0.375秒恢复中断开关的接地端功能
{
digitalWrite(13, LOW);//800=1秒,300=0.375秒
digitalWrite(1, LOW); //800=1秒,300=0.375秒
}
/*以下是钟表的最关键代码——24小时进制的实现
为了实现24小时进制,通过尝试得到上面的代码,其原理是从原来的60分钟进制1小时得来的;在小时的基础上,除以10*/
clearLEDs(); //数码管清屏
pickDigit(1); //小时十位数码管,采用1天24小时
//通过n除以48000再除以60再取除以24的余数再除以10来获取小时十位的数值并点亮数码管显示
lightSegments((n/48000/60)%24/10);
delayMicroseconds(dela);//微调时钟快慢
clearLEDs(); //数码管清屏
pickDigit(2); //小时个位数码管
//通过n除以48000再除以60再取除以24的余数再取除以10的余数来获取小时个位的数值并点亮数码管显示
lightSegments((n/48000/60)%24%10);
dispDec(2); //点亮小数点
delayMicroseconds(delb);//微调时钟快慢
clearLEDs(); //数码管清屏
pickDigit(3); //分钟十位数码管
//通过n除以48000再除以10再取除以6的余数来获取分钟十位的数值并点亮数码管显示
lightSegments((n/48000/10)%6);
delayMicroseconds(delc);//微调时钟快慢
clearLEDs(); //数码管清屏
pickDigit(4); //分钟个位数码管
//通过n除以48000再取除以10的余数来获取分钟个位的数值并点亮数码管显示
lightSegments((n/48000)%10);
delayMicroseconds(deld);//微调时钟快慢
n--;//倒计时的时钟源,每次循环减一
if (n%oneDay==oneMinute)//这是倒计时终点的提醒功能,从0:1——0:0就报警
{
digitalWrite(10, HIGH);//启动5V直流继电器
digitalWrite(12, HIGH);//启动5V直流继电器
}
}
【效果】最终效果展示两个图
(一)显示小时
(二)显示分钟
【拓展】利用继电器加上蜂鸣器,可实现定时报警功能,程序留给各位喽:-)
本帖最后由 丄帝De咗臂 于 2015-6-12 21:26 编辑
这个里面用到了中断,是因为有两个干簧管按钮,触发相应的中断函数,调整时间。因为arduino运行速度快,不使用中断,按一下可能会触发很多次。 哈哈 你也应该当这个版主 `` 大连林海 发表于 2015-6-13 14:23
哈哈 你也应该当这个版主 ``
{:2_35:}
页:
[1]