第1个回答 推荐于2016-01-03
我有个本科时学习51时自己写的,功能是可以实现的,不过方法不大好,你可以参考一下
要是完全用这个我不大建议,最还自己看看,写简便点的
#include <AT89X52.h>
#include<intrins.h>
#define NOP _nop_()
sbit p07=P0^7;
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_E=P2^2;
sbit RST=P2^3;
sbit SCLK=P2^4;
sbit IO=P2^5;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit INT=P3^2;
sbit WEI=P1^0;
sbit UP=P1^1;
sbit DOWN=P1^2;
unsigned char Busy,temp1;
unsigned char times;
char ge,shi;
/************************************
长延时函数
*************************************/
void L_delay(unsigned char ms)
{
unsigned char i;
for(i=0;i<ms;i++)
{
unsigned char j;
for(j=0;j<247;j++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/************************************
短延时函数
*************************************/
void S_delay(unsigned char m)
{
unsigned char n;
for(n=0;n<m;n++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
/**************************************
检测LCD是否忙
**************************************/
void lcd_busy()
{
Busy=0;
P0=0xff;
LCD_RS=0; //指令有效
LCD_RW=1; //读指令
LCD_E=1; //使能
S_delay(5);
LCD_E=0; //关闭
if(p07==0)
Busy=0; //busy 忙碌,禁止
else
Busy=1; // 不忙碌,允许写入数据
}
/**************************************
写指令数据到LCD
RW=0是写入
RS=0写入的是指令
**************************************/
void lcd_wc(int cmd)
{
while(Busy==1)
; //检测忙碌
S_delay(5);
LCD_RS=0;
LCD_RW=0; //写指令
LCD_E=0;
S_delay(5);
LCD_E=1;
S_delay(5);
P0=cmd; //指令码
S_delay(5);
LCD_E=0;
}
/**************************************
写显示数据到LCD
RW=0是写入
RS=1写入的是数据
**************************************/
void lcd_wd(unsigned char dat)
{
while(Busy==1) //检测忙碌
;
S_delay(5);
LCD_RS=1;
LCD_RW=0; //写数据
LCD_E=0;
S_delay(5);
LCD_E=1;
S_delay(5);
P0=dat; //数据码
S_delay(5);
LCD_E=0;
}
/****************************************
设定显示位置
****************************************/
void lcd_pos(unsigned char HH,unsigned char VV)
{
unsigned char PP;
if(HH==1)
PP=VV+0x80; //第一行数据码
if(HH==2)
PP=VV+0xc0; //第二行数据码
lcd_wc(PP); //写入数据码
}
/****************************************
LCD清屏
****************************************/
void lcd_clr()
{
S_delay(5);
lcd_wc(0x01);
L_delay(5);
}
/****************************************
LCD初始化
****************************************/
void lcd_init()
{
L_delay(5);
lcd_clr(); //清屏
lcd_wc(0x38); //设置16*2显示,5*7点阵,8位数据
L_delay(5);
lcd_wc(0x0c); //0CH-显示开,关光标 ;0EH-显示开,有光标 ; 0FH-显示开,有光标,光标闪烁
L_delay(5);
lcd_wc(0x06); //当读写一个字符后,地址指针加一,且光标加一
L_delay(5);
lcd_wc(0x01); //清屏
L_delay(5);
}
/******************************************
函数名:void write1302()
功能:写入芯片数据
入口参数:地址add 数据dat
返回值:读取的字节
******************************************/
void write1302(unsigned char add,unsigned char dat)
{
unsigned char z;
SCLK=0;
RST=1;
ACC=add;
NOP;NOP;NOP;
for(z=8;z>0;z--)
{
IO=ACC0;
NOP;NOP;NOP;
SCLK=1;
NOP;NOP;NOP;
SCLK=0;
ACC=_cror_(ACC,1);
}
ACC=dat;
for(z=8;z>0;z--)
{
IO=ACC0;
NOP;NOP;NOP;
SCLK=1;
NOP;NOP;NOP;
SCLK=0;
ACC=_cror_(ACC,1);
}
RST=0;
S_delay(5);
}
/******************************************
函数名:void read1302()
功能:读出芯片数据
入口参数:地址add
返回值:读取的一字节数据
******************************************/
void read1302(unsigned char ad)
{
unsigned char t;
SCLK=0;
RST=1;
ACC=ad;
for(t=8;t>0;t--)
{
IO=ACC0;
NOP;NOP;NOP;
SCLK=1;
NOP;NOP;NOP;
SCLK=0;
ACC=_cror_(ACC,1);
}
for(t=7;t>0;t--)
{
ACC7=IO;
NOP;NOP;NOP;NOP;NOP;NOP;
SCLK=1;
NOP;NOP;NOP;NOP;NOP;NOP;
SCLK=0;
ACC=_cror_(ACC,1);
}
RST=0;
temp1=ACC;
}
/******************************************
时钟芯片初始化
******************************************/
void ds1302_init()
{
write1302(0x8e,0x00);
}
/******************************************
函数名:void fenli()
功能:将读取的一字节数分成高四位十位和低四位个位
入口参数:读取的数据
返回值:十位数shi,个位数ge
******************************************/
void fenli(unsigned char D)
{
unsigned char D0,D1,D2;
D1=D&0x0f;
ge=D1;
D0=_cror_(D,4);
D2=D0&0x0f;
shi=D2;
}
/******************************************
显示函数
******************************************/
void play()
{
read1302(0x85); //读小时
fenli(temp1);
lcd_pos(1,0);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
lcd_wd(0x3a);
read1302(0x83); //读分
fenli(temp1);
lcd_pos(1,3);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
lcd_wd(0x3a);
read1302(0x81); //读秒
fenli(temp1);
lcd_pos(1,6);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
lcd_pos(1,10);
lcd_wd(0x57);
lcd_wd(0x65);
lcd_wd(0x65);
lcd_wd(0x6b);
read1302(0x8b); //读星期
fenli(temp1);
lcd_wd(ge+0x30);
read1302(0x8d); //读年
fenli(temp1);
lcd_pos(2,1);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
lcd_wd(0x2d);
read1302(0x89); //读月
fenli(temp1);
lcd_pos(2,4);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
lcd_wd(0x2d);
read1302(0x87); //读日
fenli(temp1);
lcd_pos(2,7);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
}
/*********************************
函数名;WEIXUAN()
功能;记录WEI按键按下的次数
入口参数;无
返回值;按下次数times
*********************************/
void WEIXUAN()
{
if(WEI==0)
{
L_delay(5);
if(WEI==0)
{
times+=1;
}
if(times==7)
times=0;
L_delay(500);
}
}
/**************************************
调节小时
**************************************/
void xiaoshi()
{
read1302(0x85);
fenli(temp1);
while(UP==0)
{
L_delay(5);
if(UP==0)
ge++;
if(ge==10)
{shi++;ge=0;}
if(ge==4&&shi==2)
{ge=0;shi=0;}
L_delay(500);
}
while(DOWN==0)
{
L_delay(5);
if(DOWN==0)
ge--;
if(ge==(-1)&&shi==0)
{ge=3;shi=2;}
if(ge==(-1))
{shi--;ge=9;}
L_delay(500);
}
temp1=shi*16+ge;
write1302(0x84,temp1);
read1302(0x85);
fenli(temp1);
lcd_pos(1,0);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
}
/**************************************
调节分
**************************************/
void fen()
{
read1302(0x83);
fenli(temp1);
while(UP==0)
{
L_delay(5);
if(UP==0)
ge++;
if(ge==10)
{shi++;ge=0;}
if(shi==6)
{ge=0;shi=0;}
L_delay(500);
}
while(DOWN==0)
{
L_delay(5);
if(DOWN==0)
ge--;
if(ge==(-1)&&shi==0)
{ge=9;shi=5;}
if(ge==(-1))
{shi--;ge=9;}
L_delay(500);
}
temp1=shi*16+ge;
write1302(0x82,temp1);
read1302(0x83);
fenli(temp1);
lcd_pos(1,3);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
}
/**************************************
调节秒
**************************************/
void miao()
{
read1302(0x81);
fenli(temp1);
while(UP==0)
{
L_delay(5);
if(UP==0)
ge++;
if(ge==10)
{shi++;ge=0;}
if(shi==6)
{ge=0;shi=0;}
L_delay(500);
}
while(DOWN==0)
{
L_delay(5);
if(DOWN==0)
ge--;
if(ge==(-1)&&shi==0)
{ge=9;shi=5;}
if(ge==(-1))
{shi--;ge=9;}
L_delay(500);
}
temp1=shi*16+ge;
write1302(0x80,temp1);
read1302(0x81);
fenli(temp1);
lcd_pos(1,6);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
}
/**************************************
调节周
**************************************/
void zhou()
{
read1302(0x8b);
fenli(temp1);
while(UP==0)
{
L_delay(5);
if(UP==0)
ge++;
if(ge==8)
{ge=1;}
L_delay(500);
}
while(DOWN==0)
{
L_delay(5);
if(DOWN==0)
ge--;
if(ge==0)
{ge=7;}
L_delay(500);
}
temp1=shi*16+ge;
write1302(0x8a,temp1);
read1302(0x8b);
fenli(temp1);
lcd_pos(1,14);
lcd_wd(ge+0x30);
}
/**************************************
调节年
**************************************/
void nian()
{
read1302(0x8d);
fenli(temp1);
while(UP==0)
{
L_delay(5);
if(UP==0)
ge++;
if(ge==10)
{shi++;ge=0;}
if(shi==10)
{ge=0;shi=0;}
L_delay(500);
}
while(DOWN==0)
{
L_delay(5);
if(DOWN==0)
ge--;
if(ge==(-1)&&shi==0)
{ge=9;shi=9;}
if(ge==(-1))
{shi--;ge=9;}
L_delay(500);
}
temp1=shi*16+ge;
write1302(0x8c,temp1);
read1302(0x8d);
fenli(temp1);
lcd_pos(2,1);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
}
/**************************************
调节月
**************************************/
void yue()
{
read1302(0x89);
fenli(temp1);
while(UP==0)
{
L_delay(5);
if(UP==0)
ge++;
if(ge==10)
{shi++;ge=0;}
if(shi==1&&ge==3)
{ge=1;shi=0;}
L_delay(500);
}
while(DOWN==0)
{
L_delay(5);
if(DOWN==0)
ge--;
if(ge==(0)&&shi==0)
{ge=2;shi=1;}
if(ge==(-1))
{shi--;ge=9;}
L_delay(500);
}
temp1=shi*16+ge;
write1302(0x88,temp1);
read1302(0x89);
fenli(temp1);
lcd_pos(2,4);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
}
/**************************************
调节日
**************************************/
void ri()
{
read1302(0x87);
fenli(temp1);
while(UP==0)
{
L_delay(5);
if(UP==0)
ge++;
if(ge==10)
{shi++;ge=0;}
if(shi==3&&ge==2)
{ge=1;shi=0;}
L_delay(500);
}
while(DOWN==0)
{
L_delay(5);
if(DOWN==0)
ge--;
if(ge==(0)&&shi==0)
{ge=1;shi=3;}
if(ge==(-1))
{shi--;ge=9;}
L_delay(500);
}
temp1=shi*16+ge;
write1302(0x86,temp1);
read1302(0x87);
fenli(temp1);
lcd_pos(2,7);
lcd_wd(shi+0x30);
lcd_wd(ge+0x30);
}
/**************************************
函数名;CTRL
功能;选择调解位
**************************************/
void CTRL()
{
WEIXUAN();
lcd_wc(0x38);
switch(times)
{
case 1: //位选按下1次就是调节小时显示
xiaoshi();
break;
case 2: //位选按下2次就是调节分显示
fen();
break;
case 3: //位选按下3次就是调节秒显示
miao();
break;
case 4: //位选按下4次就是调节星期显示
zhou();
break;
case 5: //位选按下5次就是调节年显示
nian();
break;
case 6: //位选按下6次就是调节月显示
yue();
break;
case 7: //位选按下7次就是调节日显示
ri();
break;
}
}
/********************************
外部中断0
********************************/
void exter() interrupt 0
{
EX0=0; //关闭外部中断0
INT=1; //禁止外部中断0
if(INT==0)
{
L_delay(5);
if(INT==0)
{
CTRL();
play();
}
EX0=1; //开放中断0
}
else
times=0;
}
/******************************************
主函数
******************************************/
void main()
{
ACC=0xff;
ds1302_init();
lcd_init();
while(1)
{
EA=1; //开总中断
EX0=1; //开外部中断0
IT0=0; //设置低电平触发
play();
lcd_pos(2,9);
lcd_wd(0xa0);
lcd_wd(0xa0);
lcd_wd(0xa0);
lcd_wd(0xa0);
lcd_wd(0xa0);
}
}本回答被提问者采纳