这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » STC51单片机实例之32时钟DS1302

共7条 1/1 1 跳转至

STC51单片机实例之32时钟DS1302

高工
2014-08-19 01:54:03     打赏
/********************************************************************
* 文件名  :  时钟DS1302.c
* 描述    :  该程序实现了用单片机来控制时钟芯片DS1302进行时钟的显示。
			 程序的开始,显示的是时间,按了S17后,显示日期。再按S19,显示回时间。			 

***********************************************************************/
#include<reg52.h>
#include<intrins.h>

#define uchar unsigned char
#define uint  unsigned int

uchar code table[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
sbit KEY1 = P3^2;
sbit KEY2 = P3^4;

sbit T_CLK = P1^6; /*实时时钟时钟线引脚 */
sbit T_IO = P3^5; /*实时时钟数据线引脚 */
sbit T_RST = P1^7; /*实时时钟复位线引脚 */

/********************************************************************
* 名称 : delay()
* 功能 : 延时,延时时间大概为140US。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay()
{
	int i,j;
	for(i=0; i<=10; i++)
	for(j=0; j<=2; j++)
;
}

/********************************************************************
* 名称 : Delay_1ms()
* 功能 : 延时子程序,延时时间为 1ms * x
* 输入 : x (延时一毫秒的个数)
* 输出 : 无
***********************************************************************/
void Delay_1ms(uint i)//1ms延时
{
	uchar x,j;
	for(j=0;j<i;j++)
	for(x=0;x<=148;x++);	
}

/********************************************************************
* 名称 :  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;
	}
}

/********************************************************************
* 名称 : 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(void)
{
	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中的数据,并在液晶1602上进行显示
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Run_DS1302(void)
{
	uchar sec, min, hour, day, month, year,flag=1;
	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中的小时
		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中的年
		if(KEY1 == 0)
		{
			flag = 1;	
		}
		if(KEY2 == 0)
		{
			flag = 2;
		}
		if(flag == 1)
		{
			P0 = table[hour / 10 % 10];
			P2 = 0;
			Delay_1ms(2);
			P0 = table[hour % 10];
			P2 = 1;
			Delay_1ms(2);
			P0 = 0x80;
			P2 = 2;
			Delay_1ms(2);
			P0 = table[min / 10 % 10];
			P2 = 3;
			Delay_1ms(2);
			P0 = table[min % 10];
			P2 = 4;
			Delay_1ms(2);
			P0 = 0x80;
			P2 = 5;
			Delay_1ms(2);
			P0 = table[sec / 10 % 10];
			P2 = 6;
			Delay_1ms(2);
			P0 = table[sec % 10];
			P2 = 7;
			Delay_1ms(2);
		}
		if(flag == 2)
		{
			P0 = table[year / 10 % 10];
			P2 = 0;
			Delay_1ms(2);
			P0 = table[year % 10];
			P2 = 1;
			Delay_1ms(2);
			P0 = 0x80;
			P2 = 2;
			Delay_1ms(2);
			P0 = table[month / 10 % 10];
			P2 = 3;
			Delay_1ms(2);
			P0 = table[month % 10];
			P2 = 4;
			Delay_1ms(2);
			P0 = 0x80;
			P2 = 5;
			Delay_1ms(2);
			P0 = table[day / 10 % 10];
			P2 = 6;
			Delay_1ms(2);
			P0 = table[day % 10];
			P2 = 7;
			Delay_1ms(2);
		}
	}
} 

/********************************************************************
* 名称 : Main(void)
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/ 
void Main(void)
{
	Write_DS1302Init();
	Run_DS1302();
}

 


工程师
2014-08-26 15:02:11     打赏
2楼
好厉害的程序

菜鸟
2014-08-28 16:01:42     打赏
3楼

可以上传  程序 .c 文件不?

这样好保存呀!


复制很慢


菜鸟
2014-08-28 16:54:12     打赏
4楼

所有程序很发给我的QQ不?


404398260@qq.com


菜鸟
2019-01-21 06:08:38     打赏
5楼
大神,有附带的电路图发一个啊!谢谢

高工
2022-06-19 22:27:18     打赏
6楼

学习


专家
2022-06-19 22:25:49     打赏
7楼

好厉害的程序


共7条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]