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

📄 12887(调试).c

📁 单片机对时钟芯片DS12887进行读写、显示
💻 C
字号:
#include<AT89X51.h>
#include<absacc.h>
#include<intrins.h>

#define   uchar        unsigned char
#define   uint         unsigned int
#define   nop()        _nop_()
#define   DATA_PORT    P0

#define  mca	XBYTE[0Xdf0a]                    //寄存器A的地址       
#define  mcb	XBYTE[0Xdf0b]                    //寄存器B的地址
#define  mcc	XBYTE[0Xdf0c]                    //寄存器C的地址
#define  mcd	XBYTE[0Xdf0d]                    //寄存器D的地址

sbit            ACC7=ACC^7;                      //判断DS12887是否处于更新周期
uchar code      settime[7]={7,8,24,5,19,44,0};     //07年8月23日星期四,14:29:00         //////////////////////1
uchar idata     gettime[7];                      //存储读出的时间
uchar           ad[7]= {9,8,7,6,4,2,0};            //年、月、日、星期、时、分、秒地址  //////////////////////6
uchar xdata     *addr=0xdf00;		             //片选地址

uchar           Time_Data[9];                    
uchar           Time_T[9];
uchar           Time_XQ[5];
bit             flag=0;                         //闪烁标志
bit             add_flag=0;
bit             dec_flag=0;
uchar           p;
uchar           count=0;
uchar           count1=0;

#define  COM8255  XBYTE[0x8003]              //命令口地址
#define  PA       XBYTE[0x8000]              //PA口地址
#define  PB       XBYTE[0x8001]              //PB口地址
#define  PC1      XBYTE[0x0002]              //PC口地址       //读操作
#define  PC2      XBYTE[0x8002]              //PC口地址       //写操作
bit      key_start=0;                        //键扫描标志位

/********************************************************
                     LCD函数声明
********************************************************/
uchar scan_key(void);
void shanshuo(void);
void writetime(uchar p,uchar add_flag,uchar dec_flag);

/****************************函数定义**************************************/

/********************************************************
                    LCD引脚定义
********************************************************/
#define       RS   P1_5  
#define       RW   P1_6     
#define       EN   P1_7 


/********************************************************
                     LCD程序声明
********************************************************/
void      WriteCom(uchar CMD);
void      WriteDat(uchar DAT);
void      Delay(uint ms);
uchar     CheckBusy(void);
void      Picture_Set_XY(uchar x, uchar y);
void      Char_Set_XY(uchar x, uchar y, uchar *p);
void      Lcd_Init(void);
void      clear(void);
void      Timer0_Init(void);


/************************************************
                  DS12887函数声明
************************************************/
void Initial_12887(void);
void readtime (void);
void DateToStr(uchar *gettime);
void TimeToStr(uchar *gettime);
void XQToStr(uchar *gettime);



void Timer0(void)  interrupt 1     //定时器1中断入口:50MS中断一次
   {
      TR0=0;  
      TH0=(65535-50000)/256;      //初值高字节
      TL0=(65535-50000)%256;      //定时初值低字节   
	  count++;
	  count1++;
	  if(count1==5)
   	  { readtime();                            //读DS12887时间
        DateToStr(gettime);
        TimeToStr(gettime);
        XQToStr(gettime);
        Char_Set_XY(3,1,Time_Data);            //显示年、月、日
	    Char_Set_XY(3,2,Time_T);               //显示时、分、秒
        //Delay(150);
		count1=0;
       }
    Delay(100);
     if(flag==1)            //&&count==20
	   shanshuo();
 	    TR0=1;                                 //开中断
 }
/***********************************************************
                      闪烁
***********************************************************/
void shanshuo(void)
{
	 //Char_Set_XY(0,0,"DS12887 时钟测试");
	 //Char_Set_XY(0,1,"Date:");
     //Char_Set_XY(0,2,"Time:");
//	 Delay(1000);
	 if(count==20)
   {       	
	 WriteCom(0x93);
     WriteDat(0x20);
     WriteDat(0x20);
	 count=0;
	 //if(count==20);
	   Delay(2000);
       
   } 
  
}    





 void int0() interrupt 0 
{ 
  key_start=1;
}
/***************************主函数*********************************/
                              
void main(void) 
{  

   
    uchar x=0;
	COM8255=0x81;
    EX0=1;                       //外部中断0允许控制位
    IT0=1;                       //外部中断0触发方式选择位:IT0=0为低电平触发,IT0=1为下降沿触发
	EA=1;                        //开总中断
    Lcd_Init();                            //LCD初始化
    
     clear();
	 Char_Set_XY(0,0,"DS12887 时钟测试");
	 Char_Set_XY(0,1,"Date:");
     Char_Set_XY(0,2,"Time:");
     //writetime();                        //设置时间___需要校正时间时才用
  	 Initial_12887();                      //DS12887初始化
     Timer0_Init();                        //定时器1初始化

while(1)
	{
      PC2=0x0f;            //键盘初始化
	  if(key_start==1)
	   { 
	     EA=0;
	     x=scan_key();
	     EA=1;

 	      WriteCom(0x98);
          WriteDat((x/10)+0x30);
          WriteDat((x%10)+0x30);
		  
		 if(x==1)  {flag=1;    	mcb=0x80;}	                          //SET=1,芯片停止工作,可初始化所有时标寄存器           ///进入数据设置模式
         Delay(100);
         if(x==2) { flag=0;    	mcb=0x00;}	                          //SET=1,芯片停止工作,可初始化所有时标寄存器         ///退出数据设置模式
         
         if(flag==1) 
  	       { Delay(100);
		   if(x==3)
		     { add_flag=1;
			   dec_flag=0;
			   p=0;
		       writetime(p,add_flag,dec_flag);
			  }
			 Delay(100);
		     if(x==4)
			 {
			   add_flag=1;
			   dec_flag=1;
			   p=1;
			   writetime(p,add_flag,dec_flag);
			 }
			 Delay(100);
 if(x==5)
			 {
			   add_flag=1;
			   dec_flag=1;
			   p=2;
			   writetime(p,add_flag,dec_flag);
			 }
			 Delay(100);
 if(x==6)
			 {
			   add_flag=1;
			   dec_flag=1;
			   p=3;
			   writetime(p,add_flag,dec_flag);
			 }
			 Delay(100);
 if(x==7)
			 {
			   add_flag=1;
			   dec_flag=1;
			   p=4;
			   writetime(p,add_flag,dec_flag);
			 }
			 Delay(100);
		  }
	      
	       
	
	   }///if		   	  
                      /////////////////////////////////////////	     
	}//while
} 







/*******************************LCD程序区****************************/
                    
/*************************************************
                   初始化函数
*************************************************/
void Lcd_Init(void)
{
 WriteCom(0x30);             //写指令:功能设置 8位数据,基本指令              
 WriteCom(0x0c);             //写指令:显示状态 ON,游标OFF,反白OFF                
 WriteCom(0x01);             //写指令:清除显示              
 WriteCom(0x02);             //写指令:地址归位                  
 WriteCom(0x80);             //写指令:设置DDRAM地址
 Delay(100);                 //延时
}


/*************************************************
                    延时函数
*************************************************/
void Delay(uint ms)             //延时ms毫秒
{
    uchar j;
    for(; ms>0; ms--)
     for(j=100; j>0; j--)
      {
       nop();
       nop();
      } 
}

/*************************************************
                  写控制字函数
*************************************************/
void WriteCom(uchar CMD)
{
 while(CheckBusy());            //测忙,若忙则等待
 RS = 0;                        //写控制字
 RW = 0;                        //写操作
 DATA_PORT = CMD;
 EN = 1;
 nop();
 nop();
 EN = 0;               //下降沿写入
}


/*************************************************
                    写数据函数
*************************************************/
void WriteDat(uchar DAT)
{
 while(CheckBusy());            //测忙,若忙则等待
 RS = 1;                        //写数据
 RW = 0;                        //写操作
 DATA_PORT = DAT;
 EN = 1;
 nop();
 nop();
 EN = 0;                 //下降沿写入
}

/*************************************************
                    测忙函数
*************************************************/
uchar CheckBusy(void)
{
 uchar temp;
 DATA_PORT =0xff;             //P0口置高,准备接收数据
 RS = 0;                      //读控制字
 RW = 1;                      //读操作
 EN = 1;
 nop();
 nop();
 temp = DATA_PORT;
 nop();
 nop();
 EN = 0;                      //下降沿读入
 temp &= 0x80;
 return(temp);                //若忙则返回1
}

/*************************************************
              置x,y坐标函数——写汉字
*************************************************/
void Char_Set_XY(uchar x, uchar y, uchar *p)
{
  if(y == 0)
   WriteCom((0x80+x)); 
  if(y == 1)
   WriteCom((0x90+x));
  if(y == 2)
   WriteCom((0x88+x));
  if(y == 3)
   WriteCom((0x98+x));
 while(*p != 0)
  WriteDat(*p++);
}


/*************************************************
                    清屏函数
*************************************************/
void clear(void)
{
  WriteCom(0x01);             //写指令:清除显示  
}



/***********************************DS12887程序区****************************************/

/*************************************************
                DS12887初始化函数
*************************************************/
void Initial_12887(void)
{
	mca=0x2f;		//中断周期50ms,SQW输出2HZ的方波
	ACC=mcc;		//读C寄存器,清零中断请求标志
	ACC=mcd; 		//读d寄存器, VRT=1,数据有效
	mcb=0x7f;		//允许中断,时标为二进制码,24小时方式 ,允许方波输出
	//EA=1;			//开中断
	//EX0=1;
}

/*************************************************
                DS12887时间设置函数
*************************************************/
void writetime(uchar p,bit add_flag,bit dec_flag)		              //设置时间
{    
	uchar max;
	uchar xdata  *address;
	mcb=0x80;	                          //SET=1,芯片停止工作,可初始化所有时标寄存器
    
    //*(addr+ad[p])+=1;
    switch(p)
	{ case 0: 
	   { address=addr+ad[p];
	   if(add_flag==1)  *address-=1;  }  break;
	   //else *address-=1;
	  case 1: 
	   { address=addr+ad[p];*address+=1; max=12;} break;
	  case 2: 
	   { address=addr+ad[p];*address+=1; max=31;} break;
	  case 3: 
	   { address=addr+ad[p]; *address+=1;max=7;} break;
	  case 4: 
	   { address=addr+ad[p];*address+=1; max=24;} break;
	  case 5: 
	   { address=addr+ad[p]; *address+=1;max=59;} break;
	}
	 
	
/* if(p==0){address=addr+ad[p];max=99;}
    if(p==1){address=addr+ad[p];max=12;}
    if(p==2){address=addr+ad[p];max=31;}
	if(p==3){address=addr+ad[p];max=7;}
    if(p==4){address=addr+ad[p];max=24;}
	if(p==5){address=addr+ad[p];max=59;}
	address=addr+ad[p];*/ 
     *address+=1;
   // if(add_flag==1)                             //依次写入 年、月、日、星期 、时、分、秒 的数据//////
	 // {
	   //if(*address>99)   *address=0;
       // else             *address+=1;
//	  }
   //else //if(dec_flag)
	//  {*address-=1;
	 // if(*address<0)     *address=max;
	  //  else             *address-=1;
      //} 
}

/*************************************************
                读DS12887时间
*************************************************/
void readtime(void)
{
	uchar i;
  do{                                     //判断DS12887是否处于更新周期
	  ACC=mca;
     }while(ACC7);	         	          //判断UIP位,若UIP为1,则处于更新周期,等待更新完
  for(i=0;i<7;i++)                        /////////////////////////////6
    gettime[i]=*(addr+ad[i]);	          //读时间,依次读入 年、月、日 、时、分、秒 的数据////////////
}

/*************************************************
       DS12887 年、月、日数据转换字符函数
*************************************************/
void DateToStr(uchar *gettime)
{
	Time_Data[0] = gettime[0]/10 + '0';
	Time_Data[1] = gettime[0]%10 + '0';
	Time_Data[2] = '-';
	Time_Data[3] = gettime[1]/10 + '0';
	Time_Data[4] = gettime[1]%10 + '0';
	Time_Data[5] = '-';
	Time_Data[6] = gettime[2]/10 + '0';
	Time_Data[7] = gettime[2]%10 + '0';
	Time_Data[8] = '\0';
}

/*************************************************
       DS12887 年、月、日数据转换字符函数
*************************************************/
void XQToStr(uchar *gettime)
{
   switch(gettime[3]) 
    { case  0x01:  Char_Set_XY(3,3,"星期一"); break;             //显示星期
      case  0x02:  Char_Set_XY(3,3,"星期二"); break;
      case  0x03:  Char_Set_XY(3,3,"星期三"); break;
      case  0x04:  Char_Set_XY(3,3,"星期四"); break;
      case  0x05:  Char_Set_XY(3,3,"星期五"); break;
      case  0x06:  Char_Set_XY(3,3,"星期六"); break;
      case  0x07:  Char_Set_XY(3,3,"星期日"); break; 
    }
}


/*************************************************
       DS12887 时、分、秒数据转换字符函数
*************************************************/
void TimeToStr(uchar *gettime)
{
	Time_T[0] = gettime[4]/10 +'0';
	Time_T[1] = gettime[4]%10 + '0';
	Time_T[2] = ':';
	Time_T[3] = gettime[5]/10 + '0';
	Time_T[4] = gettime[5]%10 + '0';
	Time_T[5] = ':';
	Time_T[6] = gettime[6]/10 +'0';
	Time_T[7] = gettime[6]%10 +'0';
	Time_T[8] = '\0';
}
/*************************************************
   定时器0:每秒从DS12887中读取20次数据,更新显示 
*************************************************/
void Timer0_Init(void)        //定时器1初始化:50毫秒定时,预分频256
{ 
   TR0=0;                     //停止定时器
   TMOD = 0x01;               //工作方式1
   TH0 = (65535-50000)/256;   //初值高字节
   TL0=(65535-50000)%256;     //定时初值低字节        
   EA = 1;
   ET0=1;
   TR0=1;                    //启动定时器
}

/****************************键盘扫描程序区****************************/

/************************************************
              键盘扫描子程序
************************************************/
uchar scan_key(void)
{
 
  uchar i,j,temp_i,temp_j,key_value;
  uchar a,b;                            //中间变量    
  temp_i=0x10;
  temp_j=0x01;
  PC2=0x0f;
  a=PC1;
  if((a&0x0f)!=0x0f)
   {
    Delay(10);//////////////////////////////////////////////20
	a=PC1;
    if((a&0x0f)!=0x0f)
	 for(i=0;i<4;i++)
	  for(j=0;j<4;j++)
	   { 
		 b=~(temp_i<<i);
		 PC2=b;
		 a=PC1;
		 if((a&(temp_j<<j))==0)
		  key_value=i*4+j+1;
       }
	 }
     
      key_start=0;                ///////////////////////////键标志位清零
     return key_value;
	
}

⌨️ 快捷键说明

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