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

📄 ds1302.c

📁 ds1302读写程序,经过调试已经通过.
💻 C
字号:
/***************************************************
Function:DS1302时钟读写,在LCD1602上显示并可以调整
Author:Tecman
E-mail:tecman@126.com
Great Date:2008.07.15
****************************************************/
#include <REG51.H>
#include <string.h>
#include<intrins.h>
#include <PIO.H>

#define DPORT P0
sbit 	RS=P2^0;							
sbit 	RW=P2^1;
sbit 	E =P2^2;
															//LCD1602接口定义
sbit 	CLK=P1^0;
sbit 	IO =P1^1;
sbit 	RST=P1^2;											//DS1302时间显示定义部分

sbit	key1=P1^4;
sbit	key2=P1^5;
sbit	key3=P1^6;
sbit	key4=P1^7;											//按键定义

unsigned char ID,timecount;
 									
bdata unsigned char flag1;									//标志位集合1
	sbit sec	=	flag1^0;			
	sbit min	=	flag1^1;			
	sbit hour	=	flag1^2;			
	sbit year	=	flag1^3;			
	sbit mon	=	flag1^4;			
	sbit week	=	flag1^5;
	sbit day	=	flag1^6;
	sbit flag	=	flag1^7;								//flag是闪烁标志
															
unsigned char code date[]={"Week:"};

void DISP_L1(void); 										//显示屏幕第一行 
void DISP_L2(void); 										//显示屏幕第二行
void setkey(void);											//时间调整
void Delay(unsigned int n );								//延时,毫秒数由n决定
void Set(unsigned char sel,bit Ads);     					//根据选择调整相应项目
void write1302(unsigned char Addr, unsigned char Data);   	// 向DS1302写入一个字节
unsigned char read1302(unsigned char byte);          		// 从DS1302读出一个字节

void Write_Data(unsigned char Data);						//写LCD数据
void Write_Instruction(unsigned char Cmd);					//写LCD指令
void busy(void);											//忙检查
void LCD_Init(void);										//LCD初始化
void LCD_DISP(unsigned char X, 								//水平坐标0-15								
			  unsigned char Y, 								//垂直坐标0-1
			  unsigned char Data);							//显示内容
void DISP_STR(unsigned char X,
			  unsigned char Y, 
			  unsigned char code *P);						//显示字符串



void main(void)
{  
  	Delay(40000); 											//启动等待,等LCD讲入工作状态
 	LCD_Init(); 											//LCD初始化

  	TMOD=0x01;
  	TH0=0x3C;
  	TL0=0xAF;												//50ms计时
  	EA=1;
  	TR0=1;
  	ET0=1;  
  	write1302(0x90,0xA5);									//打开充电二级管  一个二级管串联一个2K电阻 
  	write1302(0x8E,0x80);									//写保护,禁止写操作 

  while(1)
    {                   
     if (key3==0) 											// 设置和选择项目键
     {
       	Delay(10000);
       	if(key3==0)
		{
			ID++;
			if(ID>7) ID=0;
		}
       	while(key3==0);    
      }
     switch(ID)
      {
       	case 0:
         		sec=0;
         		DISP_L1(); 
				DISP_L2();
         		break;
       	case 1:											//年
         		year=1;
         		DISP_L1();
				DISP_L2();                  
         		setkey();
         		break;
       	case 2:											//月
         		year=0;
				mon=1;
         		DISP_L1(); 
				DISP_L2();                 
         		setkey();
         		break;
       	case 3:											//日
         		mon=0;
				day=1;
         		DISP_L1(); 
				DISP_L2();
         		setkey();
         		break;             
       	case 4:											//星期
         		day=0;
				week=1;
         		DISP_L1(); 
				DISP_L2();         
         		setkey();
         		break;
       	case 5:											//小时
         		week=0;
				hour=1;
         		DISP_L1(); 
				DISP_L2(); 
         		setkey();      
         		break;       
       	case 6:											//分钟
         		hour=0;
				min=1;
         		DISP_L1(); 
				DISP_L2(); 
         		setkey();
         		break;
       	case 7:											//秒
         		min=0;
				sec=1;
         		DISP_L1(); 
				DISP_L2();             
         		setkey();
         		break;              
      }
    }
}

//------------定时中断-----------
void timer(void) interrupt 1 
{
  	TH0=0x3C;
  	TL0=0xAF; 
  	timecount++;
  	if(timecount>9)
   	{
    	timecount=0;    
    	flag=~flag;             
   	}  
}

//------------调整--------------
void setkey()
{
  if (key2==0) 											//增加
      {
       	Delay(10000);
       	if(key2==0) Set(ID,0);  
       	if(ID!=7)  while(key2==0);    
      }
   if (key1==0)  										//减少
      {
       	Delay(10000);
       	if(key1==0) Set(ID,1);          
       	if(ID!=7) while(key1==0);    
      }
}

//-------根据选择调整相应项目并写入DS1302-------
void Set(unsigned char sel,bit Ads) 
{
  	signed char Addr,temp;
  	signed char Up,Down;
  	if(sel==7)  
	{
		Addr=0x80;
		Up=0;
		Down=0;
	}     										 		//秒
  	if(sel==6)  
	{
		Addr=0x82; 
		Up=59;
		Down=0;
	}    												//分钟
  	if(sel==5) 
	{
		Addr=0x84;
	 	Up=23;
		Down=0;
	}    												//小时
	if(sel==4) 
	{
		Addr=0x8a; 
		Up=7; 
		Down=1;
	}    												//星期
  	if(sel==3)  
	{
		Addr=0x86; 
		Up=31;
		Down=1;}    									//日
  	if(sel==2)  
	{
		Addr=0x88; 
		Up=12;
		Down=1;
	}    												//月
  	if(sel==1) 
	{
		Addr=0x8c; 	
		Up=99;
		Down=0;
	}    												//年
    
  	temp=read1302(Addr+1)/16*10+read1302(Addr+1)%16;
  	if (!Ads) 		temp++; 
	else 			temp--;
  	if(temp>Up) 	temp=Down;   
  	if(temp<Down) 	temp=Up;
           
  	write1302(0x8e,0x00);								//允许写操作
  	write1302(Addr,temp/10*16+temp%10);
  	write1302(0x8e,0x80);								//写保护,禁止写操作  
}

//-------------屏幕显示第一行 时间--------------
void DISP_L1(void) 
{  
	LCD_DISP(6,0,0x3A); 
	LCD_DISP(9,0,0x3A);									//显示冒号
	if(sec==1)  										//秒闪烁标志位
    {
     	if(flag==1)
       	{    
        	LCD_DISP(10,0,read1302(0x81)/16+0x30); 		//显示秒
        	LCD_DISP(11,0,read1302(0x81)%16+0x30);        
       	}
     	else
       	{
        	LCD_DISP(10,0,0x20); 					
        	LCD_DISP(11,0,0x20);    
       	}
    } 
  	else
    {
     	LCD_DISP(10,0,read1302(0x81)/16+0x30); 
     	LCD_DISP(11,0,read1302(0x81)%16+0x30);         
    }   
   
  if(min==1)  											//分钟闪烁标志位
  {
  		if(flag==1)
    	{    
        	LCD_DISP(7,0,read1302(0x83)/16+0x30); 		//显示分钟
        	LCD_DISP(8,0,read1302(0x83)%16+0x30);        
    	}
     	else
     	{
	    	LCD_DISP(7,0,0x20); 					
        	LCD_DISP(8,0,0x20);    
     	}
   } 
  else
   {
     	LCD_DISP(7,0,read1302(0x83)/16+0x30); 
     	LCD_DISP(8,0,read1302(0x83)%16+0x30);         
   } 

  if(hour==1)  											//小时闪烁标志位
  {
     	if(flag==1)
       	{    
        	LCD_DISP(4,0,read1302(0x85)/16+0x30);		//显示小时
        	LCD_DISP(5,0,read1302(0x85)%16+0x30); 
       	}
     	else
       	{
        	LCD_DISP(4,0,0x20); 						
        	LCD_DISP(5,0,0x20);    
       	}
   } 
  else
  { 
    	LCD_DISP(4,0,read1302(0x85)/16+0x30);			
    	LCD_DISP(5,0,read1302(0x85)%16+0x30);
  }
}

//----------屏幕显示第二行  日期和星----------   
void DISP_L2(void)
{
  	LCD_DISP(3,1,0x2F); 								//显示固定字符
  	LCD_DISP(6,1,0x2F);
  	DISP_STR(10,1,date);
    
  	if(year==1)  										//年闪烁标志位
    {
     	if(flag==1)
       	{    
        	LCD_DISP(1,1,read1302(0x8d)/16+0x30);		//显示年
        	LCD_DISP(2,1,read1302(0x8d)%16+0x30);
       	}
     	else
       	{
        	LCD_DISP(1,1,0x20); 						//显示年
        	LCD_DISP(2,1,0x20);    
       	}
    } 
  	else
    { 
      	LCD_DISP(1,1,read1302(0x8d)/16+0x30);
      	LCD_DISP(2,1,read1302(0x8d)%16+0x30);
    }
     
  	if(mon==1)  										//月闪烁标志位
    {
     	if(flag==1)
       	{    
        	LCD_DISP(4,1,read1302(0x89)/16+0x30);		//显示月 
        	LCD_DISP(5,1,read1302(0x89)%16+0x30);
       	}
     	else
       	{
        	LCD_DISP(4,1,0x20); 
        	LCD_DISP(5,1,0x20);    
       	}
    } 
  	else
    { 
      	LCD_DISP(4,1,read1302(0x89)/16+0x30);
      	LCD_DISP(5,1,read1302(0x89)%16+0x30);
    }   

  if(day==1)  											//日闪烁标志位
  {
     if(flag==1)
     {    
         LCD_DISP(7,1,read1302(0x87)/16+0x30);			//显示日
         LCD_DISP(8,1,read1302(0x87)%16+0x30);
     }
     else
     {
        LCD_DISP(7,1,0x20); 
        LCD_DISP(8,1,0x20);    
     }
  } 
  else
  { 
      LCD_DISP(7,1,read1302(0x87)/16+0x30);
      LCD_DISP(8,1,read1302(0x87)%16+0x30);
  }
    
  if(week==1)  											//星期闪烁标志位
  {
     if(flag==1)
     {    
         LCD_DISP(15,1,read1302(0x8b)%16+0x30);			//显示星期
     }
     else
     {
        LCD_DISP(15,1,0x20);       
     }
  } 
  else
  { 
      LCD_DISP(15,1,read1302(0x8b)%16+0x30);
  }     
}

//===============以下是LCD1602驱动================

//--------------写数据---------------
void Write_Data(unsigned char Dat)
{
  	busy(); 									//检测忙
	RS=1;	
	RW=0;
	DPORT=Dat;									//将待写数据送到数据端口
	E = 0; 										//若晶振速度太高可以在这后加小的延时
	_nop_();
  	E = 1;
}
//---------------写指令--------------
void Write_Instruction(unsigned char Cmd) 
{
	busy();
	RS=0;
	RW=0;
	DPORT=Cmd;
	E=1;
	_nop_();
	E=0;
}

//-----------忙检查------------
void busy(void)
{
 	DPORT = 0xFF; 
  	RS = 0;
  	RW = 1;
  	E = 0;
  	_nop_();
  	E = 1;
  	while (DPORT&0x80); 					//检测忙信号	
}
//-----------LCD初始化----------
void LCD_Init(void) 
{
  Delay(500); 
  Write_Instruction(0x38); 				//显示模式设置,开始要求每次检测忙信号
  Write_Instruction(0x08); 				//关闭显示
  Write_Instruction(0x01); 				//显示清屏
  Write_Instruction(0x06); 				// 显示光标移动设置
  Write_Instruction(0x0C); 				// 显示开及光标设置
}

//----------在指定位置显示一个字符----------
void LCD_DISP(unsigned char X, 
			  unsigned char Y, 
			  unsigned char Data)
{
	unsigned char temp;
	X&=0x0F;											//x位置范围是0~15
	Y&=0x01;											//y位置范围是0~1
	if(Y==0) temp=X;									//显示第一行
	else
	temp=X+0x40;
	temp|=0x80;
	Write_Instruction(temp);
	Write_Data(Data);
}
//-----------在指定位置显示一串字符---------
void DISP_STR(unsigned char X, 
			  unsigned char Y, 
			  unsigned char code *P)
{
  	unsigned char Length,j;
  	Length = strlen(P);									//计算字符长度
  	Y &= 0x1;
  	X &= 0xF; 											//限制X不能大于15,Y不能大于1
      if (X <= 0xF) 									//X坐标应小于0xF
        { 
		    for(j=0;j<Length;j++)
		     {
             	LCD_DISP(X,Y,P[j]); 					//显示单个字符
             	X++;
             }
        }
}



//=============以下是DS1302读写程序===========

//-------------实时时钟发送1字节----------- 
void sentbyte(unsigned char byte) 
{ 
	unsigned char bitcnt=8;
	while(bitcnt!=0)
	{
		CY=byte&0x01;
		byte=ACC;
		IO=CY;
        CLK = 1;
        CLK = 0;
		bitcnt--; 
  	}
}

//-------------实时时钟接收1字节--------------
unsigned char rcvbyte(void) 
{ 
    unsigned char bitcnt=8;
	while(bitcnt!=0)
	{
	    CY=IO;
		CY=ACC&0x01;
        CLK = 1;
        CLK = 0;
	bitcnt--;
    } 
    return(ACC); 
}

//---------------往DS1302写入数据-------------------
void write1302(unsigned char Addr, unsigned char Data)
{
    RST = 0;
    CLK = 0;
    RST = 1;
    sentbyte(Addr);       								// 地址,命令 
    sentbyte(Data);        								//写1Byte数据
    CLK = 1;
    RST = 0;
}

//---------------读取DS1302某地址的数据---------------
unsigned char read1302(unsigned char Addr)
{
    unsigned char temp;
    RST = 0;
    CLK = 0;
    RST = 1;
    sentbyte(Addr);            							//  地址,命令 
    temp = rcvbyte();          							//读1Byte数据 
    CLK = 1;
    RST = 0;
    return(temp);
}

//-------------延时----------------
void Delay(unsigned int n)
{
	while(n--);										//延时时间 ≈ (n*9+17)*12/fo
}													//n ≈ (t*fo/12-17)/9



⌨️ 快捷键说明

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