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

📄 ds1302.c

📁 AVR学习开发 板
💻 C
字号:
/****************************************************************************************
                         DS1302的mega8控制程序   
		                                                
             程序功能:该程序是用AVR来控制对ds1302
			           读写信号等的操作.
             硬件连接:分配PC1=SCLK,PC2=I/O,PC3=RST
			           三个I/O口分别作为时钟、数据、复位
					   的控制。
			 显示部分用12864液晶来显示时时时间
					                                 作者:张国旗
													 2008年12月31号       
****************************************************************************************/
#define uchar unsigned char
#define uint unsigned int
#define TRUE 1
#define FALSE 0
//=========RTC常量=================
#define RTC_DDR     DDRC
#define RTC_PORT	PORTC
#define RTC_CLK   	PC1	    //时钟
#define RTC_DATA  	PC2		//数据
#define RTC_CS    	PC3		//复位
//============命令=================
#define RD	  	0x01
#define WR	  	0x00
#define C_SEC		0x80	//秒
#define C_MIN		0x82	//分
#define C_HR		0x84	//时
#define C_DAY		0x86	//日
#define C_MTH		0x88	//月
#define C_WK		0x8A	//星期 DATE
#define C_YR		0x8C	//年
#define C_WP		0x8E	//控制(写保护)
#define C_CHARGE	0x90	//涓流充电
#define C_BURST		0xBE	//时钟多字节
//===========配置================
#define CLK_HALT	0x80	//停止时钟控制位    SECOND	bit7
#define CLK_START	0x00	//启动时钟
#define M12_24		0x80	//12/24小时值选择位 HOUR		bit7 
#define PROTECT		0x80	//写保护控制位      CONTROL	bit7 
#define UPROTECT	0x00	//写保护控制位      CONTROL	bit7 
//=========涓流充电控制常量======
#define TC_D1R2		0xA5	//high 1 Diode +2K Resistors  
#define TC_D2R8		0xAB	//low  2 Diodes+8K Resistors  
#define TC_DISABLED	0x00	//Disabled(TCS<>1010 or DS=00 or RS=00)
//=========RAM 命令=============
#define C_RAMBASE		0xC0	//RAM0~RAM30<<1 地址需左移一位 
//===================延时函数========================
//5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值
//1141是在8MHz晶振下,通过软件仿真反复实验得到的数值
//==================================================
void Delayus(uint US)		  
{
    uint i;
 	US=US*5/4;		  	    //5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值
 	for( i=0;i<US;i++); 
}
void Delayms(uint MS)		  
{
    uint i,j;
 	for( i=0;i<MS;i++)
 	for(j=0;j<1141;j++); 	//1141是在8MHz晶振下,通过软件仿真反复实验得到的数值
}
/*******************************************
函数名称: DS1302_init
功    能: 初始化DS1302的数据接口
参    数: 无
返回值  : 无
/********************************************/
void DS1302_portinit(void)		  
{
    RTC_DDR|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS);
	//将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出
}
/*******************************************
函数名称: DS1302_writeB
功    能: 向DS1302写入一个字节数据(没有RST操作)
参    数: byte--要写入的数据
返回值  : 无
********************************************/
void DS1302_writeB(uchar byte)
{
    uchar i;
 	for(i=0;i<8;i++)		 	        //8位数据计数
 	{
        RTC_PORT&=~BIT(RTC_CLK);	    //拉低时钟端
  		if(byte&0x01)				    //当前位是否是1
  		{
    	    RTC_PORT|=BIT(RTC_DATA);   //当前位是1,拉高数据端
  		}
  		else						  
  		{
   	 		RTC_PORT&=~BIT(RTC_DATA);  //当前位是0,拉低数据端
  		}  
  		Delayus(10);				    //调整时钟和脉冲宽度
  		RTC_PORT|=BIT(RTC_CLK);	    //时钟上升沿(DS1302采样数据)
  		byte>>=1;					    //数据右移1位,为送出新数据位做准备
 	}
}
/*******************************************
函数名称: DS1302_readB
功    能: 从DS1302读出一个字节数据(没有RST操作)
参    数: 无
返回值  : byte--读出的数据
********************************************/
uchar DS1302_readB(void)
{
    uchar i,byte=0;
 	RTC_DDR&=~BIT(RTC_DATA);		    //将数据端口设置为输入		  
 	RTC_PORT&=~BIT(RTC_DATA);		    //无上拉电阻
 	for(i=0;i<8;i++)			 	    //8位数据计数
 	{
  	    byte>>=1;  					    //保存读入的数据位
  		RTC_PORT|=BIT(RTC_CLK);	    //时钟上升沿
  		Delayus(10);				    //延时,调整时钟脉冲宽度
  		RTC_PORT&=~BIT(RTC_CLK);	    //时钟下降沿,DS1302输出数据位
  		Delayus(10);					//等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)
  		if(PINC&BIT(RTC_DATA))	 		//当前位是否是高电平
  		{
   		    byte|=BIT(PB7);			 	//是高电平就将返回数据的当前位置1
  		}
  		else
  		{
   		    byte&=~BIT(PB7);			//是低电平就将返回数据的当前位置0
  		}
 	}
 	RTC_DDR|=BIT(RTC_DATA);		 		//最后将数据端口设置为输出
 	return byte;				 		//返回读出的数据
}
/*******************************************
函数名称: DS1302_writeD
功    能: 向DS1302的某个地址写入一个字节数据
参    数: addr--地址值(寄存器或RAM)
	  	  data--要写入的地址
返回值  : 无
/********************************************/
void DS1302_writeD(uchar addr,uchar data)
{
 	{
 	    RTC_PORT&=~BIT(RTC_CS);	 //拉低片选端
 		RTC_PORT&=~BIT(RTC_CLK);	 //拉低时钟端
 		Delayus(10);
 		RTC_PORT|=BIT(RTC_CS);	 	 //拉高片选端
 		Delayus(10); 			 	 //调整片选脉冲
 		DS1302_writeB(addr);	 	 //写入操作命令(地址)
 		Delayus(10);
 		RTC_PORT&=~BIT(RTC_CLK);	 //拉低时钟端
 		Delayus(10);
 		DS1302_writeB(data);	 	 //写入数据
 		RTC_PORT&=~BIT(RTC_CLK);	 //拉低时钟端
 		Delayus(10);			 	 //调整片选脉冲
 		RTC_PORT&=~BIT(RTC_CS);	 //拉低片选端
}
}
/*******************************************
函数名称: DS1302_readD
功    能: 从DS1302的某个地址读出一个字节数据
参    数: addr--地址值(寄存器或RAM)
返回值  : data--读出的数据
********************************************/
uchar DS1302_readD(uchar addr)
{
    uchar data;
 	RTC_PORT&=~BIT(RTC_CS);	//拉低片选端
 	RTC_PORT&=~BIT(RTC_CLK);	//拉低时钟端
 	Delayus(10);
 	RTC_PORT|=BIT(RTC_CS);	 	//拉高片选端
 	Delayus(10); 			 	//调整片选脉冲
 	DS1302_writeB(addr);	 	//写入操作命令(地址)
 	Delayus(10);
 	data=DS1302_readB();	 	//读出数据
 	Delayus(10);
 	RTC_PORT&=~BIT(RTC_CLK);	//拉低时钟端
	RTC_PORT&=~BIT(RTC_CS); 	//拉低片选端
 	return data;			 	//返回读出的数据
}
/*******************************************
函数名称: DS1302_setT
功    能: 设置DS1302的时间
参    数: ptTimeD--设置时间数组指针
返回值  : 无
********************************************/
void DS1302_setT(uchar ptTimeD[])
{
    uchar i;
    uchar addr = 0x80; 			 	  		//写入地址从秒寄存器开始
    DS1302_writeD(C_WP|WR,UPROTECT); 		//控制命令,WP位为0,允许写操作
	Delayms(5);
    for(i=0;i<7;i++)
    {
        DS1302_writeD(addr|WR,ptTimeD[i]); 	// 秒 分 时 日 月 星期 年         
        addr+=2;
		Delayms(1);
    }
    DS1302_writeD(C_WP|WR,PROTECT); 		//控制命令,WP位为1,不允许写操作
}
/*******************************************
函数名称: DS1302_getT
功    能: 读取DS1302的当前时间
参    数: time[]--读取的时间数组
返回值  : 无
********************************************/
void DS1302_getT(uchar time[])
{
    uchar i;
/*=======下面的是单次读写===================
    uchar addr = 0x80; 			 	  	//读取地址从秒寄存器开始 
    for(i=0;i<7;i++)
    {
        time[i]=DS1302_readD(addr|RD);  // 秒 分 时 日 月 星期 年        
        addr+=2;
    }
===========================================*/
//=========下面是多字节读取================
    RTC_PORT&=~BIT(RTC_CS);		   //拉低片选端
    Delayus(10);
    RTC_PORT|=BIT(RTC_CS);	 		   //拉高片选端
    Delayus(10); 			 		   //调整片选脉冲
	DS1302_writeB(0xbf);       		   // 0xbf:时钟多字节读取命令 
    for (i=0;i<8;i++)       		   //时间数据的存放格式是:
    {                        		   //秒,分,时,日,月,星期,年,控制
        time[i]=DS1302_readB(); 	   //【7个数据(BCD格式)+1个控制】 
 	}
	RTC_PORT&=~BIT(RTC_CS); 	 	   //拉低片选端
//======================================
    RTC_PORT&=~BIT(RTC_CLK);	 		   //拉低时钟端(时钟端在不操作时为低)
}
/*******************************************
函数名称: DS1302_check
功    能: 检测DS1302是否正常工作
参    数: 无
返回值  : exist--为TRUE为检测到DS1302,为FALSE为没检测到
/********************************************/
uchar DS1302_check(void)
{
    uchar exist;
    DS1302_writeD(C_WP|WR,UPROTECT);	//写入写允许命令
    DS1302_writeD(C_RAMBASE|WR,0xA5);	//RAM0写入0xA5
    exist=DS1302_readD(C_RAMBASE|RD);	//读取RAM0
    if(exist==0xA5)	
	{
	    exist=TRUE;						//如果读取值与写入值相等,返回TRUE
	}
    else 	
	{
	    exist=FALSE;					//如果读取值与写入值不相等,返回FALSE
	}	
	return exist;
}
/*******************************************
函数名称: DS1302_init
功    能: 初始化DS1302
参    数: 无
返回值  : 无
********************************************/
void DS1302_init(void)
{
    DS1302_writeD(C_WP|WR,UPROTECT);	//写入写允许命令
 	DS1302_writeD(C_SEC|WR,CLK_START);	//启动振荡器,DS1302开始工作
 	DS1302_writeD(C_WP|WR,PROTECT); 	//控制命令,WP位为1,不允许写操作	  
}
/*******************************************
函数名称: BCD_ASCII
功    能: 将压缩BCD码转换成ascii码
参    数: BCD--将要转换的压缩BCD码
	  	  ptasc--转换后的ASCII码数组指针
返回值  : 无
/********************************************/
void BCD_ASCII(uchar BCD,uchar ptasc[])
{ 	
    ptasc[0]=BCD/16|0x30;	   		   //0X58	35  38 //转换十位
	ptasc[1]=BCD&0x0F|0x30;  		   //转换个位
}
/*******************************************
函数名称: Disp_time
功    能: 在1602液晶上显示当前时间(第1行格式:年-月-日 星期;第2行格式:时-分-秒)
参    数: time[]--时间数组
返回值  : 无
/********************************************/
void Disp_time(uchar time[])
{
    unsigned int vstrtemp,i;
	unsigned int vstr[8];
	vstr[0] = time[3]/16+0x30;
	vstr[1] = time[3]%16+0x30;
	vstr[2] = '/';
	vstr[3] = time[4]/16+0x30;
	vstr[4] = time[4]%16+0x30;
	vstr[5] = '/';
	vstr[6] = time[6]/16+0x30;
	vstr[7] = time[6]%16+0x30;
	WriteCommand(0x30);              //时间显示起始坐标
	WriteCommand(0x92);
	for(i=0;i<8;i++)
	{ 
	    vstrtemp=vstr[i];                
  		WriteData(vstrtemp);
	}
	vstr[0] = time[2]/16+0x30;
	vstr[1] = time[2]%16+0x30;
	vstr[2] = ':';
	vstr[3] = time[1]/16+0x30;
	vstr[4] = time[1]%16+0x30;
	vstr[5] = ':';
	vstr[6] = time[0]/16+0x30;
	vstr[7] = time[0]%16+0x30;
	WriteCommand(0x30);              //时间显示起始坐标
	WriteCommand(0x8a);
	for(i=0;i<8;i++)
	{ 
   	    vstrtemp=vstr[i];                
       	WriteData(vstrtemp);
	}
}

⌨️ 快捷键说明

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