#include <reg52.h>
#include <intrins.h>
//#define uint unsigned int
//下面是引脚连接关系
sbit scl_ds1302 =p3^2;
sbit io_ds1302 =p3^3;
sbit rst_ds1302 =p3^4;
sbit wr = p3^6;
sbit b0=p1^0;
sbit button1=p1^4;
sbit button2=p1^5;
sbit button3=p1^6;
sbit button4=p1^7;
unsigned int data display_buffer1[8],display_buffer2[8];
unsigned char bdata data_ds1302;
sbit bit_data0=data_ds1302^0;
sbit bit_data7=data_ds1302^7;
unsigned char bdata x;
sbit x0 =x^0;
sbit x7 =x^7;
void open_write_bit();
void initial_ds1302();
unsigned char read_ds1302(char command);
void open_write_bit();
void close_write_bit();
void read_time();
void set_time();
unsigned int zhuanhuan( unsigned int b);
void display1();
void display2();
void button();
void main( void)
{
initial_ds1302(); //上电启用,否则不走时
read_time(); //读取当前的年月日时分秒在数组
b0=0;
display_buffer2[5]=0x00;
display_buffer2[4]=0x03;
display_buffer2[3]=0x00;
display_buffer2[2]=0x06;
display_buffer2[1]=0x01;
display_buffer2[0]=0x04;
display_buffer1[5]=0x00;
display_buffer1[4]=0x08;
display_buffer1[3]=0x01;
display_buffer1[2]=0x00;
display_buffer1[1]=0x05;
display_buffer1[0]=0x08; //将03年6月14日08时10分58秒设置为当前时间
set_time(); //将数组中的时间置入ds1302
while(1)
{
button();
read_time();
}
}
void display1()
{
unsigned int *p;
unsigned int i, j, k;
p = display_buffer1;
j = 0xa0;
for(i=0;i <8;i++)
{
k = *p;
k = zhuanhuan( k);
p2 = j;
wr = 0;
// while(1);
_nop_( ); _nop_( ); _nop_( ); _nop_( );
p0 = k;
_nop_( ); _nop_( );
wr = 1;
p = p + 1;
j = j + 4;
}
}
void display2()
{
unsigned int *p;
unsigned int i, j, k;
p = display_buffer2;
j = 0xa0;
for(i=0;i <8;i++)
{
k = *p;
k = zhuanhuan( k);
p2 = j;
wr = 0;
// while(1);
_nop_( ); _nop_( ); _nop_( ); _nop_( );
p0 = k;
_nop_( ); _nop_( );
wr = 1;
p = p + 1;
j = j + 4;
}
}
unsigned int zhuanhuan( unsigned int b)
{
switch( b)
{
case 0: b = 0xc0; break;
case 1: b = 0xf9; break;
case 2: b = 0xa4; break;
case 3: b = 0xb0; break;
case 4: b = 0x99; break;
case 5: b = 0x92; break;
case 6: b = 0x82; break;
case 7: b = 0xf8; break;
case 8: b = 0x80; break;
case 9: b = 0x98; break;
default: break;
}
return b;
}
void close_write_bit()
{
char i;
scl_ds1302=0;
_nop_();
rst_ds1302=1;
_nop_();_nop_();
data_ds1302=0x8e; //write control redister
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
data_ds1302=0x80; //close write protect bit
io_ds1302=0;
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
}
void open_write_bit()
{
char i;
scl_ds1302=0;
_nop_();
rst_ds1302=1;
_nop_();_nop_();
data_ds1302=0x8e; //write control redister
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
data_ds1302=0x00; //open write protect bit
io_ds1302=0;
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
}
void initial_ds1302()
{
unsigned char i;
scl_ds1302=0;
_nop_();
rst_ds1302=1;
_nop_();_nop_();
data_ds1302=0x8e; //write control redister
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
data_ds1302=0x80; //close write protect bit
io_ds1302=0;
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;_nop_();
scl_ds1302=1;data_ds1302=data_ds1302> > 1;
}
rst_ds1302=0;
_nop_();
scl_ds1302=0;
scl_ds1302=0;
_nop_();
rst_ds1302=1;
_nop_();_nop_();
data_ds1302=0x90; //recharge register
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;_nop_();
scl_ds1302=1;data_ds1302=data_ds1302> > 1;
}
data_ds1302=0xa4; //no rechaarge for battery
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
rst_ds1302=0;
_nop_();
scl_ds1302=0;
scl_ds1302=0;
_nop_();
rst_ds1302=1;
_nop_();_nop_();
data_ds1302=0x80;
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
data_ds1302=0x80;
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
rst_ds1302=0;
_nop_();
scl_ds1302=0;
}
unsigned char read_ds1302(char command)
{
char i;
data_ds1302=(command < <1)|0x81;
scl_ds1302=0;
_nop_();
rst_ds1302=1;
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
scl_ds1302=1;
for (i=1;i <=8;i++) {
data_ds1302=data_ds1302> > 1;
scl_ds1302=0;_nop_();
bit_data7=io_ds1302;scl_ds1302=1;
}
rst_ds1302=0;
_nop_();
scl_ds1302=0;
return(data_ds1302);
}
void write_ds1302(unsigned char address,unsigned char numb) //写入时间
{
char i;
rst_ds1302=0;
scl_ds1302=0;
rst_ds1302=0;
rst_ds1302=1;
data_ds1302=0x80|(address < <1);
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
data_ds1302=numb;
for (i=1;i <=8;i++) {
scl_ds1302=0;io_ds1302=bit_data0;
_nop_();scl_ds1302=1;
data_ds1302=data_ds1302> > 1;
}
rst_ds1302=0;
scl_ds1302=1;
}
void read_time() //读取时间
{
unsigned char second,minute,hour,date,month,year,d;
second=0; //read second address
d=read_ds1302(second);
display_buffer1[0]=d&0x0f;
display_buffer1[1]=d> > 4;
minute=1; //read minute address
d=read_ds1302(minute);
display_buffer1[2]=d&0x0f;
display_buffer1[3]=(d> > 4);
hour=2; //read hour address
d=read_ds1302(hour);
display_buffer1[4]=d&0x0f;
display_buffer1[5]=(d> > 4);
date=3;
d=read_ds1302(date);
display_buffer2[0]=d&0x0f;
display_buffer2[1]=(d> > 4); //read data address
month=4;
d=read_ds1302(month);
display_buffer2[2]=d&0x0f;
display_buffer2[3]=(d> > 4); //read month address
year=6;
d=read_ds1302(year);
display_buffer2[4]=d&0x0f;
display_buffer2[5]=(d> > 4); //read year address
}
void set_time()
{
unsigned char data temp;
unsigned char data hour_address,minute_address,second_address,year_address,month_address,date_address;
year_address=6;
month_address=4;
date_address=3;
hour_address = 2;
minute_address = 1;
open_write_bit();
temp=(display_buffer2[5] < <4)|display_buffer2[4];
write_ds1302(year_address,temp);
temp=(display_buffer2[3] < <4)|display_buffer2[2];
write_ds1302(month_address,temp);
temp=(display_buffer2[1] < <4)|display_buffer2[0];
write_ds1302(date_address,temp);
temp=(display_buffer1[5] < <4)|display_buffer1[4];
write_ds1302(hour_address,temp);
temp=(display_buffer1[3] < <4)|display_buffer1[2];
write_ds1302(minute_address,temp);
temp=(display_buffer1[1] < <4)|display_buffer1[0];
write_ds1302(second_address,temp);
close_write_bit();
}
void button()
{
unsigned char data button1,button2,button3,button4;
char i;
if(button1=0)
{
for(i=0;i <8;i++)
{
display_buffer1[i]=0;
display2();
}
}
else if(button2=0)
{ display_buffer1[5]=display_buffer1[5]+1; }
else if(button3=0)
{ display_buffer1[3]=display_buffer1[3]+1; }
else if(button4=0)
{ display_buffer2[1]=display_buffer2[1]+1; }
else{ display1(); }
}
我把主程序和调整程序给你参考吧,其它的程序因硬件电路不同而不同。
;;;;主程序;;;;
;;;;;;;;;;;;;;;;;;;
START: SETB EA
MOV SCON,#00H ;串行输出,方式0
MOV TMOD,#10H ;计数器1,方式1
MOV TL1,#00H
MOV TH1,#00H
MOV DS1302_ADDR,#8EH
MOV DS1302_DATA,#00H ;允许写1302
LCALL WRITE
MOV DS1302_ADDR,#90H
MOV DS1302_DATA,#0A6H;1302充电,充电电流1.1MA
LCALL WRITE
MAIN1: MOV DS1302_ADDR,#8DH ;读出年
LCALL READ
MOV year,DS1302_DATA
MOV DS1302_ADDR,#8BH ;读出星期
LCALL READ
MOV week ,DS1302_DATA
MOV DS1302_ADDR,#89H ;读出月
LCALL READ
MOV month,DS1302_DATA
MOV DS1302_ADDR,#87H ;读出日
LCALL READ
MOV day,DS1302_DATA
MOV DS1302_ADDR,#85H ;读出小时
LCALL READ
MOV hour,DS1302_DATA
MOV DS1302_ADDR,#83H ;读出分钟
LCALL READ
MOV mintue,DS1302_DATA
MOV DS1302_ADDR,#81H ;读出秒
LCALL READ
MOV second,DS1302_DATA
;;公历设置程序;;;
;;;;;;;;;;;;;;;;;
SETG : SETB TR1
SETB ET1
MOV DS1302_ADDR,#8EH
MOV DS1302_DATA,#00H ;允许写1302
LCALL WRITE
MOV DS1302_ADDR,#80H
MOV DS1302_DATA,#80H ;1302停止振荡
LCALL WRITE
GWAIT: LCALL DISPLAY
JNB P1.1,GWAIT
SETG1: LCALL DISPLAY
JNB P1.1,SETG2
JNB P1.2,GADDYEAR
AJMP SETG1
GADDYEAR:MOV R7,66H ;年加一
LCALL ADD1
MOV 66H,A
CJNE A,#51H, GADDYEAR1
MOV 66H,#01H
GADDYEAR1:MOV DS1302_ADDR,#8CH ;年值送人1302
MOV DS1302_DATA,66H
LCALL WRITE
MOV R0,66H
LCALL DIVIDE ;年分离送显示缓存
MOV 4BH,R1
MOV 7BH,R1
MOV 4CH,R2
MOV 7CH,R2
WAITT1:LCALL DISPLAY
JNB P1.2,WAITT1
AJMP SETG1
SETG2: SETB 0AH ;调月时闪标志
GWAIT2: LCALL DISPLAY
JNB P1.1,GWAIT2
SETG3: LCALL DISPLAY
JNB P1.1,SETG4
JNB P1.2,GADDMONTH
AJMP SETG3
GADDMONTH:MOV R7,65H ;月加一
LCALL ADD1
MOV 65H,A
CJNE A,#13H,GADDMONTH1
MOV 65H,#01H
GADDMONTH1: MOV DS1302_ADDR,#88H ;月值送人1302
MOV DS1302_DATA,65H
LCALL WRITE
MOV R0,65H
LCALL DIVIDE ;月分离,送显示缓存
MOV 79H,R1
MOV 49H,R1
MOV 7AH,R2
MOV 4AH,R2
WAITT2: LCALL DISPLAY
JNB P1.2,WAITT2
AJMP SETG3
SETG4: SETB 0BH ;调日时闪标志
GWAIT4: LCALL DISPLAY
JNB P1.1,GWAIT4
SETG5: LCALL DISPLAY
JNB P1.1,SETG6
JNB P1.2,GADDDAY
AJMP SETG5
GADDDAY: MOV R7,63H ;日加一
LCALL ADD1
MOV 63H,A
CJNE A,#32H,GADDDAY1
MOV 63H,#01H
GADDDAY1: MOV DS1302_ADDR,#86H ;日值送人1302
MOV DS1302_DATA,63H
LCALL WRITE
MOV R0,63H
LCALL DIVIDE ;日分离,送显示缓存
MOV 76H,R1
MOV 46H,R1
MOV 77H,R2
MOV 47H,R2
WAITT3:LCALL DISPLAY
JNB P1.2,WAITT3
AJMP SETG5
SETG6: SETB 0CH ;调星期时闪标志
GWAIT6: LCALL DISPLAY
JNB P1.1,GWAIT6
SETG7: LCALL DISPLAY
JNB P1.1,SETG8
JNB P1.2,GADDWEEK
AJMP SETG7
GADDWEEK: MOV R7,64H ;星期加一
LCALL ADD1
MOV 64H,A
CJNE A,#08H,GADDWEEK1
MOV 64H,#01H
GADDWEEK1: MOV DS1302_ADDR,#8AH
MOV DS1302_DATA,64H ;星期值送人1302
LCALL WRITE
MOV R0,64H
LCALL DIVIDE ;星期值分离送显示缓存
MOV 48H,R1
MOV 78H,R1
WAITT4:LCALL DISPLAY
JNB P1.2,WAITT4
AJMP SETG7
SETG8: SETB 0DH ;调小时时闪标志
GWAIT8: LCALL DISPLAY
JNB P1.1,GWAIT8
SETG9: LCALL DISPLAY
JNB P1.1,SETG10
JNB P1.2,GADDHOUR
AJMP SETG9
GADDHOUR: MOV R7,62H ;小时加一
LCALL ADD1
MOV 62H,A
CJNE A,#24H,GADDHOUR1
MOV 62H,#00H
GADDHOUR1: MOV DS1302_ADDR,#84H ;小时值送人1302
MOV DS1302_DATA,62H
LCALL WRITE
MOV R0,62H
LCALL DIVIDE ;小时值分离送显示缓存
MOV 74H,R1
MOV 44H,R1
MOV 75H,R2
MOV 45H,R2
WAITT5: LCALL DISPLAY
JNB P1.2,WAITT5
AJMP SETG9
SETG10: SETB 0EH ;调分时候闪标志
GWAIT10: LCALL DISPLAY
JNB P1.1,GWAIT10
SETG11: LCALL DISPLAY
JNB P1.1,SETGOUT
JNB P1.2,GADDMINTUE
AJMP SETG11
GADDMINTUE: MOV R7,61H ;分钟加一
LCALL ADD1
MOV 61H,A
CJNE A,#60H,GADDMINTUE1
MOV 61H,#00H
GADDMINTUE1: MOV DS1302_ADDR,#82H ;分钟值送人1302
MOV DS1302_DATA,61H
LCALL WRITE
MOV R0,61H
LCALL DIVIDE ;分钟值分离送显示缓存
MOV 72H,R1
MOV 42H,R1
MOV 73H,R2
MOV 43H,R2
WAITT6: LCALL DISPLAY
JNB P1.2,WAITT6
AJMP SETG11
SETGOUT: LCALL DISPLAY
JNB P1.1,SETGOUT
LCALL GENGXIAN
MOV DS1302_ADDR,#80H
MOV DS1302_DATA,#00H ;1302晶振开始振荡
LCALL WRITE
MOV DS1302_ADDR,#8EH
MOV DS1302_DATA,#80H ;禁止写入1302
LCALL WRITE
CLR 08H
CLR 09H
CLR 0AH
CLR 0BH
CLR 0CH
CLR 0DH
CLR 0EH
CLR 0FH
CLR ET1 ;关闪中断
CLR TR1
LJMP MAIN1
以前我没有使用按键,走时是没有问题的,现在我想加入按键,让这个时钟可以实现更新调时的功能。
main中开始我之所以用:b0=0;是想加一个按键设置的子程序,我用的按键是矩阵键盘中的一部分,所以要将按键其中一脚置0。
至于写保护位开始打开,然后关闭,是为了走时的准确性。
:)
我现在的问题是,我加的用于调时的按键,按下之后数码管出现乱码现象。我就不明白了。