|
本多功能时钟的功能有:1、时钟显示(交替显示月、日和时、分、秒);
2、倒计时(计时阶段有场效应管电子开关,计时结束时有蜂鸣器提示。最长计时100小时-1秒);
3、秒表计时(计时时长99小时59分59秒,在计时阶段,每秒钟蜂鸣器会响0.1秒可关闭)。
主要元器件:(利用电信早期用的显示来电号码的外壳)
ATMEGA328P、一个四位数码管和一个三位数码管(可用两个四位数码管,本人把第二个第四位数码管用一个LED灯替代)、两个74HC595、DS1307模块。其它元件略。
电路图:
上传DS1307和MsTimer2的库文件失败,提示说不能传输零字节的文件,明明都是好几K的文件。
啃萝卜 - Make it easy!
复制代码
//VCC -- 5V
//GND -- GND
//DS -- A0
//ST_CP -- A1
//SH_CP -- A2
#include <Wire.h>
#include "DS1307.h"
#include <MsTimer2.h>
#define SJ 11 //时间设置键接口
#define SK 10 //秒表键接口
#define DK1 9 //定时键接口
#define ZK 5 //增加键接口
#define JK 6 //减少键接口
#define BZ 7 //蜂鸣器接口
#define LED 8 //LED接口
int szl,val,dsl,dnian,dyue,dri,dxiaos,dfenz,dmiaoz,dmiaob,dsjs; //秒表、定时分辨变量;定时小时、定时分钟、定时秒钟
// 定义记录按键当前状态的变量
int S1,D1,Z1,J1,SZ,pmkg,fmkg;
// 定义记录按键最近一次状态变化的变量,并初始化状态为LOW。
int BS1=LOW; //秒表键最近一次状态变化的变量
int BD1=LOW; //定时键最近一次状态变化的变量
int BZ1=LOW; //增加键最近一次状态变化的变量
int BJ1=LOW; //减少键最近一次状态变化的变量
int SZ1=LOW; //设置键最近一次状态变化的变量
// 定义记录最近一次抖动的时间变量,并初始化时间为0毫秒。
long STime = 0; //秒表键最近一次抖动的时间变量
long DTime=0; //定时键最近一次抖动的时间变量
long ZTime=0; //增加键最近一次抖动的时间变量
long JTime=0; //减少键最近一次抖动的时间变量
long SZTime=0; //设置键最近一次抖动的时间变量
// 定义延迟抖动的时间变量
long debouncdDelay = 60;
int dataPin = A0; //DS 74hc595的14脚。
int latchPin = A1;//ST_CP 74hc595的12脚。
int clockPin = A2;//SH_CP 74hc595的11脚。
int x=0; //定义点显示与否,0为不显示,1为显示。
int y=0; //交替显示月日和小时分秒
//int s=0;//s为秒计时器
//这里定义了74HC595的那三个脚
DS1307 clock;//define a object of DS1307 class
void init_click(uint16_t _year, uint8_t _month, uint8_t _date, uint8_t _hour, uint8_t _minite, uint8_t _second, uint8_t _week)
{
// clock.begin();
clock.fillByYMD(_year, _month, _date, 1); //年、月、日
clock.fillByHMS(_hour, _minite, _second); //时、分、秒
clock.fillDayOfWeek(_week); //1=MON 2=TUE 3=WED 4=THU 5=FRI 6=SAT 7=SUN
clock.setTime();//write time to the RTC chip
}
void setup ()
{
//让74HC595的三个脚都是输出状态
pinMode(latchPin,OUTPUT);
pinMode(clockPin,OUTPUT);
pinMode(dataPin,OUTPUT);
pinMode(BZ,OUTPUT);
pinMode(LED,OUTPUT);
digitalWrite(BZ,HIGH);
digitalWrite(LED,LOW);
//配置10,9,5,6号引脚为输入引脚 如果是自己连接普通按键 pinMode(SK,INPUT_PULLUP),弱上拉
pinMode(SK,INPUT);//10号引脚
pinMode(DK1,INPUT);//9号引脚
pinMode(ZK,INPUT);//5号引脚
pinMode(JK,INPUT);//6号引脚
pinMode(SJ,INPUT);//11号引脚
// pinMode(dianya,INPUT);//A3号引脚
szl=0;
val=0;
dsl=0;
dxiaos=0;
dfenz=0;
dmiaoz=0;
pmkg=0;// 屏幕开关
fmkg=0; //蜂鸣器开关
clock.begin();
//init_click(2017, 8, 26, 20, 44, 55,6);
// clock.fillByYMD(2017, 8, 26, 1); //年、月、日
// clock.fillByHMS(20, 58, 10); //时、分、秒
// clock.fillDayOfWeek(_week); //1=MON 2=TUE 3=WED 4=THU 5=FRI 6=SAT 7=SUN
// clock.setTime();//write time to the RTC chip
//调用中断,中断时间为10ms
MsTimer2::set(10, flash); // 10ms period
MsTimer2::start();
}
//定时器工作计数器
void flash()
{
static int xshi=0; //小时
static int s=0; //计数器
static int hao=0; //0.1秒
static int fen=0; //分
static int miao=0; //秒
s++;
if(dsjs==1){
dmiaoz++;
if(dmiaoz%2==0) digitalWrite(BZ,HIGH);
else digitalWrite(BZ,LOW);
if(dmiaoz>500){
dmiaoz=0;
dsjs=0;
digitalWrite(BZ,HIGH);
}
}
//秒表工作条件
if(val>1)
{
if(val==2) //秒表开始工作
{
hao++;
if(hao==86) hao+=12;//修正秒表计时
if(fmkg==1){
if(hao>85) digitalWrite(BZ,LOW);//在最后0.15秒内蜂鸣器发声
else digitalWrite(BZ,HIGH);}
if(hao==100)
{
hao=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
xshi++;
if(xshi==100) xshi=0;
}
}
}
if(xshi/10==0) disNum(11,1,0);
else disNum(xshi/10,1,0);
if(xshi/10==0 and xshi%10==0) disNum(11,2,0);
else disNum(xshi%10,2,0);
if (xshi/10==0 and xshi%10==0 and fen/10==0) disNum(11,3,0);
else disNum(fen/10,3,0);
if(xshi/10==0 and xshi%10==0 and fen/10==0 and fen%10==0) disNum(11,4,0);
else disNum(fen%10,4,0);
if(xshi/10==0 and xshi%10==0 and fen/10==0 and fen%10==0 and miao/10==0) disNum(11,5,0);
else disNum(miao/10,5,0);
disNum(miao%10,6,1);
disNum(hao/10,7,0);
disNum(11,8,0);
}
if(val==3) //秒表暂停
{
if(xshi/10==0) disNum(11,1,0);
else disNum(xshi/10,1,0);
if(xshi/10==0 and xshi%10==0) disNum(11,2,0);
else disNum(xshi%10,2,0);
if (xshi/10==0 and xshi%10==0 and fen/10==0) disNum(11,3,0);
else disNum(fen/10,3,0);
if(xshi/10==0 and xshi%10==0 and fen/10==0 and fen%10==0) disNum(11,4,0);
else disNum(fen%10,4,0);
if(xshi/10==0 and xshi%10==0 and fen/10==0 and fen%10==0 and miao/10==0) disNum(11,5,0);
else disNum(miao/10,5,0);
disNum(miao%10,6,1);
disNum(hao/10,7,0);
disNum(11,8,0);
digitalWrite(BZ,HIGH);
}
if(val==4) //秒表停止工作
{
val=1;
xshi=0;
fen=0;
miao=0;
hao=0;
}
}
//时间设定
if(szl>1)
{
if(szl==2)
{
disNum(dnian/1000,1,0);
disNum(dnian%1000/100,2,0);
disNum(dnian%100/10,3,0);
if(s>50) disNum(10,4,0);
else disNum(dnian%10,4,0);
}
if(szl==3)
{
disNum(dyue/10,1,0);
if(s>50) disNum(10,2,0);
else disNum(dyue%10,2,0);
}
if(szl==4)
{
disNum(dri/10,3,0);
if(s>50) disNum(10,4,0);
else disNum(dri%10,4,0);
}
if(szl==5)
{
disNum(dxiaos/10,1,0);
if(s>50) disNum(10,2,0);
else disNum(dxiaos%10,2,0);
}
if(szl==6)
{
disNum(dfenz/10,3,0);
if(s>50) disNum(10,4,0);
else disNum(dfenz%10,4,0);
}
if(szl==7)
{
disNum(dmiaoz/10,5,0);
if(s>50) disNum(10,6,0);
else disNum(dmiaoz%10,6,0);
}
}
//定时器工作
if(dsl>1)
{
if(dsl==2) //调整定时的小时数
{
if(dxiaos/10==0) disNum(11,1,0);
else disNum(dxiaos/10,1,0);
if(s>50) disNum(10,2,0);
else disNum(dxiaos%10,2,0);
disNum(11,3,0);
disNum(11,4,0);
disNum(11,5,0);
disNum(11,6,0);
disNum(dsl,7,0);
disNum(11,8,0);
}
if(dsl==3) //调整定时的分钟数
{
if(dxiaos/10==0) disNum(11,1,0);
else disNum(dxiaos/10,1,0);
if(dxiaos%10==0) disNum(11,2,0);
else disNum(dxiaos%10,2,0);
if(dfenz/10==0) disNum(11,3,0);
else disNum(dfenz/10,3,0);
if(s>50) disNum(10,4,0);
else disNum(dfenz%10,4,0);
disNum(11,5,0);
disNum(11,6,0);
disNum(dsl,7,0);
disNum(11,8,0);
}
if(dsl==4) //调整定时的秒数
{
if(dxiaos/10==0) disNum(11,1,0);
else disNum(dxiaos/10,1,0);
if(dxiaos%10==0) disNum(11,2,0);
else disNum(dxiaos%10,2,0);
if(dfenz/10==0) disNum(11,3,0);
else disNum(dfenz/10,3,0);
if(dfenz%10==0) disNum(11,4,0);
else disNum(dfenz%10,4,0);
if(dmiaoz/10==0) disNum(11,5,0);
else disNum(dmiaoz/10,5,0);
if(s>50) disNum(10,6,0);
else disNum(dmiaoz%10,6,0);
disNum(dsl,7,0);
disNum(11,8,0);
}
}
if(s<50)x=1; //秒点显示与否开关,1开,0关。
else x=0;
if(s==100)
{
s=0;
y++;
if(y==8) y=1;
}
}
void printTime()
{
int dNum [8];//定义数组,显示年月日时分秒
//int nian,yue,ri,shi,fen,miao; //定义年月日时分秒
int i;
clock.getTime();
// nian=clock.year;
if(dsl==5) //定时器开始工作,定时器指示灯亮,第八个虚拟数码管输入数字5
{
digitalWrite(LED,HIGH);//定时继电器工作
// clock.getTime();
if(dmiaob!=clock.second)
{
dmiaob=clock.second;
if(dmiaoz==0)
{
if(dfenz==0)
{
if(dxiaos!=0)
{
dxiaos--;
dfenz=59;
dmiaoz=59;
}
else //定时结束
{
val=1;
dsl=1;
dsjs=1;
dmiaoz=0;
//关闭定时指示灯
digitalWrite(LED,LOW); //关闭定时继电器
}
}
else {
dfenz--;
dmiaoz=59;
}
}
else dmiaoz--;
}
if(dxiaos/10==0) disNum(11,1,0);
else disNum(dxiaos/10,1,0);
if(dxiaos/10==0 and dxiaos%10==0) disNum(11,2,0);
else disNum(dxiaos%10,2,0);
if(dxiaos/10==0 and dxiaos%10==0 and dfenz/10==0) disNum(11,3,0);
else disNum(dfenz/10,3,0);
if(dxiaos/10==0 and dxiaos%10==0 and dfenz/10==0 and dfenz%10==0) disNum(11,4,1);
else disNum(dfenz%10,4,1);
if(dxiaos/10==0 and dxiaos%10==0 and dfenz/10==0 and dfenz%10==0 and dmiaoz/10==0) disNum(11,5,0);
else disNum(dmiaoz/10,5,0);
disNum(dmiaoz%10,6,0);
disNum(dsl,7,0);
disNum(10,8,0);
}
else{
if(y<3){
if(clock.month/10==0)dNum [1]=11;
else dNum [1]=clock.month/10;
dNum [2]=clock.month%10;
if(clock.dayOfMonth/10==0) dNum [3]=11;
else dNum [3]=clock.dayOfMonth/10 ;
dNum [4]=clock.dayOfMonth%10;
disNum(dNum[1], 1,0);
disNum(dNum[2], 2,0);
disNum(dNum[3], 3,0);
disNum(dNum[4], 4,0);
disNum(11, 5,0);
disNum(11, 6,0);
disNum(val, 7,0);
disNum(11, 8,0);
}
if(y>2)
{
if(clock.hour/10==0) dNum [1]=11;
else dNum [1]=clock.hour/10;
dNum [2]=clock.hour%10;
dNum [3]=clock.minute/10;
dNum [4]=clock.minute%10;
dNum [5]=clock.second/10;
dNum [6]=clock.second%10;
dNum [7]=11;
// int t=dNum[8];
disNum(dNum[1], 1,0);
disNum(dNum[2], 2,x);
disNum(dNum[3], 3,0);
disNum(dNum[4], 4,0);
disNum(dNum[5], 5,0);
disNum(dNum[6], 6,1);
disNum(pmkg, 7,0);
disNum(11, 8,0);
}
}
}
//这个函数是显示一个数用的disNum(显示的数,显示的位)
void disNum(int Num_Qua, int Num_Pos, int Num_Dec)
{
int Num_Qua_B = 0;
int Num_Pos_B = 0;
switch (Num_Qua)
{
case 0:Num_Qua_B = 192;break;
case 1:Num_Qua_B = 249;break;
case 2:Num_Qua_B = 164;break;
case 3:Num_Qua_B = 176;break;
case 4:Num_Qua_B = 153;break;
case 5:Num_Qua_B = 146;break;
case 6:Num_Qua_B = 130;break;
case 7:Num_Qua_B = 248;break;
case 8:Num_Qua_B = 128;break;
case 9:Num_Qua_B = 144;break;
case 10:Num_Qua_B = 247;break; //数码管显示"_"
default: Num_Qua_B = 255;break; //0-9以外的整数表示该位的数不显示
};
//这个值转换为2进制 为一个数abcdefg的需要亮的针脚。增加的绿灯数字为1,最后一个位。
switch (Num_Pos)
{
case 1:Num_Pos_B = 1;break;
case 2:Num_Pos_B = 2;break;
case 3:Num_Pos_B = 4;break;
case 4:Num_Pos_B = 8;break;
case 5:Num_Pos_B = 16;break;
case 6:Num_Pos_B = 32;break;
case 7:Num_Pos_B = 64;break;
case 8:Num_Pos_B = 128;break;
default: Num_Pos_B = 0;break;
};
//这个值转换为2进制 为当前点亮的位数。
if (Num_Dec == 1)
{
Num_Qua_B = Num_Qua_B + 128;
}
if(pmkg==1) Num_Pos_B = 0;
//128是Q7端口2进制值转换为10进制的结果。
digitalWrite(latchPin,LOW); //将ST_CP口上面加低电平让芯片准备好接收数据
int L = Num_Qua_B; int R = Num_Pos_B;
shiftOut(dataPin,clockPin,MSBFIRST,R);
shiftOut(dataPin,clockPin,MSBFIRST,L);
digitalWrite(latchPin,HIGH); //将ST_CP这个针脚恢复到高电平
//上面是74HC595的输出方式 每个74HC595能接受一个8位的2进制数值来电灯 第一个74HC595再次输入一个8位的数值他会把他现在的数值传给第二个串联的74HC595。
delayMicroseconds(100);
}
void loop()
{
//时间设置键
int SJ1 = digitalRead(SJ);//读取当前时间设置按键状态 SJ1->buttonState
if(SJ1 != SZ1)
{
//如果按键发生了变化 则重新设置最近一次抖动的时间
//方法millis()可以获取当前时间,单位统一为毫秒。
SZTime = millis();
}
// 判断按键按下状态时间间隔是否大于延迟抖动的时间长度。
if(millis()-SZTime>debouncdDelay)
{
// 判断当前的按键状态是否和之前有所变化
if(SJ1 != SZ){
// 如果发生了变化,
// 则更新按键状态变量。
SZ =SJ1;
if(SZ == HIGH){
//再次确认是否真的按下了按键,是的话就执行以下命令
szl++;
if(szl==2){
clock.getTime();
dnian=clock.year;
dyue=clock.month;
dri=clock.dayOfMonth;
dxiaos=clock.hour;
dfenz=clock.minute;
dmiaoz=clock.second;
}
if(szl==8){
clock.fillByYMD(dnian,dyue,dri, 1); //年、月、日
clock.fillByHMS(dxiaos, dfenz, dmiaoz); //时、分、秒
clock.setTime();//write time to the RTC chip
szl=1;
}
}
}
}
// 更新按键最近一次状态变化的变量
SZ1 = SJ1;
//秒表键
int DS1 = digitalRead(SK);
if(DS1 != BS1)
{
STime = millis();
}
if(millis()-STime>debouncdDelay)
{
if(DS1 != S1){
S1 = DS1;
if(S1 == HIGH){
val++;
}
}
}
BS1 = DS1;
//定时键
int ss1=digitalRead(DK1);
if(ss1 != BD1)
{
DTime = millis();
}
if(millis()-DTime>debouncdDelay){
if(ss1 != D1)
{
D1 = ss1;
if(D1 == HIGH)
{
dsl++;
if(dsl==6) //取消定时
{
val=1;
dsl=1;
}
}
}
}
BD1 = ss1;
//增键
int DZ1 = digitalRead(ZK);
if(DZ1 != BZ1)
{
ZTime = millis();
}
if(millis()-ZTime>debouncdDelay)
{
if(DZ1 != Z1)
{
Z1 = DZ1;
if(Z1 == HIGH)
{
if(val*dsl*szl==1) fmkg=!fmkg;
if(szl>1)
{
if(szl==2)
{
dnian++;
}
if(szl==3)
{
dyue++;
if(dyue==13) dyue=1;
}
if(szl==4)
{
dri++;
if(dri==32) dri=1;
}
if(szl==5)
{
dxiaos++;
if(dxiaos==24) dxiaos=1;
}
if(szl==6)
{
dfenz++;
if(dfenz==60) dfenz=1;
}
if(szl==7)
{
dmiaoz++;
if(dmiaoz==60) dmiaoz=1;
}
}
if(dsl>1)
{
if(dsl==2)
{
dxiaos++;
if(dxiaos==100) dxiaos=0;
}
if(dsl==3)
{
dfenz++;
if(dfenz==60) dfenz=0;
}
if(dsl==4)
{
dmiaoz++;
if(dmiaoz==60) dmiaoz=0;
}
}
}
}
}
BZ1 = DZ1;
//减键
int DJ1 = digitalRead(JK);
if(DJ1 != BJ1)
{
JTime = millis();
}
if(millis()-JTime>debouncdDelay)
{
if(DJ1 != J1)
{
J1 = DJ1;
if(J1 == HIGH)
{
if(val*dsl*szl==1) pmkg=!pmkg;
if(dsl>1){
if(dsl==2)
{
dxiaos--;
if(dxiaos==-1) dxiaos=99;
}
if(dsl==3)
{
dfenz--;
if(dfenz==-1) dfenz=59;
}
if(dsl==4)
{
dmiaoz--;
if(dmiaoz==-1) dmiaoz=59;
}
}
if(szl>1)
{
if(szl==2)
{
dnian--;
}
if(szl==3)
{
dyue--;
if(dyue==-1) dyue=12;
}
if(szl==4)
{
dri--;
if(dri==-1) dri=31;
}
if(szl==5)
{
dxiaos--;
if(dxiaos==-1) dxiaos=23;
}
if(szl==6)
{
dfenz--;
if(dfenz==-1) dfenz=59;
}
if(szl==7)
{
dmiaoz--;
if(dmiaoz==-1) dmiaoz=59;
}
}
}
}
}
BJ1 = DJ1;
if(val*dsl*szl==1 or dsl==5)
{
printTime();
}
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|