最近师傅交给实时时钟学习,不讲解不提示总之自己搞定,IIC协议早期学过,可是DS1307实在是头疼得很,不知是什么原因无法在数码管显示正确的时间,资料也查了很多还是没有头绪,已陷入死胡同无法走出,已经第3天了还是束手无策,实属无奈,望各位大师给予帮助不胜感激!!!
P0数码管显示,74HC595控制数码管位码。年,月,日,时,分,秒,星期。
单片机源程序如下:
#include <reg52.h>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit sda=P2^0;//;模拟I2C 数据传送位
sbit scl=P2^1;//;模拟I2C 时钟控制状态标志
sbit SER = P1^2; //数据输入
sbit SCK = P1^0; //串行移位时钟
sbit RCK = P1^1; //锁存器时钟
sbit tiao=P1^3; //调节键
sbit jia =P1^4; //按键+
sbit jian=P1^5; //按键-
uchar Hours,Minutes,Seconds,Year,Month,Date,Weeks;
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar data dis_buf[]={0,0,0xbf,0,0,0xbf,0,0};//显示缓存
void hc595(uchar Data)//74HC595的数据串入并出子程序
{
uchar i;
for(i=0;i<8;i++) //由高位到低位发送一个字节
{
Data<<=1; //左移一位,最高位溢出到位寄存器CY
SER=CY; //从位寄存器的进位标志位CY读取
SCK = 0; //串行移位
SCK = 1;
}
RCK = 0; //锁存
RCK = 1;
}
uchar Decimal_to_BCD(uchar temp)//十进制转换成BCD码
{
uchar a,b,c;
a=temp;
b=0;
while(a>=10)
{
a=a-10;
b=b+16;
c=a+b;
temp=c;
}
return temp;
}
uchar BCD_to_Decimal(uchar temp)//BCD码转换成十进制
{
uchar a,b,c;
a=temp;
b=0;
while(a>=16)
{
a=a-16;
b=b+10;
c=a+b;
temp=c;
}
return temp;
}
void delay_5us()//5us延时
{
_nop_();
_nop_();
_nop_();
}
void star_1307()//开始
{
sda=1;
delay_5us();//5us延时
scl=1;
delay_5us();//5us延时
sda=0;
delay_5us();//5us延时
}
void stop_1307()//停止
{
sda=0;
delay_5us();//5us延时
scl=1;
delay_5us();//5us延时
sda=1;
delay_5us();//5us延时
}
void ack_1307()//应答
{
uchar z=0;
while((sda==1)&&(z<50))z++;//条件判断, sda=1,则没有应答。如果没有应答则延时:z<50,z++;后返回
scl=0;
delay_5us();//5us延时
}
void write_1307(uchar slave_write_address,uchar byte_address,uchar data_data)//写一个数据
{
uchar temp,temp1,i,ii;
star_1307(); //开始
for(ii=0;ii<3;ii++)//根据 24CXX文档资料,和时序图,按顺序送:器件写地址,字节地址,数据
{
if(ii==0)
{
temp=slave_write_address;//送 器件写地址
temp1=slave_write_address;
}
else if(ii==1)
{
temp=byte_address;//送 字节地址
temp1=byte_address;
}
else if(ii==2)
{
temp=data_data;//送 数据
temp1=data_data;
}
for(i=0;i<8;i++)
{
scl=0;
delay_5us();//5us延时
temp=temp1;
temp=temp&0x80;//相 与 后,把不相关的位清零
if(temp==0x80)//根据前面 相 与 后,判断 temp是否等于0x80,是则该位为 1
sda=1;
else
sda=0;
delay_5us();//5us延时
scl=1;
delay_5us();//5us延时
scl=0;
delay_5us();//5us延时
temp1=temp1<<1;//向左移出1位
}
sda=1;
delay_5us();//5us延时
scl=1;
delay_5us();//5us延时
ack_1307();
}
stop_1307();//停止
}
uchar read_1307(uchar slave_write_address,uchar byte_address,uchar slave_read_address) //读一个数据
{
uchar temp,temp1,i,ii,x,data_data;
star_1307(); //开始
for(ii=0;ii<3;ii++) //根据 24CXX文档资料,和时序图,按顺序送:器件写地址,字节地址,器件读地址
{
if(ii==0)
{
temp=slave_write_address; //送 器件写地址
temp1=slave_write_address;
}
else if(ii==1)
{
temp=byte_address; //送 字节地址
temp1=byte_address;
}
else if(ii==2)
{
star_1307(); //开始
temp=slave_read_address; //送 器件读地址
temp1=slave_read_address;
}
for(i=0;i<8;i++) //开始读数据
{
scl=0;
delay_5us(); //5us延时
temp=temp1;
temp=temp&0x80; // 相 与 后,把不相关的位清零
if(temp==0x80) //根据前面 相 与 后,判断 temp是否等于0x80,是则该位为 1
sda=1;
else
sda=0;
delay_5us(); //5us延时
scl=1;
delay_5us(); //5us延时
scl=0;
delay_5us(); //5us延时
temp1=temp1<<1; //向左移出1位
}
sda=1;
delay_5us(); //5us延时
scl=1;
delay_5us(); //5us延时
ack_1307(); //应答
}
for(x=0;x<8;x++)
{
data_data=data_data<<1; //向左移入1位
sda=1;
delay_5us(); //5us延时
scl=0;
delay_5us(); //5us延时
scl=1;
delay_5us(); //5us延时
if(sda==1) //判断 数据线是否是高电平
data_data|=0x01; //把读到的数据 或 0X01
}
ack_1307(); //应答
stop_1307(); //停止
return data_data; //返回读到的数据
}
void init_1307() //初始化
{
Hours=23;
Minutes=14;
Seconds=11;
Year=17;
Month=11;
Date=24;
Weeks=5;
Seconds=Decimal_to_BCD(Seconds); //十进制转换成BCD码
Minutes=Decimal_to_BCD(Minutes); //十进制转换成BCD码
Hours=Decimal_to_BCD(Hours); //十进制转换成BCD码
Date=Decimal_to_BCD(Date); //十进制转换成BCD码
Year=Decimal_to_BCD(Year); //十进制转换成BCD码
Month=Decimal_to_BCD(Month); //十进制转换成BCD码
write_1307(0xd0,0x00,Seconds); //写入秒
write_1307(0xd0,0x01,Minutes); //写入分
write_1307(0xd0,0x02,Hours); //写入时
write_1307(0xd0,0x03,Weeks); //写入星期
write_1307(0xd0,0x04,Date); //写入日期
write_1307(0xd0,0x05,Month); //写入月
write_1307(0xd0,0x06,Year); //写入年
}
void read_time_1307()
{
Seconds=read_1307(0xd0,0x00,0xd1); //读秒
Seconds=BCD_to_Decimal(Seconds); //BCD码转换成十进制
Minutes=read_1307(0xd0,0x01,0xd1); //读分
Minutes=BCD_to_Decimal(Minutes); //BCD码转换成十进制
Hours=read_1307(0xd0,0x02,0xd1); //读时
Hours=BCD_to_Decimal(Hours); //BCD码转换成十进制
Year=read_1307(0xd0,0x06,0xd1); //读年
Year=BCD_to_Decimal(Year); //BCD码转换成十进制
Date=read_1307(0xd0,0x04,0xd1); //读日
Date=BCD_to_Decimal(Date); //BCD码转换成十进制
Month=read_1307(0xd0,0x05,0xd1); //读月
Month=BCD_to_Decimal(Month); //BCD码转换成十进制
Weeks=read_1307(0xd0,0x03,0xd1); //读周
}
|