丄帝De咗臂 发表于 2015-6-12 20:29:43

定时器(四位数码管)

本帖最后由 丄帝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: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:}
页: [1]
查看完整版本: 定时器(四位数码管)