📄 时钟ds1302.c
字号:
/********************************************************************
* 文件名 : DS1302.c
* 描述 : 该文件实现用DS1302来实现日历和时钟功能,并在数码管上显示出来。
按P3^2 和 P3^4分别可以选择显示时间和日期。
* 创建人 : 东流,2009年4月9日
* 版本号 : 2.0
* 技术支持论坛:www.zidh.com/bbs(请进入“赞助商板块”中的“东流电子工作室”)
* 感谢“中国自动化资讯网”对本工作室的大力支持。
***********************************************************************/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit ACC0 = ACC^0; //这里声明了累加器的位操作
sbit ACC7 = ACC^7;
sbit P3_2 = P3^2; //按P3.2键显示日期
sbit P3_4 = P3^4; //按P3.4键显示时间
sbit T_CLK = P1^2; //实时时钟时钟线引脚
sbit T_IO = P1^3; //实时时钟数据线引脚
sbit T_RST = P1^4; //实时时钟复位线引脚
uchar code table[11] = {0x03, 0x9f, 0x25, 0x0d, 0x99, 0x49, 0x41, 0x1f, 0x01, 0x09, 0xfd}; //0xfd是只显示中间一横
uchar code table_d[10] = {0x02, 0x9e, 0x24, 0x0c, 0x98, 0x48, 0x40, 0x1e, 0x00, 0x08}; //数码管显示带了点
/********************************************************************
* 名称 : v_RTInputByte()
* 功能 : 往DS1302写入1Byte数据
* 输入 : ucDa 写入的数据
* 输出 : 无
***********************************************************************/
void v_RTInputByte(uchar ucDa)
{
uchar i;
ACC = ucDa;
T_RST = 1;
for(i=8; i>0; i--)
{
T_IO = ACC0;
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
/********************************************************************
* 名称 : uc_RTOutputByte()
* 功能 : 从DS1302读取1Byte数据
* 输入 : 无
* 返回值: ACC
***********************************************************************/
uchar uc_RTOutputByte(void)
{
uchar i;
T_RST = 1;
for(i=8; i>0; i--)
{
ACC = ACC >>1;
T_IO=1;
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC);
}
/********************************************************************
* 名称 : v_W1302(uchar ucAddr, uchar ucDa)
* 功能 : 往DS1302写入数据
* 输入 : ucAddr: DS1302地址, ucDa: 要写的数据
* 返回值 : 无
***********************************************************************/
void v_W1302(uchar ucAddr, uchar ucDa)
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); // 写地址
_nop_();
_nop_();
v_RTInputByte(ucDa); // 写1Byte数据
T_CLK = 1;
T_RST = 0;
}
/********************************************************************
* 名称 : uc_R1302(uchar ucAddr)
* 功能 : 读取DS1302某地址的数据
* 输入 : ucAddr: DS1302地址
* 返回值 : ucDa :读取的数据
***********************************************************************/
uchar uc_R1302(uchar ucAddr)
{
uchar ucDa;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); //写地址,命令
_nop_();
_nop_();
ucDa = uc_RTOutputByte(); //读1Byte数据
T_CLK = 1;
T_RST = 0;
return(ucDa);
}
/********************************************************************
* 名称 : v_BurstW1302T
* 功能 : 往DS1302写入时钟数据(多字节方式)
* 输入 : pSecDa: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年 控制
* 8Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B 1B
* 返回值 : 无
***********************************************************************/
void v_BurstW1302T(uchar *pSecDa)
{
uchar i;
v_W1302(0x8e, 0x00); //控制命令,WP=0,写操作
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(0xbe); //0xbe:时钟多字节写命令
for(i=8; i>0; i--) //8Byte = 7Byte 时钟数据 + 1Byte 控制
{
v_RTInputByte(*pSecDa); //写1Byte数据
pSecDa++;
}
T_CLK = 1;
T_RST = 0;
}
/********************************************************************
* 名称 : v_BurstR1302T(uchar *pSecDa)
* 功能 : 读取DS1302时钟数据
* 输入 : pSecDa: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年
* 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
* 返回值 : ucDa :读取的数据
***********************************************************************/
void v_BurstR1302T(uchar *pSecDa)
{
uchar i;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(0xbf); //0xbf:时钟多字节读命令
for(i=8; i>0; i--)
{
*pSecDa = uc_RTOutputByte(); //读1Byte数据
pSecDa++;
}
T_CLK = 1;
T_RST = 0;
}
/********************************************************************
* 名称 : v_BurstW1302R(uchar *pReDa)
* 功能 : 往DS1302寄存器数写入数据(多字节方式)
* 输入 : pReDa: 寄存器数据地址
* 返回值 : 无
***********************************************************************/
void v_BurstW1302R(uchar *pReDa)
{
uchar i;
v_W1302(0x8e,0x00); //控制命令,WP=0,写操作
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(0xfe); //0xbe:时钟多字节写命令
for(i=31; i>0; i--) //31Byte 寄存器数据
{
v_RTInputByte(*pReDa); //写1Byte数据
pReDa++;
}
T_CLK = 1;
T_RST = 0;
}
/********************************************************************
* 名称 : v_BurstR1302R(uchar *pReDa)
* 功能 : 读取DS1302寄存器数据
* 输入 : pReDa: 寄存器数据地址
* 返回值 : 无
***********************************************************************/
void v_BurstR1302R(uchar *pReDa)
{
uchar i;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(0xff); //0xbf:时钟多字节读命令
for(i=31; i>0; i--) //31Byte 寄存器数据
{
*pReDa = uc_RTOutputByte(); //读1Byte数据
pReDa++;
}
T_CLK = 1;
T_RST = 0;
}
/********************************************************************
* 名称 : v_Set1302(uchar *pSecDa)
* 功能 : 设置初始时间
* 输入 : pSecDa: 初始时间地址。初始时间格式为: 秒 分 时 日 月 星期 年
* 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
* 返回值: 无
***********************************************************************/
void v_Set1302(uchar *pSecDa)
{
uchar i;
uchar ucAddr = 0x80;
v_W1302(0x8e, 0x00); //控制命令,WP=0,写操作
for(i=7; i>0; i--)
{
v_W1302(ucAddr, *pSecDa); // 秒 分 时 日 月 星期 年
pSecDa++;
ucAddr += 2;
}
v_W1302(0x8e, 0x80); //控制命令,WP=1,写保护
}
/********************************************************************
* 名称 : v_Get1302(uchar ucCurtime[])
* 功能 : 读取DS1302当前时间
* 输入 : ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年
* 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
* 返回值 : 无
***********************************************************************/
void v_Get1302(uchar ucCurtime[])
{
uchar i;
uchar ucAddr = 0x81;
for(i=0; i<7; i++)
{
ucCurtime[i] = uc_R1302(ucAddr); //格式为: 秒 分 时 日 月 星期 年
ucAddr += 2;
}
}
/********************************************************************
* 名称 : delay()
* 功能 : 延时,延时时间为 10ms * del。这是通过软件延时,有一定误差。
* 输入 : del
* 输出 : 无
***********************************************************************/
delay(uchar del)
{
uint i,j;
for(i=0;i<=25;i++)
for(j=0;j<=del;j++)
;
}
/********************************************************************
* 名称 : dectobcd(uchar dec)
* 功能 : DEC码转换为BCD码
* 输入 : dec码
* 输出 : bcd码
***********************************************************************/
uchar dectobcd(uchar dec)
{
uchar bcd;
bcd = 0;
while(dec >= 10)
{
dec -= 10;
bcd++;
}
bcd <<= 4;
bcd |= dec;
return bcd;
}
/********************************************************************
* 名称 : bcdtodec(uchar bcd)
* 功能 : BCD码转换为DEC码
* 输入 : bcd码
* 输出 : dec码
***********************************************************************/
uchar bcdtodec(uchar bcd)
{
uchar data1;
data1 = bcd & 0x0f; //取BCD低4位
bcd = bcd & 0x70; //剔除BCD的最高位和低4位。
data1 += bcd >> 1;
data1 += bcd >> 3; //用位移代替乘法运算
return data1;
}
/********************************************************************
* 名称 : Write_DS1302Init()
* 功能 : 往DS1302中写入数据。最开始显示的数据就是在这里设置的。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Write_DS1302Init()
{
v_W1302(0x8e,0);
v_W1302(0x80,0x50); //写入秒
v_W1302(0x8e,0);
v_W1302(0x82,0x59); //写入分
v_W1302(0x8e,0);
v_W1302(0x84,0x07); //写入小时
v_W1302(0x8e,0);
v_W1302(0x86,0x08); //写入日
v_W1302(0x8e,0);
v_W1302(0x88,0x08); //写入月
v_W1302(0x8e,0);
v_W1302(0x8a,0x05); //写入星期
v_W1302(0x8e,0);
v_W1302(0x8c,0x08); //写入年
}
/********************************************************************
* 名称 : Run_DS1302(void)
* 功能 : 读出DS1302中的时间,在数码管上进行显示
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Run_DS1302(void)
{
uchar sec, min, hour, day, month, year;
while(1)
{
v_W1302(0x8f, 0);
sec = bcdtodec(uc_R1302(0x81)); //读出DS1302中的秒
v_W1302(0x8f, 0);
min = bcdtodec(uc_R1302(0x83)); //读出DS1302中的分
v_W1302(0x8f, 0);
hour = bcdtodec(uc_R1302(0x85)); //读出DS1302中的小时
P0 = table[sec%10];
P2 = 0x01;
delay(2);
P0 = table[sec / 10];
P2 = 0x02;
delay(2);
P0 = table[10];
P2 = 0x04;
delay(2);
P0 = table[min % 10];
P2 = 0x08;
delay(2);
P0 = table[min / 10];
P2 = 0x10;
delay(2);
P0 = table[10];
P2 = 0x20;
delay(2);
P0 = table[hour % 10];
P2 = 0x40;
delay(2);
P0 = table[(hour / 10) & 0x01];
P2 = 0x80;
delay(2);
while(!P3_2)
{
while(1)
{
v_W1302(0x8f, 0);
day = bcdtodec(uc_R1302(0x87)); //读出DS1302中的日
v_W1302(0x8f, 0);
month = bcdtodec(uc_R1302(0x89)); //读出DS1302中的月
v_W1302(0x8f, 0);
year = bcdtodec(uc_R1302(0x8d)); //读出DS1302中的年
P0 = table_d[day % 10];
P2 = 0x01;
delay(2);
P0 = table[day / 10];
P2 = 0x02;
delay(2);
P0 = table_d[month % 10];
P2 = 0x04;
delay(2);
P0 = table[month / 10];
P2 = 0x08;
delay(2);
P0 = table_d[year % 10];
P2 = 0x10;
delay(2);
P0 = table[year / 10];
P2 = 0x20;
delay(2);
P0 = table[0];
P2 = 0x40;
delay(2);
P0 = table[2];
P2 = 0x80;
delay(2);
if(P3_4 == 0) break;
}
}
}
}
/********************************************************************
* 名称 : Main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Main()
{
Write_DS1302Init();
Run_DS1302();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -