51单片机对DS1302(实时时钟芯片)的仿真

51单片机对DS1302(实时时钟芯片)的仿真

  • 仿真效果
    在这里插入图片描述
  • 源代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <reg51.h>
#include <intrins.h> //因为要调用nop函数,所以添加了这个库NOP,延时作用
sbit RS=P3^0; //NOP指令本身的含义是空操作,即此时CPU什么也不做,仅仅是等待,直到下一个机器周期的到来。
sbit RW=P3^1;
sbit E=P3^2;
sbit T_RST=P3^3;
sbit T_CLK=P3^4;
sbit T_IO=P3^5;
unsigned char datechar[]={"DATE:"};
unsigned char timechar[]={"TIME:"};
unsigned char datebuffer[10]={0x32,0x30,0,0,0x2d,0,0,0x2d,0,0};//0x32表示2,0x30表示0,0x2d表示—
unsigned char timebuffer[8]={0,0,0x3a,0,0,0x3a,0,0};//0x3a表示:
unsigned char weekbuffer={0x30};

void WriteB(unsigned char dat)//单字节写
{
unsigned char i;
for(i=8; i>0; i--)
{
T_IO=dat&0x01;
T_CLK = 1;
T_CLK = 0;
dat = dat >> 1;
}
}

unsigned char ReadB(void) //单字节读
{
unsigned char i,readdat=0;
for(i=8; i>0; i--)
{
readdat=readdat>>1;
if(T_IO)
{
readdat|=0x80;
}
T_CLK = 1;
T_CLK = 0;
}
return(readdat);
}

void W1302(unsigned char address,unsigned char dat)
{
T_RST = 0;
T_CLK = 0;
\_nop\_();
\_nop\_();
T_RST = 1;
\_nop\_();
\_nop\_();
WriteB(address);
WriteB(dat);
T_CLK = 1;
T_RST =0;
}

unsigned char R1302(unsigned char address)//上面的是DS1302的函数
{
unsigned char dat=0;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
WriteB(address);
dat = ReadB();
T_CLK = 1;
T_RST =0;
return(dat);
}

void delay(unsigned int n)//延时函数
{
unsigned i=0,j=0;
for(i=0;i<n;i++)
{
for(j=0;j<120;j++);
}
}
void writedat(unsigned char dat)//写数据函数lcd的下面这些函数
{
RS=1; // RS:数据/命令选择端
RW=0; // R/W :读/写选择端
E=0; // 使能端:下降沿有效
P2=dat;
delay(5);
E=1;
E=0;
}

void writecom(unsigned char com)//写命令函数
{
RS=0; // RS:数据/命令选择端
RW=0; // R/W :读/写选择端
E=0; //使能端:下降沿有效
P2=com;
delay(5);
E=1;
E=0;
}
void initlcd()//初始化LCD1602
{
writecom(0x38); //0x38;设置16×2显示
writecom(0x0c); //0x0C:设置开显示,不显示光标
writecom(0x06); //0x06:写一个字符后地址指针加1
writecom(0x01); //0x01:显示清0,数据指针清0
}


void display()//显示函数
{
int i=0,temp=0;
temp=R1302(0x8d); //读年
datebuffer[2]=0x30+temp/16;
datebuffer[3]=0x30+temp%16;

temp=R1302(0x8b); //读星期
weekbuffer=0x30+temp;

temp=R1302(0x89); //读月
datebuffer[5]=0x30+temp/16;
datebuffer[6]=0x30+temp%16;

temp=R1302(0x87); //读日
datebuffer[8]=0x30+temp/16;
datebuffer[9]=0x30+temp%16;

temp=R1302(0x85); //读时
temp=temp&0x7f;
timebuffer[0]=0x30+temp/16;
timebuffer[1]=0x30+temp%16;

temp=R1302(0x83); //读分
timebuffer[3]=0x30+temp/16;
timebuffer[4]=0x30+temp%16;

temp=R1302(0x81); //读秒
temp=temp&0x7f;
timebuffer[6]=0x30+temp/16;
timebuffer[7]=0x30+temp%16;

writecom(0x80); //0x80:LCD第一行的起始地址
for(i=0;i<5;i++)
{
writedat(datechar[i]);
}
writecom(0xc0);
for(i=0;i<5;i++)
{
writedat(timechar[i]);
}

writecom(0x86);//显示日历
for(i=0;i<10;i++)
{
writedat(datebuffer[i]);
}
writecom(0xc6);//显示时间

for(i=0;i<8;i++)
{
writedat(timebuffer[i]);
}
writedat(' ');
writedat(weekbuffer);//显示星期
}


void main()
{
initlcd();
W1302(0x8e,0); //打开写保护
W1302(0x8c,0x21);//打开年,BCD码
W1302(0x8a,0x04);//写入星期
W1302(0x88,0x07);//写入月
W1302(0x86,0x15);//写入日
W1302(0x84,0x22);//写入时
W1302(0x82,0x42);//写入分
W1302(0x80,0x30);//写入秒
W1302(0x8e,0x80);//关闭写保护
while(1)
{
display();
}
}