#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();
}
}
红字的地方是不太懂得地方,请教各位大神
|