#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCL = P3^6; //定义时钟信号接口
sbit IO = P3^4; //定义数据信号接口
sbit RST = P3^5; //定义复位信号接口
sbit ACC0 = ACC^0; //ACC寄存器的最低位
sbit ACC7 = ACC^7; //ACC寄存器的最高位
uchar ds1,ds2,time;
uchar curttime[7];
//数码管显示字符表
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
//初始化时间表
uchar code InitTime[] = {0x01,0x20,0x02,0x16,0x10,0x06,0x10,
};
//段选表
uchar code tabwcon[] ={0x07,0x06,0x05,0x04,
0x03,0x02,0x01,0x00};
//读取时间的地址表
uchar code read_time_address[7]={
0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
//写入时间的地址表
code uchar write_rtc_address[7]={
0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
//数码管显示延时函数
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
{
for(y=190;y>0;y--);
{
}
}
}
//发送一个字节
void SendByte(uchar date)
{
uchar i;
ACC = date; //将date变量存入ACC中
for (i = 8; i >0; i--)
{
IO = ACC0;
SCL = 1; //时钟信号线拉高发送一位数据
SCL = 0; //发送完一位数据后 拉低时钟线
ACC = ACC>>1; //将ACC的D1位移到D0位准备发送
}
}
//接收一个字节
uchar AccByte(void)
{
uchar i;
for (i = 8; i >0; i--)
{
ACC = ACC>>1; //向右一位准备接受总线上的数据
ACC7 = IO; //从总线上接收数据并存到ACC7中
SCL = 1; //从总线上接收到一位数据
SCL = 0; //接收完一位数据后 拉低时钟线
}
return (ACC); //返回接收到的数据 ACC
}
//写一个字节 注意与读一个字节的区别
void WriteByte(uchar add, uchar date)
{
RST = 0; SCL = 0; RST = 1; //初始化 开启丛机内部定时器电路
SendByte(add); //发送将写入数据的地址
SendByte(date); //向预定地址写入数据 //拉高时钟线 为下一次读取的初始化
SCL = 1; RST = 0; //屏蔽任何输入输出 释放总线
}
//读一个字节 注意与发一个字节的区别
uchar ReadByte(uchar add)
{
uchar date;
RST = 0; SCL = 0; RST = 1; //初始化 开启丛机内部定时器电路
SendByte(add); //发送将读数据的地址
date = AccByte(); //将接收到的数据赋予rdate //拉高时钟线 为下一次读取的初始化
SCL = 1; RST = 0; //屏蔽任何输入输出
return (date); //返回读到的数据
}
//时钟寄存器多字节写
/*void BurstW1302T(uchar *p) //P寄存器地址指针
{
uint i;
WriteByte(0X8e,0x00); //写保护控制命令 WP = 0(开启写命令) 写操作
RST = 0; SCL = 0; RST = 1; //初始化
SendByte(0xbe); //时钟多字节写命令(时钟突发访问)
// 向地址逐一发送数据
for (i = 0; i < 8; i++)
{
SendByte(*p);
p++;
}
SCL = 1; //拉高时钟线 为下一次读取的初始化
RST = 0; //主机释放总线
}
//时钟寄存器多字节读 读数据的时候不用写保护控制命令
void BurstR1302T(uchar *p)
{
uint i;
RST = 0; SCL = 0; RST = 1; //初始化
SendByte(0xbf); //时钟多字节读命令(时钟突发访问)
for (i = 0; i < 8; i++)
{
*p = AccByte(); //接收数据并将其存到P指针所指向的地址
p++;
}
SCL = 1; RST = 0; //同上
}
//RAM寄存器多字节写(道理同时钟数据多字节读写一样)
void BurstW1302R(uchar *p)
{
uint i;
WriteByte(0X8e,0x00);
RST = 0; SCL = 0; RST = 1;
SendByte(0xfe); //寄存器突发访问(写)
for (i = 0; i < 32; i++)
{
SendByte(*p);
p++;
}
SCL = 1; RST = 0;
}
//RAM寄存器多字节读 (道理同时钟数据多字节读写一样)
void BurstR1302R(uchar *p)
{
uint i;
RST = 0; SCL = 0; RST = 1;
SendByte(0xff); //寄存器突发访问(读)
for (i = 0; i < 32; i++)
{
*p = AccByte();
p++;
}
SCL = 1; RST = 0;
} */
//设置初始化时间 注意区分于多字节写的不同
void TimeSet(uchar *p)
{
uchar i;
uchar add = 0x80; //写入数据的初始地址
WriteByte(0x8e,0x00); //写保护控制 WP=0,允许写入数据
for (i = 0; i < 7; i++)
{
WriteByte(add,*p);
p++;
add += 2;
}
WriteByte(0x8e,0x80); //写保护控制 WP=1,禁止写入数据
}
//读取时间 并将其存到数组中
void GetTime(uchar curttime[])
{
uchar i;
uchar add = 0x81; //读取数据的初始地址
for (i = 0; i < 8; i++)
{
curttime[i] = ReadByte(add); //在此地址读数据并存入数组中
add += 2;
}
}
//每隔5秒轮流显示时间和日期
void display()
{
uchar i,j;
//显示时间
if (time <= 100)
{
for (i = 0; i < 4; i++)
{
if(j == 8) { j = 0; }
ds1 = curttime[i]&0x0f;
ds2 = (curttime[i]&0xf0)>>4;
P2 = tabwcon[j];
P0 = table[ds1];
j++;
delay(1);
P2 = tabwcon[j];
P0 = table[ds2];
j++;
delay(1);
}
}
//显示日期
else if(time>=100 && time<=200)
{
for (i = 4; i < 7; i++)
{
if(j == 6) { j = 0; }
ds1 = curttime[i]&0x0f;
ds2 = (curttime[i]&0xf0)>>4;
P2 = tabwcon[j];
P0 = table[ds1];
j++;
delay(1);
P2 = tabwcon[j];
P0 = table[ds2];
j++;
delay(1);
}
}
else time = 0; //清零
}
void init()
{
TMOD = 0x01; //设置定时器0工作方式
TH0 = (65536-50000)/265;
TL0 = (65536-50000)%265;
IE = 0x82;
TR0 = 1;
}
void main()
{
init();
TimeSet(InitTime);
while(1)
{
GetTime(curttime);
display();
}
}
void timer() interrupt 1
{
TH0 = (65536-50000)/265;
TL0 = (65536-50000)%265;
time++;
}