新手勿噴,打了個實物板,驗證了一下功能正常。
1.實現功能 開機時正常顯示時間并讀取DS1302ROM 鬧鐘時間 進行初始化,
2.時間設置:按KEY1 1次進入時間設置畫面 在按KEY3進入時間設置狀態 秒設置,然后按key1 key2進行時間加減,在按KEY3分設置 key1 key2進行時間加減......
3.鬧鐘:按key1 倆次后進入鬧鐘畫面 在按KEY3進入鬧鐘設置狀態分設置,然后按key1 key2進行時間加減 ...最后設置完后退出之前寫入DS1302ROM。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.gif (90.71 KB, 下載次數: 39)
下載附件
2022-6-2 19:57 上傳
11.png (68.73 KB, 下載次數: 41)
下載附件
仿真
2022-6-2 17:36 上傳
單片機源程序如下:
#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;//設置鬧鐘
}
}
}
51hei.png (12.32 KB, 下載次數: 31)
下載附件
2022-6-2 19:59 上傳
Keil5代碼與Proteus8.8仿真下載:
da13021602-02.7z
(109.43 KB, 下載次數: 68)
2022-6-2 19:58 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|