📄 pcf8563t.c
字号:
/*
***********************************************************
HFUT-TI DSP 实验室
hfut-crazy
QQ:251759752
***********************************************************
*/
#include"includes.h"
extern INT8U TIMER_8563[10];
INT8U old_minute,new_minute;
/*
***********************************************
*** This routine will send the I2C Start Bit ***
SCL:
---|
SDA:
---|
***********************************************
*/
void I2C_Start (void) //I2C发送开始位
{
DDRE |=((1<<PE4)|(1<<PE5)); //将PA0数据端口(SDA),PA1时钟端口(SCL)设为输出
Delay_Us(0);
DATE_CLK_set; //将时钟端口(SCL)设为高
Delay_Us(DELAYCNT);
DATE_DT_set; //将时钟端口(SCL)设为高
Delay_Us(DELAYCNT);
DATE_DT_clr; //将数据端口(SDA)设为高
Delay_Us(DELAYCNT);
DATE_CLK_clr; //将数据端口(SDA)设为高
Delay_Us(DELAYCNT);
}
/*
***********************************************
*** This routine will send the I2C Stop Bit ***
SCL:
_|--
SDA:
|____|-
***********************************************
*/
void I2C_Stop (void) //I2C发送停止位
{
DDRE|=((1<<PE4)|(1<<PE5)); //将PA0数据端口(SDA),PA1时钟端口(SCL)设为输出
Delay_Us(0);
DATE_DT_clr; //将数据端口(SDA)设为低
Delay_Us(DELAYCNT);
DATE_CLK_set;
Delay_Us(DELAYCNT);
DATE_DT_set; //将数据端口(SDA)设为高
Delay_Us(DELAYCNT);
}
/********************************************
内部函数,输出ACK ,每个字节传输完成,输出ack=0,结束读书据,ack=1;
********************************************/
INT8U WriteACK(void)
{
INT8U ACK;
DDRE|=((1<<PE4)|(1<<PE5));
Delay_Us(0);
DATE_DT_set;
Delay_Us(DELAYCNT);
DATE_CLK_set;
Delay_Us(DELAYCNT);
DDRE&=~(1<<PE5);
Delay_Us(0);
if(PINE&0x20)ACK = 1;
else ACK = 0;
DATE_CLK_clr;
Delay_Us(DELAYCNT);
return (ACK);
}
// *********************************************************************** //
// *** 发送完毕检查校验位,有校验位返回1,无返回0 *** //
// *********************************************************************** //
unsigned char I2C_Ackn(void)
{
unsigned char errtime=255;
DDRE|=(1<<PE4);
DDRE&=~(1<<PE5); // 设置数据口(SDA)为输入
Delay_Us(0);
DATE_CLK_clr;
asm("nop");
DATE_CLK_set; //将数据端口(SDA)设为高
Delay_Us(DELAYCNT);
while(PINE&0x20)
{
errtime--;
if (!errtime) //errtime=0,没接收到
{
I2C_Stop();
return 0x00;
}
}
DATE_CLK_clr; // 将时钟端口(SCL)设为低
Delay_Us(DELAYCNT);
return 0x01; //true
}
// ******************************************************** //
// *** This routine will write a byte to the I2C device *** //
// ******************************************************** //
void Write_I2C_Byte(unsigned char byte) //写一个字节到I2C设备
{
unsigned char i;
DDRE|=((1<<PE5)|(1<<PE4));
Delay_Us(0);
for (i = 0; i < 8; i++) //传送8位数据
{
DATE_CLK_clr; //将时钟端口(SCL)设为低
Delay_Us(DELAYCNT);
if((byte & 0x80)) DATE_DT_set; // 设置 SDA 位
else DATE_DT_clr; // 清除 SDA 位
Delay_Us(DELAYCNT);
DATE_CLK_set; //将时钟端口(SCL)设为高
Delay_Us(DELAYCNT);
byte = byte << 1;
}
DATE_CLK_clr;
Delay_Us(DELAYCNT);
I2C_Ackn();
Delay_Us(DELAYCNT*10);
return;
}
// ********************************************************* //
// *** This routine will read a byte from the I2C device *** //
// ********************************************************* //
unsigned char Read_I2C_Byte(void) //读取I2C设备的数据
{
unsigned char i,buff = 0;
//Delay_Us(2);
DDRE|=(1<<PE4); //PA1为时钟,输出
DDRE&=~(1<<PE5);
Delay_Us(0);
for (i = 0; i < 8; i++)
{
DATE_CLK_clr; //将时钟端口(SCL)设为高
Delay_Us(DELAYCNT);
DATE_CLK_set; //将时钟端口(SCL)设为高
Delay_Us(DELAYCNT);
buff = (buff << 1);
if ( PINE& 0x20 )buff|=0x01;
}
DDRE|=((1<<PE5)|(1<<PE4));//读完毕过后应答一个高电平
Delay_Us(0);
DATE_CLK_clr;
Delay_Us(DELAYCNT*2);
DATE_DT_set;
Delay_Us(DELAYCNT);
DATE_CLK_set; //将时钟端口(SCL)设为高
//DATE_DT_clr;
Delay_Us(DELAYCNT*10);
return buff; // 返回读取值
/*
unsigned char a;
unsigned char b=0;
for(a=0;a<8;a++)
{
SCL = 1;
b=b<<1;
if (SDA==1)
b=b|0x01; //按位或
SCL = 0;
}
return (b);
*/
}
//读8563寄存器
unsigned char rtc_read(INT8U devRaddr,INT8U devWaddr,unsigned char address)
{
unsigned char d;
I2C_Start();
Write_I2C_Byte(devWaddr);
Write_I2C_Byte(address);
I2C_Start();
Write_I2C_Byte(devRaddr);
d=Read_I2C_Byte();
//d>>=1;
I2C_Stop();
Delay_Us(DELAYCNT*150);
return d;
}
////////////////////////////////////////////////////////////////////////////////
//写8563寄存器
void rtc_write(unsigned char devaddr,unsigned char address,unsigned char data)
{
I2C_Start();
Write_I2C_Byte(devaddr);
Write_I2C_Byte(address);
Write_I2C_Byte(data);
I2C_Stop();
Delay_Us(DELAYCNT*150);
return;
}
////////////////////////////////////////////////////////////////////////////////
void rtc_start(void)
{
rtc_write(PCF8563WADDR,0,0);
}
////////////////////////////////////////////////////////////////////////////////
void rtc_stop(void)
{
rtc_write(PCF8563WADDR,0,0x20);
}
void GetPCF8563(unsigned char *TIMER_8563)
{
CLI();
* TIMER_8563 =(rtc_read(PCF8563RADDR,PCF8563WADDR,2)&0x7f); //寄存器0x02为秒寄存器
*(TIMER_8563+1)=(rtc_read(PCF8563RADDR,PCF8563WADDR,3)&0x7f); //寄存器0x03为分寄存器
*(TIMER_8563+2)=(rtc_read(PCF8563RADDR,PCF8563WADDR,4)&0x3f); //寄存器0x04为时寄存器
*(TIMER_8563+3)=(rtc_read(PCF8563RADDR,PCF8563WADDR,5)&0x3f); //寄存器0x05为天寄存器
*(TIMER_8563+4)=(rtc_read(PCF8563RADDR,PCF8563WADDR,7)&0x1f); //寄存器0x07为月寄存器
*(TIMER_8563+5)=(rtc_read(PCF8563RADDR,PCF8563WADDR,8)); //寄存器0x08为年寄存器
SEI();
// return TIMER_8563;
}
unsigned char get_second(void) //获得当前秒数
{
unsigned i,j;
i=(rtc_read(PCF8563RADDR,PCF8563WADDR,2)&0x7f); //寄存器0x02为秒寄存器
j=(i&0x0f)+(i>>4)*10;
return j;
}
////////////////////////////////////////////////////////////////////////////////
void SetPCF8563(unsigned char adds,unsigned char data)
{
CLI();
rtc_stop();
rtc_write(PCF8563WADDR,adds,data);
rtc_start();
SEI();
}
//设置时间 (**年/**月/**日 **时:**分)
void set8563(void)
{
SetPCF8563(8,0x08); //设置年
SetPCF8563(7,0x07); //设置月
SetPCF8563(5,0x06); //设置日
SetPCF8563(4,0x06); //设置时
SetPCF8563(3,0x06); //设置分
rtc_write(PCF8563WADDR,0x0d,0xf2);
rtc_write(PCF8563WADDR,0x00,0x00);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -