最近師傅交給實時時鐘學習,不講解不提示總之自己搞定,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); //讀周
}
|