📄 8583.c
字号:
/******************************************************************
* copyright 2004 *
*******************************************************************
文件名称: 8583.c
文件版本: 1.00
创建人:
创建日期: 2004.05.18
功能描述: 8583日历时钟驱动
相关硬件: AT89S52,11.0592M晶震
*******************************************************************/
#include <8583.h>
uchar year_base;
uchar year_buf;
/*+++++++++++++++++++++++++++++++++++++++++++++++++
i2cstart:发出i2c其始信号
++++++++++++++++++++++++++++++++++++++++++++++++++*/
static void i2cstart(void)
{
_nop_();
scl=1;
somenop( );
sda=0;
somenop( );
scl=0;
somenop( );
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++
i2cstop: 发出i2c总线结束信号
+++++++++++++++++++++++++++++++++++++++++++++++++++*/
static void i2cstop(void)
{
sda=0;
_nop_( );
scl=1;
somenop( );
sda=1;
somenop( );
scl=0;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++
i2cinit: i2c总线初始化程序
++++++++++++++++++++++++++++++++++++++++++++++++++*/
static void i2cinit ( void )
{
scl=0;
somenop( );
i2cstop( );
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++
i2cclock:发送总线时钟信号,并返回时钟高电平期间SDA的状态,
可用于发送也可用于接收
+++++++++++++++++++++++++++++++++++++++++++++++++++*/
static bit i2cclock (void)
{
bit sample;
somenop( );
scl=1;
_nop_( );_nop_( );_nop_( );
sample=sda;
_nop_( );_nop_( );
scl=0;
somenop( );
return(sample);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
i2csendbyte:向I2C总线发送一个字节,并请求应答,若收到应答,则
返回1,否则返回0
++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static bit i2csendbyte(uchar i2cdata)
{
register uchar i;
for (i=0;i<8;i++)
{
sda=(bit)(i2cdata&0x80);
i2cdata<<=1;
i2cclock( );
}
sda=1;
return (~i2cclock( ));
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
i2creceivebyte:从总线接收一个字节,并返回该字节,不回送应答信号
主函数调用本函数前应保证sda为1
++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static uchar i2creceivebyte(void)
{
uchar i2cdata=0;
register uchar i;
for (i=0;i<8;i++)
{
i2cdata<<=1;
if (i2cclock( )) i2cdata++;
}
return (i2cdata);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++
i2csendack:向i2c总线发送应答信号ack
++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static void i2csendack (void)
{
sda=0;
i2cclock( );
sda=1;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
i2csendnotack:发送非应答信号到i2c总线
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static void i2csendnotack(void)
{
sda=1;
i2cclock( );
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++
wr8583:对8583ram单元的读写操作
参数:addr: 指定的RAM单元地址
buf:读写数据缓冲区首地址
num:从addr开始读写的数据字节个数
wr: 读写标志,1为主机读,0为主机写
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void wr8583(uchar addr,uchar buf[ ],uchar num,uchar wr) reentrant
{
uchar index; //发送字节索引
EA=0; //发送期间禁止中断,防止干扰
i2cinit( );
i2cstart( );
i2csendbyte (0xa0); //发送 8583写地址
i2csendbyte(addr); //发送要操作的RAM地址
if (wr==0) //主机写数据
{
for (index=0;index<num;index++)
{
i2csendbyte(buf[index]);
}
}
else if (wr==1)
{ //主机读数据
i2cstart ( ); //发送重复起始信号
i2csendbyte(0xa1); //发8583读地址
for (index=0;index<num-1;index++)
{
sda=1; //写之前将数据线置高
buf[index]=i2creceivebyte( );
i2csendack( ); //发送应答信号
}
buf[index]=i2creceivebyte( );//读最后一个数据
i2csendnotack( ); //发送非应答信号
}
i2cstop( );
EA=1;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++
fill8583:对8583RAM单元添丛固定的值
参数:
filler: 要填充的字节内容
startaddr: 指定的RAM单元首地址
fillnum : 从startaddr开始填充的字节个数
+++++++++++++++++++++++++++++++++++++++++++++++++++*/
void fill8583(uchar filler,uchar startadr,uchar fillnum)
{
uchar index;
EA=0;
i2cinit( );
i2cstart( );
i2csendbyte(0xa0);
i2csendbyte(startadr);
for (index=0;index<fillnum;index++)
{
i2csendbyte(filler);
}
i2cstop( );
EA=1;
}
//该程序仅适用于本程序中计算bcd年加法
uchar yearbcdadd(uchar data1,uchar data2)
{
uchar temp;
temp=data1+data2;
if(temp&0x0f>=0x0a) temp=(temp&0xf0)+(temp&0x0f-0x0a)+0x10;
return temp;
}
/*******************************************************************
* 函数名称: read_daytime
* 创建人员: gloria
* 函数版本: 1.00
* 创建日期: 2004.5.19
* 功能描述: 读取8583内的日期和时间
* 入口参数: daytime 存放读出的日期和时间的结构指针
* buf 暂时存放读出的日期和时间的缓冲区首址
* 返回值: 无
* 修改记录:
*******************************************************************/
/*+++++++++++++++++++++++++++++++++++++++++
read_time:读出8583时间数据
+++++++++++++++++++++++++++++++++++++++++++*/
void read_daytime(struct DAYTIME *daytime,uchar *buf )
{
uchar temp;
fill8583(0x40,0x00,1); //保持和捕捉数据,?准备读数据
wr8583(0x02,buf,5,1); //读时分秒年月日各寄存器
fill8583(0x00,0x00,1); //计数状态
daytime->second=buf[0];
daytime->minute=buf[1];
daytime->hour=buf[2];
temp=buf[3];
daytime->day=temp&0x3f;
temp=buf[3];
daytime->yearl=(temp&0xc0)>>6;
temp=buf[4];
daytime->month=temp&0x1f;
daytime->week=(buf[4]&0xe0)>>5;
wr8583(0x0c,buf,1,1); //年低位缓冲
year_buf=buf[0];
// daytime->year_base=buf[1];
if(daytime->yearl<year_buf)
{
//4位年进位
//计算年基准,更新年基准和年缓冲单元
year_base=yearbcdadd(year_base,4);
year_buf=daytime->yearl;
//将年基准和年低位缓冲存入8583中
buf[0]=year_base;
buf[1]=year_buf;
wr8583(0x0b,buf,2,0);
}
else if(daytime->yearl>year_buf)
{
//年进位
year_buf=daytime->yearl;
buf[0]=year_buf;
wr8583(0x0c,buf,1,0);
}
//相等,不作处理
daytime->yearl=yearbcdadd(year_base,daytime->yearl); //计算年低位值
return;
}
//设置8583数据
void set_8583(uchar *buf )
{
fill8583(0x80,0x00,1); //停止计数
wr8583(0x01,buf,6,0);
fill8583(0x00,0x00,1); //计数状态
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -