#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit sclk = P1^0; //1302時鐘端口
sbit dio = P1^1; //1302數據端口
sbit ce = P1^2; //1302使能
sbit wela = P2^7; //位選
sbit dula = P2^6; //段選
sbit KEY1=P3^0; //按鍵 設置/確認
sbit KEY2=P3^1; //按鍵 加
sbit KEY3=P3^2; //按鍵 減
uchar snum,fnum;
char shi,fen,miao;
uchar ss;
char FunctionKeyNum=0; //功能鍵鍵值
char FuncTempNum=0; //功能鍵臨時鍵值
typedef enum KeyState{StateInit,StateAffirm,StateSingle,StateRepeat}; //鍵值狀態值
/***********寫時分秒地址************/
#define write_shi 0x84
#define write_fen 0x82
#define write_miao 0x80
#define write_ram 0xc0
/***********讀時分秒地址************/
#define read_shi 0x85
#define read_fen 0x83
#define read_miao 0x81
#define read_ram 0xc1
// 0 1 2 3 4 5 6 7 8 9
uchar d[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共陰不帶小數點
//uchar dd[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; // 共陰帶小數點
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=120;y>0;y--);
}
void t0_init() //定時50ms一個中斷 //
{
TMOD |= 0X01; // 這樣第2~8bit原來是什么還是什么,不影響,第1bit賦值為1; TMOD=0x01 這樣是給2~8bit賦值為0,第1bit賦值為1。//
TH0 = (65536-46080)/256; // 11.0592MHz除12為921600Hz,就是一秒921600次機器周期,50ms=46080次機器周期。 //
TL0 = (65536-46080)%256; // 256(D)=0100(H),這里01就是高8位的數據,00就是低8位的數據, //
EA = 1; // 15536(D)里有多少個256,就相當于高8位有多少數值,就是除,商存入高8位寄存器后余下的數存入低8位即可//
ET0 = 1;
TR0 = 1;
}
void t1_init()
{
TMOD |= 0x10;
TH1 = 0xDC;
TL1 = 0x00;
TR1 = 1;
}
void temer0() interrupt 1
{
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
ss++;
if(ss==20)
ss=0;
}
void display(uchar shi,uchar fen,uchar miao) //顯示函數
{
if(FunctionKeyNum==0)
{
snum=30;
fnum=30;
}
if(FunctionKeyNum==1)
{
fnum++;
snum=30;
}
if(FunctionKeyNum==2)
{
snum++;
fnum=30;
}
if(snum>=30)
{
if((shi/10)<1) //如果小時十位小于1,
{
wela=1;
P0=0xfe; //第1位
wela=0;
dula = 1;
P0=0xff; // 小時十位就不顯示
dula = 0;
}
else
{
wela=1;
P0=0xfe; //第1位
wela=0;
dula=1;
P0=d[shi/10];
dula=0;
P0=0xff; //消隱 關閉位選
delay(2);
}
wela=1;
P0=0xfd; //第2位
wela=0;
dula=1;
P0=d[shi%10];
dula=0;
P0=0xff;
delay(2);
if(snum==60)
snum=0;
}
// if(miao%2==0) //if(miao%2==0) 1秒閃爍1次
if(ss>=10) // 這里寫為ss>=10,閃爍頻率可調
{
wela=1;
P0=0xfb; //第3位
wela=0;
dula=1;
P0=0x40; //第三位數碼管顯示“— ”
dula=0;
P0=0xff;
delay(2);
}
else
{
wela=1;
P0=0xfb; //第3位
wela=0;
dula=1;
P0=0; //第三位數碼管不顯示
dula=0;
P0=0xff;
delay(2);
}
if(fnum>=30)
{
wela=1;
P0=0xf7; //第4位
wela=0;
dula=1;
P0=d[fen/10];
dula=0;
P0=0xff;
delay(2);
wela=1;
P0=0xef; //第5位
wela=0;
dula=1;
P0=d[fen%10];
dula=0;
P0=0xff;
delay(2);
if(fnum==60)
fnum=0;
}
// if(miao%2==0) //if(miao%2==0) 1秒閃爍1次
if(ss>=10) //if(ss>=10)閃爍頻率可調
{
wela=1;
P0=0xdf; //第6位
wela=0;
dula=1;
P0=0x40; //第六位數碼管顯示“— ”
dula=0;
P0=0xff;
delay(2);
}
else
{
wela=1;
P0=0xdf; //第6位
wela=0;
dula=1;
P0=0; //第六位數碼管不顯示
dula=0;
P0=0xff;
delay(2);
}
wela=1;
P0=0xbf; //第7位
wela=0;
dula=1;
P0=d[miao/10]; //秒十位
dula=0;
P0=0xff;
delay(2);
wela=1;
P0=0x7f; //第8位
wela=0;
dula=1;
P0=d[miao%10]; //秒個位
dula=0;
P0=0xff;
delay(2);
}
void write_1302(uchar add,dat) //寫1302函數
{
uchar i,temp;
temp=add;
ce=0;
_nop_();
sclk=0;
_nop_();
ce=1;
_nop_();
for(i=0;i<8;i++)
{
sclk=0;
_nop_();
if((temp&0x01)==0x01)
dio=1; //把字節存儲在dio中
else
dio=0;
temp>>=1; //右移
sclk=1; //數據在上升沿時,DS1302讀取數據
_nop_();
}
temp=dat;
for(i=0;i<8;i++)
{
sclk=0;
_nop_();
if((temp&0x01)==0x01)
dio=1;
else
dio=0;
temp>>=1;
sclk=1;
_nop_();
}
ce=0; //數據傳送結束
sclk=0;
}
uchar read_1302(uchar add) //讀1302函數
{
uchar dat,dat1,i,temp;
temp=add;
ce=0;
_nop_();
sclk=0;
_nop_();
ce=1;
for(i=0;i<8;i++)
{
sclk=0;
_nop_();
if((temp&0x01)==0x01)
dio=1;
else
dio=0;
temp>>=1;
sclk=1;
_nop_();
}
for(i=0;i<8;i++)
{
sclk=0;
_nop_();
if(dio) 請問這句什么意思
dat|=0x80;
if(i<7)
dat>>=1;
sclk=1;
}
dat1=dat/16;
dat=dat%16;
dat=dat1*10+dat; //這三句功能是什么
ce=0;
sclk=0;
return dat;
}
void init_1302() //初始化函數 設置時間
{
write_1302(0x8e,0x00); //保護取消,可以進行寫操作
write_1302(write_miao,0x57);
write_1302(write_fen,0x55);
write_1302(write_shi,0x15);
write_1302(0x8e,0x80); //保護啟動,不能進行寫操作
}
void read_sf()
{
shi=read_1302(read_shi);
fen=read_1302(read_fen);
miao=read_1302(read_miao);
display(shi,fen,miao);
}
void KeyScan(void)
{
static uchar KeyStateTemp1 = 0; //按鍵狀態臨時存儲值1
static uchar KeyStateTemp2 = 0; //按鍵狀態臨時存儲值2
static uchar KeyStateTemp3 = 0; //按鍵狀態臨時存儲值3
static uchar KeyTime = 0; //按鍵延時時間
bit KeyPressTemp1; //按鍵是否按下存儲值1
bit KeyPressTemp2; //按鍵是否按下存儲值2
bit KeyPressTemp3; //按鍵是否按下存儲值3
if(KEY1==0)
{
delay(10);
if(KEY1==0)
FuncTempNum++;
if(FuncTempNum>3) FuncTempNum = 0;
}
if(FuncTempNum) //只有功能鍵被按下后,增加和減小鍵才有效
{
KeyPressTemp2 = KEY2; //讀取I/O口的鍵值
switch(KeyStateTemp2)
{
case StateInit: //按鍵初始狀態
if(!KeyPressTemp2) //當按鍵按下,狀態切換到確認態
KeyStateTemp2 = StateAffirm;
break;
case StateAffirm: //按鍵確認態
if(!KeyPressTemp2)
{
KeyTime = 0;
KeyStateTemp2 = StateSingle;//切換到單次觸發態
}
else KeyStateTemp2 = StateInit; //按鍵已抬起,切換到初始態
break;
case StateSingle: //按鍵單發態
if(KeyPressTemp2) //為什么按下時間小于1s
{
KeyStateTemp2 = StateInit; //按鍵釋放,則回到初始態
if(FunctionKeyNum == 1) //若功能鍵第一次按下
{
fen++;
fen=fen/10*16+fen%10; //轉為16進制
if(fen==0x60)
fen=0x00;
write_1302(write_fen,fen); //寫入1302
read_sf(); //讀出時間,然后顯示
}
if(FunctionKeyNum == 2) //若功能鍵第二次按下
{
shi++;
shi=shi/10*16+shi%10; //轉為16進制
if(shi==0x24)
shi=0x00;
write_1302(write_shi,shi);
read_sf();
}
}
else if(++KeyTime > 100) //按下時間大于1s(100*10ms)
{
KeyStateTemp2 = StateRepeat;//狀態切換到連發態
KeyTime = 0;
}
break;
case StateRepeat: //按鍵連發態
if(KeyPressTemp2)
KeyStateTemp2 = StateInit; //按鍵釋放,則進初始態
else //按鍵未釋放
{
if(++KeyTime > 10) //按鍵計時值大于100ms(10*10ms)
{
KeyTime = 0;
if(FunctionKeyNum == 1) //若功能鍵第一次按下
{
fen++;
fen=fen/10*16+fen%10; //轉為16進制
if(fen==0x60)
fen=0x00;
write_1302(write_fen,fen); //寫入1302
read_sf(); //讀出時間,然后顯示
}
if(FunctionKeyNum == 2) //若功能鍵第二次按下
{
shi++;
shi=shi/10*16+shi%10; //轉為16進制
if(shi==0x24)
shi=0x00;
write_1302(write_shi,shi);
read_sf();
}
}
break;
}
break;
default: KeyStateTemp2 = KeyStateTemp2 = StateInit; break;
}
KeyPressTemp3 = KEY3; //讀取I/O口的鍵值
switch(KeyStateTemp3)
{
case StateInit: //按鍵初始狀態
if(!KeyPressTemp3) //當按鍵按下,狀態切換到確認態
KeyStateTemp3 = StateAffirm;
break;
case StateAffirm: //按鍵確認態
if(!KeyPressTemp3)
{
KeyTime = 0;
KeyStateTemp3 = StateSingle; //切換到單次觸發態
}
else KeyStateTemp3 = StateInit; //按鍵已抬起,切換到初始態
break;
case StateSingle: //按鍵單發態
if(KeyPressTemp3) //按下時間小于1s
{
KeyStateTemp3 = StateInit; //按鍵釋放,則回到初始態
if(FunctionKeyNum == 1) //若功能鍵第一次按下
{
fen--;
fen=fen/10*16+fen%10; //轉為16進制
if(fen==-1)
fen=0x59;
write_1302(write_fen,fen);
read_sf();
}
if(FunctionKeyNum == 2) //若功能鍵第二次按下
{
shi--;
shi=shi/10*16+shi%10; //轉為16進制
if(shi==-1)
shi=0x23;
write_1302(write_shi,shi);
read_sf();
}
}
else if(++KeyTime > 100) //按下時間大于1s(100*10ms)
{
KeyStateTemp3 = StateRepeat; //狀態切換到連發態
KeyTime = 0;
}
break;
case StateRepeat: //按鍵連發態
if(KeyPressTemp3)
KeyStateTemp3 = StateInit; //按鍵釋放,則進初始態
else //按鍵未釋放
{
if(++KeyTime > 10) //按鍵計時值大于100ms(10*10ms)
{
KeyTime = 0;
if(FunctionKeyNum == 1) //若功能鍵第一次按下
{
fen--;
fen=fen/10*16+fen%10; //轉為16進制
if(fen==-1)
fen=0x59;
write_1302(write_fen,fen);
read_sf();
}
if(FunctionKeyNum == 2) //若功能鍵第二次按下
{
shi--;
shi=shi/10*16+shi%10; //轉為16進制
if(shi==-1)
shi=0x23;
write_1302(write_shi,shi);
read_sf();
}
}
break;
}
break;
default: KeyStateTemp3 = KeyStateTemp3 = StateInit; break;
}
}
}
void ExecuteKeyNum()
{
if(TF1)
{
TF1 = 0;
TH1 = 0xDC;
TL1 = 0x00;
KeyScan();
}
switch (FuncTempNum)
{
case 1: FunctionKeyNum = 1;
write_1302(0x8e,0x00); //寫保護取消
write_1302(write_miao,0x80); // 寫秒80,時鐘停止走時;
break;
case 2: FunctionKeyNum = 2;
break;
case 3:
FunctionKeyNum = 0;
write_1302(write_miao,0x00);
write_1302(0x8e,0x60); //保護啟動
FuncTempNum =0;
break;
}
}
void main()
{
t0_init();
t1_init();
init_1302();
while(1)
{
read_sf();
ExecuteKeyNum();
}
}
紅字的地方是不太懂得地方,請教各位大神
|