新手勿喷,打了个实物板,验证了一下功能正常。
1.实现功能 开机时正常显示时间并读取DS1302ROM 闹钟时间 进行初始化,
2.时间设置:按KEY1 1次进入时间设置画面 在按KEY3进入时间设置状态 秒设置,然后按key1 key2进行时间加减,在按KEY3分设置 key1 key2进行时间加减......
3.闹钟:按key1 俩次后进入闹钟画面 在按KEY3进入闹钟设置状态分设置,然后按key1 key2进行时间加减 ...最后设置完后退出之前写入DS1302ROM。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
仿真
单片机源程序如下:
#include<reg52.h>
#include"lcd1602.h"
#include "DS1302.h"
#include "mues.h"
void showsit();
void showsec();
void showmin();
void showhour();
void showbit();
void showyear();
void showmon();
void showday();
void ak();
void alarmclock();
void alarmclocksit();
void alarmclockmin();
void alarmclockhour();
void alarmclockshowbit();
sbit pwm=P3^0;
sbit key1=P2^7;
unsigned char flag,bits,count,sitcount,secdata,mindata,hourdata,keyone,yeardata,mondata,daydata
,alarmclockcount;
unsigned char alarmhourdata,alarmmindata,nudata,nudatas,t_H,t_L,da=1,db=0,dbtwo=3;
//延时函数
void DelayMS1(unsigned int x)
{
unsigned char t;
while(x--) for(t=0;t<120;t++);
}
void initEx0() { //KEY3
EA = 1; //开启总中断
EX0 = 1; //开启0号外部中断
IT0 = 1; //设置外部中断触发方式
//0 - 低电平触发
//1 - 负跳变触发
}
void ex0_intr() interrupt 0 //外部0中断处理函数
{
if(keyone==0){ //实现一键多意,只有3个按键不够用
flag++;
if(flag>=3){flag=0;}
}
if(flag==1&&sitcount==1&&keyone==1){if(secdata<=0){secdata=60;}secdata--;}
if(flag==1&&sitcount==2&&keyone==1){if(mindata<=0){mindata=60;}mindata--;}
if(flag==1&&sitcount==3&&keyone==1){if(hourdata<=0){hourdata=24;}hourdata--;}
if(flag==1&&sitcount==4&&keyone==1){if(yeardata<=0){yeardata=22;}yeardata--;}
if(flag==1&&sitcount==5&&keyone==1){if(mondata<=0){mondata=11;}mondata--;}
if(flag==1&&sitcount==6&&keyone==1){if(daydata<=0){daydata=31;}daydata--;}
if(flag==2&&alarmclockcount==1&&keyone==1){if(alarmmindata<=0){alarmmindata=60;}alarmmindata--;}
if(flag==2&&alarmclockcount==2&&keyone==1){if(alarmhourdata<=0){alarmhourdata=24;}alarmhourdata--;}
}
void initEx1() { //KEY2
EA = 1; //开启总中断
EX1 = 1; //开启0号外部中断
IT1 = 1; //设置外部中断触发方式
//0 - 低电平触发
//1 - 负跳变触发
}
void ex1_intr() interrupt 2 //外部1中断处理函数处理按键/切换
{
if(flag==1&&sitcount==1){
secdata++;
if(secdata>=60){secdata=0;}
}
if(flag==1&&sitcount==2){
mindata++;
if(mindata>=60){mindata=0;}
}
if(flag==1&&sitcount==3){
hourdata++;
if(hourdata>=24){hourdata=0;}
}
if(flag==1&&sitcount==4){
yeardata++;
if(yeardata>=24){yeardata=0;}
}
if(flag==1&&sitcount==5){
mondata++;
if(mondata>=12){mondata=0;}
}
if(flag==1&&sitcount==6){
daydata++;
if(daydata>=31){daydata=0;}
}
if(flag==2&&alarmclockcount==1){
alarmmindata++;
if(alarmmindata>=60){alarmmindata=0;}
}
if(flag==2&&alarmclockcount==2){
alarmhourdata++;
if(alarmhourdata>=24){alarmhourdata=0;}
}
}
void INIT_T0() //KEY1 //1毫秒@12.000MHz
{
TMOD = 0x01; //设置定时器模式
TL0 = t_L; //设置定时初值
TH0 = t_H; //设置定时初值
TR0 = 1; //定时器0开始计时
EA = 1;
ET0 = 1;
}
void lcd1602T0() interrupt 1 //监听按键3切换功能
{
if(nudatas==1){ //开始蜂鸣器
if(db<dbtwo){
pwm=0;
}else{
pwm=1;
}
db++;
db=db%10;
TL0 = t_L; //设置定时初值
TH0 = t_H; //设置定时初值
}
if(nudata==0){
if(key1==0&&bits==0){
bits=1;
}
if( key1==1&&bits==1){
if(flag==0&&keyone==0){ TR1=1;}
if(flag==1){sitcount++;bits=0;if( sitcount>=8){sitcount=0;}
if(flag==1&&sitcount==1){ keyone=1;}}
if(flag==2){alarmclockcount++;bits=0;if(alarmclockcount>=4){alarmclockcount=0;}
if(flag==2&&alarmclockcount==1){keyone=1;}}
bits=0;
}
t_H = (65535 - 30000) / 256;
t_L = (65535 - 30000) % 256;
}
}
//上面是三个按键中断
void INIT_T1(){ //开启定时器1定时读DS1302时间显示出来
TMOD = 0x20; //设置定时器模式
TL1 = 0x88; //设置定时初值
TH1 = 0x88; //设置定时重载值
TR1 = 0; //定时器1开始计时
EA = 1;
ET1 = 1;
}
void SEGT1() interrupt 3
{
unsigned char nums;
nums++;
if(nums>=200){
nums=0;
DS1302redinit();//定时器每200MS取一次时间然后显示到1602
tab1[12]=((TIME[0]&0x0f)+'0'); //秒
tab1[11]=((TIME[0] >> 4)+'0');
tab1[10]='-';
tab1[9]=((TIME[1]&0x0f)+'0'); //分
tab1[8]=((TIME[1] >> 4)+'0');
tab1[7]='-';
tab1[6]=((TIME[2]&0x0f)+'0');
tab1[5]=((TIME[2] >> 4)+'0');
tab2[6]=((TIME[6]&0x0f)+'0');
tab2[5]=((TIME[6] >> 4)+'0');
tab2[7]='-';
tab2[9]=((TIME[4]&0x0f)+'0');
tab2[8]=((TIME[4] >> 4)+'0');
tab2[10]='-';
tab2[12]=((TIME[3]&0x0f)+'0');
tab2[11]=((TIME[3] >> 4)+'0');
if((alarmmindata%10)==((TIME[1]&0x0f))
&&(alarmhourdata%10)==((TIME[2]&0x0f))
&&(alarmhourdata/10)==((TIME[2]>> 4))
&&(alarmmindata/10)==((TIME[1]>>4))
&&('0'==((TIME[0]&0x0f)+'0'))
&&('0'==((TIME[0] >> 4)+'0')))
{//闹钟
nudata=1;
TR1=0;
}
start();
}
}
void ak(){
unsigned char t,k;
for(k=0;k<20;k++){
if(key1==0){
break;
}
for(t=0;t<42;t++)
{
if(key1==0){
break;
}
t_H=toneH[soundtone[t]]; //提取音调对应的定时器初始值
t_L=toneL[soundtone[t]];
TH0=t_H; //给TH0和TL0赋值
TL0=t_L;
nudatas=1;
TR0=1;//打开定时器,蜂鸣器发声
DelayMS1(soundlong[t]*300); //延时soundlong[t]指定的时间长度
}
}
nudata=0;//关闭闹钟
nudatas=0;//关闭闹钟
}
void alarmclock(){
switch(alarmclockcount){
case 0:alarmclocksit();break;
case 1:alarmclockmin();break;
case 2:alarmclockhour();break;
case 3:alarmclockshowbit();break;
}
}
void alarmclockshowbit(){
ramTIME[1]=((alarmmindata/10*16)|(alarmmindata%10));//BCD码转换
ramTIME[0]=((alarmhourdata/10*16)|(alarmhourdata%10));
ram();//写闹钟时间到DS1302RAM
keyone=0;flag=0;flag=bits=count=sitcount=alarmclockcount=0; //设置好后还原
}
void alarmclockmin(){//调闹钟分
Whiteorder(0x80|0x49);
Whitedata(((alarmmindata%10)+'0'));
Whiteorder(0x80|0x48);
Whitedata(((alarmmindata/10)+'0'));
}
void alarmclockhour(){//调闹钟时
Whiteorder(0x80|0x46);
Whitedata(((alarmhourdata%10)+'0'));
Whiteorder(0x80|0x45);
Whitedata(((alarmhourdata/10)+'0'));
}
void alarmclocksit(){//进入闹钟初始化第一个页面
Whiteorder(0x80|0x00);//setting
Whitedata((0x00));
Whitedata((0x00));
Whitedata((0x00));
Whitedata(('a'));
Whitedata(('l'));
Whitedata(('a'));
Whitedata(('r'));
Whitedata(('m'));
Whitedata(('c'));
Whitedata(('l'));
Whitedata(('o'));
Whitedata(('c'));
Whitedata(('k'));
Whiteorder(0x80|0xc0);//setting
Whitedata((0x00));
Whitedata((0x00));
Whitedata((0x00));
Whitedata((0x00));
Whitedata((0x00));
Whitedata(((alarmhourdata/10)+'0'));
Whitedata(((alarmhourdata%10)+'0'));
Whitedata(('-'));
Whitedata(((alarmmindata/10)+'0'));
Whitedata(((alarmmindata%10)+'0'));
Whitedata((0x00));
Whitedata((0x00));
Whitedata((0x00));
}
void showclock(){
switch(count){
case 0: TR1 = 1;break;
}
}
void sitclock(){//时间设置
switch(sitcount){
case 0:showsit();break;
case 1:showsec();break;
case 2:showmin();break;
case 3:showhour();break;
case 4:showyear();break;
case 5:showmon();break;
case 6:showday();break;
case 7:showbit();break;
}
}
void showbit(){ //设置好时间后写到DS1302
INIT_TIME[0]=((secdata/10*16)+(secdata%10));
INIT_TIME[1]=(mindata/10*16)+(mindata%10);
INIT_TIME[2]=(hourdata/10*16)+(hourdata%10);
INIT_TIME[3]=(daydata/10*16)+(daydata%10);
INIT_TIME[4]=(mondata/10*16)+(mondata%10);
INIT_TIME[6]=(yeardata/10*16)+(yeardata%10);
DS1302init();
keyone=0;flag=0;flag=bits=count=sitcount=0; //设置好后还原
}
void showyear(){ //设置年
Whiteorder(0x80|0x46);
Whitedata(((yeardata%10)+'0'));
Whiteorder(0x80|0x45);
Whitedata(((yeardata/10)+'0'));
}
void showmon(){ //设置月
Whiteorder(0x80|0x49);
Whitedata(((mondata%10)+'0'));
Whiteorder(0x80|0x48);
Whitedata(((mondata/10)+'0'));
}
void showday(){ //设置日
Whiteorder(0x80|0x4c);
Whitedata(((daydata%10)+'0'));
Whiteorder(0x80|0x4b);
Whitedata(((daydata/10)+'0'));
}
void showsec(){ //设置秒
Whiteorder(0x80|0x0c);
Whitedata(((secdata%10)+'0'));
Whiteorder(0x80|0x0b);
Whitedata(((secdata/10)+'0'));
}
void showmin(){ //设置分
Whiteorder(0x80|0x09);
Whitedata(((mindata%10)+'0'));
Whiteorder(0x80|0x08);
Whitedata(((mindata/10)+'0'));
}
void showhour(){//设置时
Whiteorder(0x80|0x06);
Whitedata(((hourdata%10)+'0'));
Whiteorder(0x80|0x05);
Whitedata(((hourdata/10)+'0'));
}
void showsit(){ //设置时间第一个界面
Whiteorder(0x80|0x00);//setting
Whitedata(('S'));
Whitedata(('e'));
Whitedata(('t'));
Whitedata((0x00));
Whiteorder(0x80|0xc0);//setting
Whitedata((0x00));
Whitedata((0x00));
Whitedata((0x00));
Whitedata((0x00));
}
void main(){
RSTintit();
initEx1();
INIT_T0();
initEx0();
INIT_T1();
ramread();
alarmmindata = (((((ramreadTIME[0])&0xF0)>>4)*10)+(ramreadTIME[0])&0x0F);
alarmhourdata = (((((ramreadTIME[1])&0xF0)>>4)*10)+((ramreadTIME[1])&0x0F)); //开机就读取DS1302保存的闹钟
while(1){
if(nudata==1){
ak();
}
switch(flag){
case 0:showclock();break; //正常显示
case 1:TR1=0;sitclock();nudata=0;break;//设置时间 /闹钟关闭nudata=0;pwm=1;
case 2:TR1=0;alarmclock();break;//设置闹钟
}
}
}
Keil5代码与Proteus8.8仿真下载:
da13021602-02.7z
(109.43 KB, 下载次数: 68)
|