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

📄 main.c

📁 基于12887和80c52的时钟程序
💻 C
字号:
#include "include.h"
#include "ds12887.h"
#include "p8255.h"

#define open 0x00//打开所有显示位
#define close 0xff//关闭所有显示位
#define first_open 0xdf//显示秒个位
#define secon_open 0xef//显示秒十位
#define three_open 0xf7//显示分个位
#define four_open 0xfb//显示分十位
#define five_open 0xfd//显示时个位
#define six_open 0xfe//显示时十位才                        


uchar code d2q[]={0x7b,0X30,0Xea,0Xf8,0Xb1,0Xd9,0XDB,0X70,0Xfb,0Xf9};//十进制转换为七段码

uchar data time[7];//时间缓冲
uint data tem;//温度缓冲
uchar data thl1;//定时器1初值

uchar data timch_bitchoose=0;//调时位选
uchar data t1_intrup_time=0;//T1中断次数,用于闪动1分自动退出调时状态
uchar data flash_T=0;//记录一个闪动周期动态显示的次数,用于闪动周期的占空比


/////////////////数码管的闪动亮灭的开关控制变量//////////////////
uchar data six_flash=open;//控制第六位数码管的闪动灭
uchar data five_flash=open;//控制第五位数码管的闪动灭
uchar data four_flash=open;//
uchar data three_flash=open;
uchar data secon_flash=open;//控制第二位数码管的闪动灭
uchar data first_flash=open;//控制第一位数码管的闪动灭



uchar data flash_time=0;//在调时状态下无操作时由调时状态自动退出前闪动的时间
uchar data showtime=0;//控制是显示时间(0)还是显示日期(4)
bit bdata leapyear=0;//记录是否闰年 闰年=1
uchar data showpoint=0x00;//控制在显示日期时显示数点

//中断函数
void Int0_timeset_bit(void);//调时位选
void T1_sec_end(void);//定时50ms,中断响应从12887读取时间送入缓冲区
void T0_time_set(void);//调时值设置,加1


void display(); //显示
void delay(uchar data x);//延迟 x ms
uchar BCD2BIN(uchar data BCD);
uchar BIN2BCD(uchar data BIN);
void keyscan();//扫描8255 C口 键盘,进而判断是显示时间(showtime=0)还是显示日期(showtime=4)
void if_leapyear();//判断是否闰年
//void Init();



main()
{
 

  P8255Con=0x88;//A口方式0输出,B口方式0输出,C口高四位输入,低四位输出
  P8255Con=0x88;

  TMOD=0X16;//0001 0110,定时器0采用外部计数方式2,定时器1采用定时方式1
  TH0=0xfe;
  TL0=0XFE;//定时初值,定时器0计1满
  thl1=15536;//定时器1定时50ms
  
  IT0=1;//INT0中断采用下降沿
  IT1=1;//INT1中断采用下降沿
  
  EX0=1;//外部中断0允许
  EX1=1;//外部中断1允许
  ET0=1;//定时中断0允许
  ET1=1;//定时中断1允许
  EA=1;//总中断允许
  
  PT0=0;
  PT1=1;//读取时间函数为最高优先级
  PX0=0;
  PX1=0;

  TR0=1;//开启定时器0
  TR1=1;


 P8255Con=0x88;//A口方式0输出,B口方式0输出,C口高四位输入,低四位输出
 P8255Con=0x88;
 //P1=0X00;

  
 //SetTime(BIN2BCD(00),BIN2BCD(38),BIN2BCD(17));
 //SetDate(0x26,0x06,0x07);

 
 while(1)
  {
   keyscan();//确定显示时间还是日期
   display();//显示
  }

}



//////////////////调时位选////////////////////////

void Int0_timeset_bit(void) interrupt 0 using 1//调时位选
{
  timch_bitchoose++;//调时位的移位

  if(timch_bitchoose==4)//退出调时状态
    timch_bitchoose=0;
 
//根据要调时的位确定各个闪动开关变量的开与闭
  switch(timch_bitchoose)
     {
	  case 0:six_flash=0x00;five_flash=0x00;three_flash=0x00;four_flash=0x00;secon_flash=0x00;first_flash=0x00;break;//不是调时状态
	  case 1:six_flash=0x00;five_flash=0x00;three_flash=0x00;four_flash=0x00;secon_flash=0xff;first_flash=0xff;break;//调秒,闪
	  case 2:six_flash=0x00;five_flash=0x00;three_flash=0xff;four_flash=0xff;secon_flash=0x00;first_flash=0x00;break;//调分,闪
	  case 3:six_flash=0xff;five_flash=0xff;three_flash=0x00;four_flash=0x00;secon_flash=0x00;first_flash=0x00;break;//调时,闪
	 }   
 
}


/////////////////////每50ms从128887读取时间,从ds1820读取温度写入缓冲区//////////////////

void T1_sec_end(void) interrupt 3 using 3//
{ uchar data i;
  
  thl1=15536;//重新赋初值
  t1_intrup_time++;
  if(t1_intrup_time==20)//满1秒钟
   {
	t1_intrup_time=0;
	flash_time++;

	if(flash_time==30)//在调时状态时,如果不操作,则30秒后自动退出调时状态
	  {
	   flash_time=0;
	   timch_bitchoose=0;
	  }
	}
//从12887读取时间送缓冲区
  time[0]=GetSeconds();
  time[1]=GetMinutes();
  time[2]=GetHours();
  time[3]=GetDay();
  time[4]=GetDate();
  time[5]=GetMonth();
  time[6]=GetYear();
//从ds1820读取温度
  tem=ReadTemperature();
//将BCD码转换为二进制
for(i=0;i<7;i++)
  time[i]=BCD2BIN(time[i]);
  
}

/****************调时状态时,时间修改**************************/

void T0_time_set(void) interrupt 1 using 2//调时值设置
{ 
  flash_time=0;//保证从调时状态自动返回的前提是无调时操作
  
  switch(timch_bitchoose)
     {
	  case 0:break;
	  case 1:if(showtime==4)
	            time[0+showtime]++;//调日,
				else
				   time[0+showtime]=0;//调秒清零
				break;
	  case 2:time[1+showtime]++;break;//调分或月
	  case 3:if(showtime!=4||time[6]!=99)//
                time[2+showtime]++;
             else
                time[2+showtime]=0;
             break;//调时或年
	 }
 if(time[0]>=60)//调秒防溢出
	 time[0]=0;	 
 if(time[1]>=60)//调分防溢出
	 time[1]=0;
 if(time[2]>=24)//调时防止溢出
    time[2]=0;
 if(time[3]>=8)//调星期防止溢出
    time[3]=1;
 if(time[5]>=13)//调月防止溢出
    time[5]=1;
   
//调日期防止溢出
 if(time[5]==1||time[5]==3||time[5]==5||time[5]==7||time[5]==8||time[5]==10||time[5]==12)//含31天的月份
    {
	   if(time[4]>=32)
	      time[4]=0;
	 }
 else 
    {
     if(time[5]==4||time[5]==6||time[5]==9||time[5]==11)//30天的月份
         {
			 if(time[4]>=31)
	         time[4]=0;
			}
	 else                          //二月是28天还是29天
	      {
			 if_leapyear();//判断是否闰年,闰年时leapyear=1
			 if(leapyear==1)//是闰年
			   {
			    if(time[4]>=30)
	            time[4]=0;
			   }
             else//不是闰年
               {
			     if(time[4]>=29)
	               time[4]=0;
				}

    	  }
	      
    }

 
 //将调时后的时间日期写入12887
 if(showtime==0)//当前状态是显示时间状态
    SetTime(BIN2BCD(time[0])/*秒*/,BIN2BCD(time[1])/*分*/,BIN2BCD(time[2]))/*时*/;
 else//当前状态是显示日期
    SetDate(BIN2BCD(time[4])/*日*/,BIN2BCD(time[5])/*月*/,BIN2BCD(time[6]))/*年*/;
  
}



//////////////////////////动态显示时间日期/////////////////////////////
 
 void display() //显示时间
{
 uchar data six,five,four,three,secon,first;
 //将要显示的数字的各位分离
 six=time[2+showtime]/10;
 five=time[2+showtime]%10;
 
 four=time[1+showtime]/10;
 three=time[1+showtime]%10;

 secon=time[0+showtime]/10;
 first=time[0+showtime]%10;

 //将二进制数转换为七段码
 six=d2q[six];
 five=d2q[five];
 four=d2q[four];
 three=d2q[three];
 secon=d2q[secon];
 first=d2q[first];

  if(showtime==4)//当前状态是显示日期
      showpoint=0x04;//显示日期时显示数点
  else//当前状态是显示时间
      showpoint=0x00;//显示时间时不显示数点

  if(timch_bitchoose==0)//确保不在调时状态时关闭闪动开关变量使不闪
  {
   six_flash=0x00;
   five_flash=0x00;
   three_flash=0x00;
   four_flash=0x00;
   secon_flash=0x00;
   first_flash=0x00;   
  }

  if(flash_T<=15)//若在调时状态,闪,灭   
    {
     P8255B=close;
     P8255A=six;
     P8255B=six_open|six_flash;
     delay(3);

     P8255B=close;
     P8255A=five|showpoint;//显示日期时显示年与月之间的隔点
     P8255B=five_open|five_flash;
     delay(3);

     P8255B=close;
     P8255A=four;
     P8255B=four_open|four_flash;
     delay(3);

     P8255B=close;
     P8255A=three|showpoint;//显示日期时显示月与日之间的隔点
     P8255B=three_open|three_flash;
     delay(3);

     P8255B=close;
     P8255A=secon;
     P8255B=secon_open|secon_flash;
     delay(3);

     P8255B=close;
     P8255A=first;
     P8255B=first_open|first_flash;
     delay(3);
    }
 else//若在调时状态,闪,亮
   {    
     P8255B=close;
     P8255A=six;
     P8255B=six_open;
     delay(3);

     P8255B=close;
     P8255A=five|showpoint;//显示日期时显示年与月之间的隔点
     P8255B=five_open;
     delay(3);

     P8255B=close;
     P8255A=four;
     P8255B=four_open;
     delay(3);

     P8255B=close;
     P8255A=three| showpoint;//显示日期时显示月与日之间的隔点
     P8255B=three_open;
     delay(3);

     P8255B=close;
     P8255A=secon;
     P8255B=secon_open;
     delay(3);

     P8255B=close;
     P8255A=first;
     P8255B=first_open;
     delay(3);
   }

	flash_T++;//flash_T 记录一个闪动周期内动态显示的次数
 
   if(flash_T==50)//一个闪动周期内动态显示50次,闪动周期大于 50*(3*6)ms
      flash_T=0;
 }


/*************时间延迟***************************/
void delay(uchar data x)//x为要延迟的时间ms级
{
 uchar data j;
 while (x-->0)
 {
  for(j=0;j<125;j++) // 延迟的时间1ms
   {;}
 }
}

/*********************进制转换***************************/
uchar BCD2BIN(uchar data BCD)
{
	unsigned char data tem=0;
	tem=BCD&0x0f;
	BCD=BCD>>4;
	tem+=BCD*10;
	return tem;
}


uchar BIN2BCD(uchar data BIN)
{
 uchar data shi,ge,BCD;
 shi=BIN/10;
 ge=BIN%10;
 shi=shi<<4;
 BCD=shi|ge;
 return BCD;   
}

/************************************************/


/////////////////////判断是否闰年////////////////////
void if_leapyear()
{
 uchar data year;
 year=2000+time[6];
 if(year%4!=0)
   leapyear=0;
 else if(year%100!=0)
   leapyear=1;
 else if(year%400!=0)
   leapyear=0;
 else
   leapyear=1;
}
////////////////////////////键盘输入控制显示时间还是显示日期/////////////////////////
void keyscan()
{
  P8255C=0Xc0;
 if((P8255C&0xc0)!=0xc0)
   {
    delay(5);
    if((P8255C&0xc0)!=0xc0)
      {
       if(showtime==0)
          showtime=4;//显示日期
       else
          showtime=0;//显示时间
      }
   }
	while((P8255C&0xc0)!=0xc0) //防止一次按键,多次响应
	    P8255B=0XFF;
}
/*
//////////////////初始化函数///////////////
void Init()//定时器。中断的初始化
{
	TMOD=0X16;//0001 0110,定时器0采用外部计数方式2,定时器1采用定时方式1
    
    TH0=0xfe;
    TL0=0XFE;//定时初值,定时器0计1满

    thl1=15536;//定时器1定时50ms
	//12M Hz 晶振

    EX0=1;//外部中断0允许
    EX1=1;//外部中断1允许
    ET0=1;//定时中断0允许
    ET1=1;//定时中断1允许
 

	IT0=1;
	IT1=1;//外部中断触发方式	

	TR1=1;      //T1运行
	TR0=1;      // T0 运行


	P8255Con=0x88; //初始化8255 A口输入检测数据 0x82

	EA=1;  //开中断
}
*/	

⌨️ 快捷键说明

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