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

📄 程序.txt

📁 采用DS12C887做时钟
💻 TXT
字号:
#include <REGX51.H>
#include <INTRINS.H>
#include <ABSACC.H >
 
#define TM_second  XBYTE[0x7f00]     //秒
#define TM_minute  XBYTE[0x7f02]     //分
#define TM_hour    XBYTE[0x7f04]     //时
#define TM_day     XBYTE[0x7f07]     //日
#define TM_month   XBYTE[0x7f08]     //月
#define TM_year    XBYTE[0x7f09]     //年(显示2位)
#define REG_a     XBYTE[0x7f0a]      //寄存器A
#define REG_b     XBYTE[0x7f0b]      //寄存器B
#define REG_c     XBYTE[0x7f0c]      //寄存器C
#define REG_d     XBYTE[0x7f0d]      //寄存器D

unsigned char  clock[8];
unsigned char  calendar[8];
unsigned char  time_buf[7];
unsigned char  time_buf1[7];
unsigned char  displaybit[]={0xfe,0xfd,0xfb,0xf7,          //位显代码 
                               0xef,0xdf,0xbf,0x7f}; 
unsigned char code displaycode[]={0xfc,0x60,0xda,0xf2,     //数码管显示代码
                                    0x66,0xb6,0xbe,0xe0, 
                                    0xfe,0xf6,0x77,0x7c, 
                                    0x39,0x5e,0x79,0x71,0x00,0x02}; 

unsigned char  displaycount=0; n=0; ds=0; z=0; 
unsigned char displaybuf[8]={16,16,16,16,16,16,16,16}; 
unsigned int  timecount=0, timecount1=0, timecount2=0,c=0; 
unsigned char  readdata[8];
unsigned long  a, aa, bb; 
sbit DQ=P3^5;     //选P3.5口与DS18B20的数字信号输出端DQ相连 
bit sflag; 


bit resetpulse(void)     //DS18B20初始化实现对DS18B20的复位
{   
unsigned char pre;          
  unsigned char i; 
  DQ=0;     //发出复位脉冲,将数据线下拉480μS-960μS 
  for(i=255;i>0;i--); 
  DQ=1;     //DS18B20等待15μS-60μS 
  for(i=60;i>0;i--); 
  pre=DQ; 
    for(i=200;i>0;i--);
    return(pre);     // DS18B20返回60μS-240μS存在低脉冲,判断是否准备好接受或发送数据 
}


void writecommandtods18b20(unsigned char command)     //写时序 
{ 
     unsigned char i,j; 
     for(i=0;i<8;i++) 
       { 
          if((command & 0x01)==0)     //写0时序 
            {                   
              DQ=0;     //拉低单总线至少60μS,保证DS18B20在15μS-45μS时可以正确地采样I/O总线上的低电平
for(j=35;j>0;j--); 
              DQ=1; 
            } 
          else     //写1时序  
           { 
              DQ=0;     //拉低单总线后,在15us之内就得释放
              for(j=2;j>0;j--); 
              DQ=1; 
              for(j=33;j>0;j--); 
           } 
          command=_cror_(command,1);      
        } 
} 

unsigned char readdatafromds18b20(void)     //读时序  
{ 
unsigned char i,j; 
    unsigned char temp; 
    temp=0; 
    for(i=0;i<8;i++) 
      { 
        temp=_cror_(temp,1); 
        DQ=0;     //单总线拉低后,读时序开始 
        _nop_(); 
        _nop_(); 
        DQ=1;     //停止将数据线拉低,以读取数据
        for(j=10;j>0;j--); 
        if(DQ==1) 
          { 
            temp=temp | 0x80; 
           } 
       else 
         { 
            temp=temp | 0x00; 
          } 
       for(j=200;j>0;j--); 
    } 
  return(temp); 
}


void settime()       //DS12B887设置系统时间
{
     REG_b=0xfe;     //B寄存器 SET位置1使芯片停止工作,才可以初始化各个时标寄存器;采用二进制码,24小时工作制,不使用夏令时
     TM_second =time_buf[0];
     TM_minute=time_buf[1];
     TM_hour=time_buf[2];
     TM_day=time_buf[4];
     TM_month=time_buf[5];
     TM_year=time_buf[6];
     REG_b=0x7e;     // SET位清0芯片正常工作,停止初始化
}

void readtime()     // DS12B887读取系统时间
{   
unsigned char  c;
do{ c=REG_a;} while((c&0x80)==0x80);     //A寄存器的UIP位为1时,芯片处于或即将开始更新,程序不可读写时标寄存器

time_buf[0]=TM_second;
    time_buf[1]=TM_minute;
    time_buf[2]=TM_hour;
    time_buf[4]=TM_day;
    time_buf[5]=TM_month;
    time_buf[6]=TM_year;
}


void delay(void)     //延时
{
unsigned char a,b;
	 for(a=0;a<225;a++)
 	  {
		  for(b=0;b<200;b++);
	  }
}


void main(void) 
{ 
TMOD=0x01; 
    TH0=(65536-2000)/256; 
    TL0=(65536-2000)%256; 
  
    ET0=1; 
    EA=1;
    EX1 = 0;
    REG_a=0x2f;     // A寄存器的DV0-DV2位置为010,启动芯片内部振荡器RTC
    readtime();   
    settime();  
    TR0=1; 
    while(1)
      {   
if(timecount2==c+1)      //设置相应变量,有中断程序执行时主程序才读取一次温度值,避免频繁的读取数据对数码管显示造成的影响

   { 
readtime();c++;
} 
clock[7]=time_buf[0]%10;     //数字钟赋值
clock[6]=time_buf[0]/10;
 		  clock[5]=17;                //显示中间横杆
clock[4]=time_buf[1]%10;
 		  clock[3]=time_buf[1]/10;
 		  clock[2]=17;     
clock[1]=time_buf[2]%10;
clock[0]=time_buf[2]/10;
 		 
	 	  calendar[7]=time_buf[4]%10;   //日历赋值
 		  calendar[6]=time_buf[4]/10;
         calendar[5]=17;
 		  calendar[4]=time_buf[5]%10;  
calendar[3]=time_buf[5]/10; 
calendar[2]=17;
  		  calendar[1]=time_buf[6]%10; 
calendar[0]=time_buf[6]/10;

 	      if(P3_0==0)     // P3.0——显示切换键,ds=0:显示时钟;
ds=1:显示日历;
ds=2:显示温度
           {  
		      delay(); while(!P3_0); delay();
             ds++;
             if(ds==3){ds=0;}
           }

         if(ds==0)     //按键改变时钟时、分、秒值
          {
		      if(P3_1==0)     // P3.1——调时调分调秒切换键,z=1:调时;
z=2:调分;
z=3:调秒
               { delay();while(!P3_1);delay();z++;}
	          switch(z)
	            {  case 1: if(P3_2==0)     // P3.2——时分秒值增加键
{ delay();
while(!P3_2);delay();time_buf[2]++;
if(time_buf[2]==24){time_buf[2]=0;}
settime();
}
if(P3_3==0)     // P3.3——时分秒值减小键

{ delay();
while(!P3_3);delay();time_buf[2]--;
if(time_buf[2]==0){time_buf[2]=23;}
settime();
}
break;
                   case 2: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[1]++;
if(time_buf[1]==60){time_buf[1]=0;}
settime();
}
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[1]--;
if(time_buf[1]==0){time_buf[1]=59;}
settime();
}
break;
                    case3: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[0]++;
if(time_buf[0]==60){time_buf[0]=0;};
settime();
}
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[0]--;
if(time_buf[0]==0){time_buf[0]=59;}
settime();
}
break;
				 }
             if(z==4){z=0;}
		  }

       if(ds==1)     //按键改变日历年、月、日值
         {
		     if(P3_1==0)
               { delay();while(!P3_1);delay();z++;}
            switch(z)
               {
Case 1: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[6]++;settime();
}
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[6]--;
if(time_buf[6]==0){time_buf[6]=99;}
settime();
}
break;
                case 2: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[5]++;
if(time_buf[5]==13){time_buf[5]=0;};
settime();
}
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[5]--;
if(time_buf[5]==0){time_buf[5]=12;}
settime();
}
break;
                case 3: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[4]++;
if(time_buf[4]==32){time_buf[4]=0;}
settime();
};
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[4]--;
if(time_buf[4]==0){time_buf[4]=31;}
settime();
}
break;
			   }
             if(z==4){z=0;}
}
         }
}
 

void t0(void) interrupt 1 using 0 
{ 
  unsigned char x; 
  unsigned int result; 
  
  TH0=(65536-2000)/256;     //定时2ms  
  TL0=(65536-2000)%256; 
  c=timecount2;     //设置相应变量,有中断程序执行时主程序才读取一次温度值
  timecount2++;

  if(ds==2)     //温度功能设定
    {  
	    if(displaycount==2)     //温度值个位显示小数点 
          { 
            P1=displaycode[displaybuf[displaycount]] | 0x01; 
          } 
        else 
          { 
            P1=displaycode[displaybuf[displaycount]]; 
          }
	}

   if(ds==0)
     {
	    P1=displaycode[clock [displaycount]];
	 }

   if(ds==1)
     {
		P1=displaycode[calendar[displaycount]];
	  }
 
   P2=displaybit[displaycount]; 
   displaycount++; 
   if(displaycount==8) 
     { 
        displaycount=0; 
     }
   timecount++;  timecount1++;

if(timecount1==250)     //若P3.1调时调分调秒切换键按下,则每0.5s对应修改位的数值熄灭,实现闪烁显示
	  {
	     switch(z)
	       {  case 1:displaybit[0]=0xff;displaybit[1]=0xff;break;
	          case 2:displaybit[3]=0xff;displaybit[4]=0xff;break;
	          case 3:displaybit[6]=0xff;displaybit[7]=0xff;break;
			}
	  }

if(timecount1==500)
	  {  
switch(z)
	       {  case 0:displaybit[6]=0xbf;displaybit[7]=0x7f;break;
	          case 1:displaybit[0]=0xfe;displaybit[1]=0xfd;break;
	          case 2:displaybit[0]=0xfe;displaybit[1]=0xfd;
displaybit[3]=0xf7;displaybit[4]=0xef;break;
	          case 3:displaybit[0]=0xfe;displaybit[1]=0xfd;
displaybit[3]=0xf7;displaybit[4]=0xef;
displaybit[6]=0xbf;displaybit[7]=0x7f;break;
	       }
	     timecount1=0;
	   }

   if(timecount==250)     //每0.5s读取一次温度值 
     {  
	    timecount=0;
	    if(ds==2) 
         {
		     while(resetpulse());     //写前调用初始化程序对DS18B20复位
writecommandtods18b20(0xcc);     //单片DS18B20工作,跳过读ROM中64位地址的过程 
            writecommandtods18b20(0x44);     //启动DS18B20进行温度转化,将结果存入内部RAM中
	 
            while(resetpulse());     //写前调用初始化程序对DS18B20复位
            writecommandtods18b20(0xcc);     
            writecommandtods18b20(0xbe);     // 读DS18B20RAM中温度数据	 
            readdata[0]=readdatafromds18b20();     //温度数据低8位赋值 
            readdata[1]=readdatafromds18b20();     //温度数据高8位赋值 
	  
 	         for(x=0;x<8;x++) 
              { 
                displaybuf[x]=16; 
              } 
            sflag=0; 
            if((readdata[1] & 0xf8)==0x80)     //温度数据高5位为1时,温度为负值 
              { 
                 sflag=1; 
                 readdata[1]=~readdata[1];     //对负温度值进行取反加1操作 
                 readdata[0]=~readdata[0]; 
result=readdata[0]+1; 
                 readdata[0]=result; 
                 if(result>255) 
                   { 
                      readdata[1]++; 
                   } 
               }
		
		      if(sflag==1)     //若为负温度,数码管首位显示负号
			    {  
				   displaybuf[0]=17;
				 }
		      readdata[1]=readdata[1]&0x07;     //将代表符号的高5位数屏蔽
			   aa=625;bb=(readdata[1]*256+readdata[0]);
		      a=bb*aa;     //计算实际温度值
	
	         displaybuf[1]=a/100000;     //给各显示位赋温度值
		      displaybuf[2]=a%100000/10000;
		      displaybuf[3]=a%10000/1000;
			  displaybuf[4]=a%1000/100;
			  displaybuf[5]=a%100/10;
			  displaybuf[6]=a%10;
	       }
     } 
}

⌨️ 快捷键说明

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