📄 pcf8563t.c
字号:
#include <reg52.h>
#include<intrins.h>
sbit SDA=P1^1;
sbit SCL=P1^0;
sbit de=P1^2;
sbit dd=P1^5;
#define uchar unsigned char
#define uint unsigned int
uchar pp=0;
void send_8bit(uchar ch) ;
void dog()
{
dd=1;
_nop_();
_nop_();
dd=0;
}
void init_uart(void) //定时器2发生波特率
{
SCON= 0xd0; //SCON: serail mode 3, 8-bit UART, enable ucvr
T2CON= 0x34; //Baud:1200 fosc=11.059MHz
RCAP2H = 0Xfe;
RCAP2L = 0xe0;
TH2 =0Xfe;
TL2 = 0xe0;
ES = 1; //串行口中断允许
// PS=1; //中断优先最高
PT0=0;
PT1=0;
EX1=1;
IT1=1; //边沿触发
EA=1; //总中断允许
}
void send_8bit(uchar ch)
{
de=1; //485允许发
SBUF=ch;
while(TI==0){;}
TI = 0;
}
void flash_delay(uint n)
{
uint i;
for(i=0;i<n;i++);
}
void start_i2c(void)
{
SCL=1;_nop_();
SDA=1;_nop_();
SDA=0;_nop_();
SCL=1;_nop_();
}
/*-----------------------------------------------
函数说明:停止位
-----------------------------------------------*/
void stop_i2c(void)
{
SDA=0;_nop_();
SCL=1;_nop_();
SDA=1;_nop_();
SCL=1;_nop_();/////////////////////////////////////////////////////////////////////
}
/*-----------------------------------------------
函数说明:应答函数
-----------------------------------------------*/
void ack_i2c(void)
{
SDA=1;_nop_();
SCL=0;_nop_();
SCL=1;_nop_();
SCL=0;_nop_();
}
/*-----------------------------------------------
函数说明:无需应答位,在读程序中用到
-----------------------------------------------*/
void no_ack(void)
{
SDA=1;_nop_();
SCL=1;_nop_();
SCL=0;_nop_();
}
/*-----------------------------------------------
函数说明:写一个字节(8位)数据
-----------------------------------------------*/
void write_8bit(uchar ch)
{
uchar i;
SCL=0;_nop_();
for(i=0;i<8;i++)
{
SDA=(bit)(ch&0x80);_nop_();
ch<<=1;
SCL=1;_nop_();
SCL=0;_nop_();
}
}
/*----------------------------------------------
函数说明:(字节读)
-----------------------------------------------*/
uchar read_8bit(uchar addr )
{
uchar temp;
uchar i;
start_i2c();
write_8bit(0xA2); //8563器件写地址
ack_i2c();
write_8bit(addr);
ack_i2c();
start_i2c();
write_8bit(0xA3); //8563器件读地址
ack_i2c();
for(i=0;i<9;i++)
{
temp=temp|SDA;
if(i<8)
{
temp=temp<<1;
}
SCL=0;_nop_();
SCL=1;_nop_();
}
if(addr!=0x08) //除最后一个字节外,其他都要从MASTER发应答。
{ack_i2c();}
no_ack();
stop_i2c();
return(temp);
}
void write_one(uchar addr,uchar ddata)
{
start_i2c();
write_8bit(0xA2);
ack_i2c();
write_8bit(addr);
ack_i2c();
write_8bit(ddata);
ack_i2c();
stop_i2c();
}
/*-----------------------------------------------
函数说明:修改时间:年,月,日,星期,时(24小时制),分,秒
-----------------------------------------------*/
void wt_time(uchar *time)
{
uchar i;
uchar temp[7];
temp[6]=time[0]; //年
temp[5]=time[1]; //月
temp[3]=time[2]; //日
temp[4]=time[3]; //星期
temp[2]=time[4]; //时
temp[1]=time[5]; //分
temp[0]=time[6]; //秒
start_i2c();
write_8bit(0xA2);
ack_i2c();
write_8bit(0x02);
ack_i2c();
for(i=0;i<7;i++)
{
write_8bit(temp[i]);
ack_i2c();
//addrl=addrl+1; //页写不须软件累加地址,器件按存入字节数自动累加地址
}
stop_i2c();
}
/*-----------------------------------------------
读时间
-----------------------------------------------------*/
void rd_time(uchar *time)
{
int i;
uchar addr=0x02;
uchar temp;
uchar temp2;
for(i=0;i<7;i++)
{
temp=read_8bit(addr);
if(i==0) //去掉无效位 //秒
{temp2=temp&0x7f; time[6]=temp2;}
if(i==1) //去掉无效位 //分
{temp2=temp&0x7f; time[5]=temp2;}
if(i==2) //时
{temp2=temp&0x3f; time[4]=temp2;}
if(i==3) //日
{temp2=temp&0x3f; time[2]=temp2; }
if(i==4) //星期
{temp2=temp&0x07; time[3]=temp2;}
if(i==5) //月
{temp2=temp&0x1f; time[1]=temp2;}
if(i==6) //年
{temp2=temp; time[0]=temp2;}
flash_delay(50);
addr=addr+1; //页读须软件累加地址
}
}
/*--------------------------------------------------------------------------------
函数说明:向8563寄存器指定地址写数据
addr是寄存器地址,ddata是要送的数值。
---------------------------------------------------------------------------------*/
void set_8563(uchar addr,uchar ddata)
{
start_i2c();
write_8bit(0xA2);
ack_i2c();
write_8bit(addr);
ack_i2c();
write_8bit(ddata);
ack_i2c();
stop_i2c();
}
/**--------------------------------------------------------------------------------
函数说明:设置报警闹钟。
addr:报警寄存器地址,具体数值
09h 分钟报警32:没小时的第32分钟报----1
0Ah 小时报警17:每天的17点报警--------2
0BH 日报警21:每月的21号报警----------3
0CH 星期报警3:没星期的星期3报警------4
---------------------------------------------------------------------------------*/
void set_timeAla(uchar num,uchar count)
{
uchar temp;
temp=read_8bit(0x01); //读出控制寄存器2中原有数据
temp=temp|0x02;
write_one(0x01,temp);
if(num==1) { set_8563(0x09,count);}
if(num==2) { set_8563(0x0a,count);}
if(num==3) { set_8563(0x0b,count);}
if(num==4) { set_8563(0x0c,count);}
}
/**--------------------------------------------------------------------------------
函数说明:秒中断设置
---------------------------------------------------------------------------------*/
void set_secAla(uchar num)
{
uchar temp;
temp=read_8bit(0x01); //读出控制寄存器2中原有数据
temp=temp|0x11;
write_one(0x01,temp);
set_8563(0x0e,0x81); //脉冲中断模式,不需要清楚TF位
if(num==1){set_8563(0x0f,64); } //1秒中断
if(num==2){set_8563(0x0f,128); } //2秒中断
if(num==3){set_8563(0x0f,192); } //3秒中断
if(num==4){set_8563(0x0f,255); } //4秒中断
}
/**--------------------------------------------------------------------------------
函数说明:清除所有报警设置。
---------------------------------------------------------------------------------*/
void clr_timeAla(void)
{
set_8563(0x01,0x00); //关中断
set_8563(0x09,0x80);
set_8563(0x0A,0x80);
set_8563(0x0B,0x80);
set_8563(0x0C,0x80);
// SetPCF8563(0x0D,0x00);
// SetPCF8563(0x0E,0x03);
}
/**--------------------------------------------------------------------------------
函数说明:清除报警标志位AF和倒计时标志位TF
---------------------------------------------------------------------------------*/
void clr_AF_TF(void)
{
uchar temp;
temp=read_8bit(0x01); //读出控制寄存器2中原有数据
temp=temp&0x13;
write_one(0x01,temp);
}
void intt() interrupt 2
{
uchar time[7];
IE1=0;
clr_AF_TF();
send_8bit(0xff);
set_secAla(1);
rd_time(time);
if(time[5]==0x00)
{
pp++;
}
}
///////////////////////////////////////
void main()
{
uchar time[7];
uchar k[7]={0x04,0X01,0x30,0x07,0x21,0x50,0x00};
wt_time(k) ;
init_uart();
set_secAla(1); //设置秒报警
set_timeAla(1,0x20); //没小时的第20分钟报警
while(1)
{
dog();
rd_time(time); //读取时间
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -