⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds1302.c

📁 单片机实现闹钟功能
💻 C
字号:
//*************************************************************************************************
//*																								  *
//*				***************************DS1302驱动程序*************************				  *
//*																								  *
//*************************************************************************************************


//*************************************************************************************************
//*																								  *
//*			 ******************************头文件及宏定义**************************				  *
//*																								  *
//*************************************************************************************************
#include <at89x51.h>

#define DSIO P1_2					   //实时时钟数据线引脚
#define DSCLK P1_1					   //实时时钟时钟线引脚 
#define DSRST P1_0					   //实时时钟复位线引脚

#define DS_SECOND	0x80			   //DS1302数据地址。
#define DS_MINUTE	0x82
#define DS_HOUR		0x84 
#define DS_WEEK		0x8A
#define DS_DAY		0x86
#define DS_MONTH	0x88
#define DS_YEAR		0x8C


//*************************************************************************************************
//*																								  *
//*			  ********************************全局变量******************************			  *
//*																								  *
//*************************************************************************************************            
sbit  ACC0 = ACC^0;
sbit  ACC7 = ACC^7;

typedef struct TIME			  //定义的时间类型
{
	unsigned char ucSecond;
	unsigned char ucMinute;
	unsigned char ucHour;
	unsigned char ucWeek;
	unsigned char ucDay;
	unsigned char ucMonth;
	unsigned char ucYear;
	unsigned char ucaDateString[9];
	unsigned char ucaTimeString[9];
}TIME;	



//*************************************************************************************************
//*																								  *
//*			 *********************实时时钟写入一字节(内部函数)*************************			  *
//*																								  *
//*************************************************************************************************
void vWriteByte(unsigned char ucByte) 
{ 
    unsigned char ucCount;

    ACC = ucByte;

    for(ucCount=8;ucCount>0;ucCount--)
    {
        DSIO = ACC0;          			  //把累加器第0位赋给DSIO口。

        DSCLK = 1;						  //DSCLK下降沿,写入数据。
        DSCLK = 0;

        ACC = ACC >> 1; 				  //把累加器里的数据右移一位。
    } 
}


//*************************************************************************************************
//*																								  *
//*			 *********************实时时钟读入一字节(内部函数)************************			  *
//*																								  *
//*************************************************************************************************
unsigned char ucReadByte(void) 	
{ 
    unsigned char ucCount;

    for(ucCount=8;ucCount>0;ucCount--)
    {
        ACC = ACC >>1;  		   //把累加器右移一位。
		       		
        ACC7 = DSIO;			   //把DSIO的数据传给累加器最高位。

        DSCLK = 1;				   //DSCLK下降沿读出数据。
        DSCLK = 0;
    } 

    return ACC; 
}


//*************************************************************************************************
//*																								  *
//*			 *************************向实时时钟写入一字节***************************			  *
//*																								  *
//*************************************************************************************************
void vDSWriteDirect(unsigned char ucAddr, unsigned char ucData)	//ucAddr: DS1302地址, ucData: 要写的数据
{
    DSRST = 0;
    DSCLK = 0;
    DSRST = 1;

    vWriteByte(ucAddr);       	// 地址,命令 
    vWriteByte(ucData);       	// 写1Byte数据

    DSCLK = 1;
    DSRST = 0;
} 

//*************************************************************************************************
//*																								  *
//*			 *************************读取DS1302某地址的数据*************************			  *
//*																								  *
//*************************************************************************************************
unsigned char vDSReadDirect(unsigned char ucAddr)	
{
    unsigned char ucData;

    DSRST = 0;
    DSCLK = 0;
    DSRST = 1;

    vWriteByte(ucAddr|0x01);        // 地址,命令 
    ucData = ucReadByte();         // 读1Byte数据

    DSCLK = 1;
    DSRST = 0;

    return ucData;
}

//*************************************************************************************************
//*																								  *
//*			 ******************************是否写保护*******************************			  *
//*																								  *
//*************************************************************************************************
void vDSSetProtect(bit bFlag)       
{
	if(bFlag)
		vDSWriteDirect(0x8E,0x10);
	else
		vDSWriteDirect(0x8E,0x00);
}



//*************************************************************************************************
//*																								  *
//*			 ******************************设置实时时钟时间**************************			  *
//*																								  *
//*************************************************************************************************
void vDSSetTime(unsigned char ucAddress, unsigned char ucValue)
{
	vDSSetProtect(0);									   		 //取消保护。

	vDSWriteDirect(ucAddress, ((ucValue/10)<<4 | (ucValue%10))); //吧ucValue转换成BCD码,然后写入。
}



//*************************************************************************************************
//*																								  *
//*			 ******************************读取实时时钟时间**************************			  *
//*																								  *
//*************************************************************************************************
void vDSGetTime(TIME *stTime)			  //把读取的BCD码转换成2进制数然后存入时间数组。
{
	unsigned char ucReadValue;

	ucReadValue = vDSReadDirect(DS_SECOND);						   //秒
	stTime->ucSecond=((ucReadValue&0x70)>>4)*10+(ucReadValue&0x0F);

	ucReadValue = vDSReadDirect(DS_MINUTE);						   //分
	stTime->ucMinute=((ucReadValue&0x70)>>4)*10+(ucReadValue&0x0F);

	ucReadValue = vDSReadDirect(DS_HOUR);						   //小时
	stTime->ucHour =((ucReadValue&0x70)>>4)*10+(ucReadValue&0x0F);

	ucReadValue = vDSReadDirect(DS_DAY);						   //天
	stTime->ucDay =((ucReadValue&0x70)>>4)*10+(ucReadValue&0x0F);
		
	ucReadValue = vDSReadDirect(DS_WEEK);						   //星期
	stTime->ucWeek=((ucReadValue&0x70)>>4)*10+(ucReadValue&0x0F);

	ucReadValue =vDSReadDirect(DS_MONTH);						   //月
	stTime->ucMonth=((ucReadValue&0x70)>>4)*10+(ucReadValue&0x0F);

	ucReadValue =vDSReadDirect(DS_YEAR);						   //年
	stTime->ucYear=((ucReadValue&0x70)>>4)*10+(ucReadValue&0x0F);	
}



//*************************************************************************************************
//*																								  *
//*			 ******************************实时时钟日期字符串**************************			  *
//*																								  *
//*************************************************************************************************
void vDateString(TIME *stTime)		   //把日期数据转换成日期字符串,便于显示。
{
	stTime->ucaDateString[0] = stTime->ucYear/10 + '0';
	stTime->ucaDateString[1] = stTime->ucYear%10 + '0';

	stTime->ucaDateString[2] = '-';

	stTime->ucaDateString[3] = stTime->ucMonth/10 + '0';
	stTime->ucaDateString[4] = stTime->ucMonth%10 + '0';

	stTime->ucaDateString[5] = '-';

	stTime->ucaDateString[6] = stTime->ucDay/10 + '0';
	stTime->ucaDateString[7] = stTime->ucDay%10 + '0';

	stTime->ucaDateString[8] = '\0';
}



//*************************************************************************************************
//*																								  *
//*			 ******************************实时时钟时间字符串**************************			  *
//*																								  *
//*************************************************************************************************
void vTimeString(TIME *stTime)		 //把时间数据转换成时间字符串,便于显示。
{
	stTime->ucaTimeString[0] = stTime->ucHour/10 + '0';
	stTime->ucaTimeString[1] = stTime->ucHour%10 + '0';

	stTime->ucaTimeString[2] = ':';

	stTime->ucaTimeString[3] = stTime->ucMinute/10 + '0';
	stTime->ucaTimeString[4] = stTime->ucMinute%10 + '0';

	stTime->ucaTimeString[5] = ':';

	stTime->ucaTimeString[6] = stTime->ucSecond/10 + '0';
	stTime->ucaTimeString[7] = stTime->ucSecond%10 + '0';

	stTime->ucaDateString[8] = '\0';
}



//*************************************************************************************************
//*																								  *
//*				 ******************************初始化时钟**************************				  *
//*																								  *
//*************************************************************************************************
void vDSInitialize()
{
	unsigned char ucSecond=vDSReadDirect(DS_SECOND);

	if(ucSecond&0x80)		  
		vDSSetTime(DS_SECOND,0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -