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

📄 souce.txt

📁 基于51单片机的电子万年历,用C51编写的程序.利用4乘5键盘进行调时,具有闹钟功能
💻 TXT
字号:



#include <reg51.h>
#include <intrins.h>
#include <absacc.h>

#define uchar unsigned char
#define PA XBYTE[0x9000]
#define PB XBYTE[0x9100]
#define PC XBYTE[0x9200]
#define PS XBYTE[0x9300]//8255控制口地址
#define PD XBYTE[0x8800]//138地址
#define bell XBYTE[0x8000]

bit zd_flag;//整点报时标志
uchar zd_counter;//整点计数器2秒
bit bell_flag;
bit alarm_d,alarm_flag;
uchar counter_a;//闹钟报警时间计数
uchar alarm_arry[7]={0};
uchar Time[7]={7,8,28,20,50,10,2};        //时间数组
uchar counter_0=0;                    //调时位计数器

bit Flag;                        //1秒时间到
bit ren_year;                     //是否是闰年标志

uchar bcd_arry[2]={0,0};
uchar code_sure;//调时送数码
uchar arry_num;//调时数组号码


sbit RS=P3^2;//LCM控制口
sbit RW=P3^3;
sbit E=P3^4;
sbit P17=P1^7;
uchar s_char3[9]={'f','i','g','h','t','i','n','g','\0'};
uchar s_char1[6]={'h','a','p','p','y','\0'};//字符串
uchar s_char2[5]={'w','e','e','k','\0'};

//***************key
uchar lock_key();
bit key_check();
uchar get_key_code();
bit lock_status=1;
uchar m_code=0;
uchar lock_code;
uchar s_lock_code=17;//密码
//void delay_key(unsigned int N);
//88888888888888      LCM
void lcm_init();
void w_commend(uchar commend);//写入命令
void busy();//忙判断
void w_data(uchar _data);//写数据
void w_s_char(uchar n,uchar char_arry[5]);//写字符串
void r_ac_add();//读取LCM中的ACC地址
void find_add();//查找调时位以闪烁光标提示
//8888888888888888888888
void time_change();
void bcd_turn(uchar x);//BCD转换
void sipo(uchar s_buffer_arry[7]);//输出程序
void timer0();
void counter_0_d();//计数器处理程序

void time_set();
void month_28();
bit year_deal();
uchar month_deal();
void delay50ms();

void time_set();
void time_send();
void time_set_10(uchar i);
void time_set_ge(uchar i);

void alarm_set();
bit time_time();
void alarm_deal();

void main()
{
 TMOD=0x22;
 TH0=0x1a;
 TL0=0x1a;
 ET0=1;
 EA=1;
 TR0=1;//T0初始化

 PS=0x9b;//8255初始化
 
 
 lcm_init();
lcm_init();
 for(;;)
 {
  
 bell=0xff;
  switch(lock_key())
  {
   case 15:time_set();break;//进入调时
   case 19:alarm_set();break;//进入闹钟设置
  }
  if(time_time()!=1)
  alarm_deal();
  if(zd_flag==1)
  {
  if(zd_counter<1)//报时
bell=0;
else
{
zd_counter=0;
zd_flag=0;
bell=0xff;
}
}
   w_commend(0x0c);//关光标
   sipo(Time);

   
 }
}

/*==================时间更新=====================*/
void time_change()
{ 
   Time[5]=Time[5]+1;
   if(Time[5]>59)
   {
    Time[4]=Time[4]+1;
    Time[5]=0;
    if(Time[4]>59)
    {
     Time[3]=Time[3]+1;    /*时分秒日进位*/
     Time[4]=0;
     if(Time[3]>23)
     {
      Time[2]=Time[2]+1;
      Time[3]=0;
      if(Time[2]==month_deal()+1)
      {
       Time[1]=Time[1]+1;
       Time[2]=1;
       if(Time[1]>12)
       {
        Time[0]=Time[0]+1;
        Time[1]=1;
        if(Time[0]>99) Time[0]=0;
       }
      }    
     }
    }
   }
if(Time[5]==59&&Time[4]==59&&Time[3]==23)//week
{
 Time[6]=Time[6]+1;
if(Time[6]>7)
Time[6]=1;
}
if(Time[5]==0&&Time[4]==0)
zd_flag=1;



}




/*==========显示程序============*/

void sipo(uchar s_buffer_arry[7])
{ 
 uchar i;
w_commend(0xc9);
 w_s_char(5,s_char1);//显示happy
 w_commend(0x89);
 w_s_char(4,s_char2);//显示字符week
w_commend(0x8d);
w_data(s_buffer_arry[6]+0x30);
//bcd_turn(s_buffer_arry[6]);//先进行BCD转换
 
 //w_data(bcd_arry[1]+0x30);
 w_commend(0x80);
 for(i=0;i<6;i++)
 {
 if(i<3)//显示年月日
 {
 bcd_turn(s_buffer_arry[i]);//先进行BCD转换
 w_data(bcd_arry[0]+0x30);
 w_data(bcd_arry[1]+0x30);
 if(i<2)// 最后一个不显示间隔符
 w_data(0x2d);//间隔符
 
 }
 else//第二行显示时间
 {
  
  if(i==3)
  w_commend(0xc0);

  bcd_turn(s_buffer_arry[i]);
  w_data(bcd_arry[0]+0x30);//先进行BCD转换
  w_data(bcd_arry[1]+0x30);
  if(i<5)
  w_data(0x3a);//间隔符
  
  }

 }

}



/*========================T0中断=============================*/
void timer0() interrupt 1 
{
 unsigned int sndacc;  /*秒累加器*/
 sndacc=sndacc+1;
 if(sndacc==4000)
 {
  Flag=1;
  sndacc=0;
 
bell_flag=!bell_flag;
if(zd_flag==1)
zd_counter=zd_counter+1;
  if(alarm_d==1)
  counter_a=counter_a+1;
time_change();
Flag=0;
 }
}



/*====================timeset======================*/
void time_set()
{
if(alarm_flag!=1)//如果不是闹钟时间设置,则停止定时器工作
TR0=0;
do
  {
  while(key_check()==0);/**********等待下一个键按下,避免虚跳********/

 switch(get_key_code())
  {
   case 14:{find_add();time_send();};break;
   case 13:counter_0=0;break;
   case 15:{counter_0_d();w_commend(0x0e);/*sipo(Time);*/find_add();};break;//关光标闪烁
  }
  //while(key_check()==0);/**********等待下一个键按下,避免虚跳********/
 
  if(get_key_code()<10)
  {
  w_commend(0x0e);
  code_sure=get_key_code();//对输入调时数字的处理
  find_add();
  w_data(code_sure+0x30);
  }
  }
  while(counter_0!=0);
TR0=1;
lcm_init();
 
}
//****************计数器处理counter_0_d******************************
void counter_0_d()
{
  counter_0=counter_0+1;
 if(counter_0>13)
counter_0=1;

}
/*
//***********************************判断输入数字是否合理
bit judge_time()
{
 
 if((Time[0]>99||Time[1]>12||Time[2]>month_deal()||Time[3]>23||Time[4]>59||Time[5]>59)==1)

 return 0;
 else
 return 1;
}
*/
 
//********************time_send***************************
void time_send()
{
 switch(counter_0)
 {
  case 1:{arry_num=0;time_set_10(arry_num);};break;
  case 2:{arry_num=0;time_set_ge(arry_num);};break;
  case 3:{arry_num=1;time_set_10(arry_num);};break;
  case 4:{arry_num=1;time_set_ge(arry_num);};break;
  case 5:{arry_num=2;time_set_10(arry_num);};break;
  case 6:{arry_num=2;time_set_ge(arry_num);};break;
  case 7:{arry_num=6;time_set_ge(arry_num);};break;
  case 8:{arry_num=3;time_set_10(arry_num);};break;
  case 9:{arry_num=3;time_set_ge(arry_num);};break;
  case 10:{arry_num=4;time_set_10(arry_num);};break;
  case 11:{arry_num=4;time_set_ge(arry_num);};break;
  case 12:{arry_num=5;time_set_10(arry_num);};break;
  case 13:{arry_num=5;time_set_ge(arry_num);};break;
  
 }
}

//**********************time_set_10(uchar i)***************************
void time_set_10(uchar i)       //当调时位为10位时的处理智育
{
 if(alarm_flag==1)//进入了设置闹钟时间
 alarm_arry[i]=alarm_arry[i]%10+10*code_sure;
 else
 Time[i]=Time[i]%10+10*code_sure;
}
 //********************time_set_ge(uchar i)**********************************
void time_set_ge(uchar i)
{
 if(alarm_flag==1)
 alarm_arry[i]=alarm_arry[i]-alarm_arry[i]%10+code_sure;
 else
 Time[i]=Time[i]-Time[i]%10+code_sure;
}                               //当调时位为个位时的处理智育

 
//*************************************闹钟***********
void alarm_set()
{
//uchar i;
 alarm_flag=1;
 //for(i=0;i<7;i++)

 //alarm_arry[i]=Time[i];//显示当前时间
 sipo(alarm_arry);//显示上次闹钟时间
 time_set();
 if(time_time()!=1)//如果没有调闹钟,则改变一下时间,避免退出时直接闹钟时间到
 alarm_arry[5]=Time[5]-1;
 alarm_flag=0;
}

//********************time_time闹钟对时**********
bit time_time()
{
uchar i;
 for(i=0;i<6;i++)
 {
 if(alarm_arry[i]!=Time[i])//比较
 {
 return 1;
 break;
 }
}
}
//********************
void alarm_deal()
{
w_commend(0x01);
 alarm_d=1;
 while(counter_a<10)
 {
 if(get_key_code()==13)//如果按下退出键,则退出报警
 counter_a=10;
if(bell_flag==1)
bell=0;//蜂鸣器响,响一秒,停一秒
else
bell=0xff;


do
{
w_commend(0x80);
w_s_char(8,s_char3);//闹钟报警期间显示字符串,只显示一次,避免屏闪
}
while(counter_a>10);
}



alarm_d=0;
counter_a=0;


}
/*********月处理************/
uchar month_deal()
{
 switch(Time[1])
 {
  
  case 1:return 31;break;
  case 2:{if(year_deal()) return 28;
          else return 29;}break;
  case 3:return 31;break;
  case 4:return 30;break;
  case 5:return 31;break;
  case 6:return 30;break;
  case 7:return 31;break;
  case 8:return 31;break;
  case 9:return 30;break;
  case 10:return 31;break;
  case 11:return 30;break;
  case 12:return 31;break;
  default:return 0;
} 
}


/******************闰年判断,是闰年返回1,否则返回0********************/
bit year_deal()
{
 unsigned int year;
 year=2000+Time[0];
 if((year%100!=0)&&(year%4==0)||(year%100==0)&&(year%4==0))
 return 1;
 else
 return 0;
}
   


/********************BCD转换*************************/
void bcd_turn(uchar x)
{
 bcd_arry[0]=x/10;
 bcd_arry[1]=x%10;
}

//***********延时程序约10MS***************

void delay50ms()
{
unsigned char i,j;
for(i=0;i<251;i++)
{
   for(j=0;j<40;j++);
   j=0;
   }
   i=0;

}


/*8888888888888888 LCM 显示88888888888888888888888888888
  888888888888888888888888888888888888888888888888888888*/


void lcm_init()
{
 

 /*清屏并光标肝椿*/

 w_commend(0x01);

//w_commend(0x03);

/*设置显示模式:8位2行5x7点阵*/
 w_commend(0x3c);
  /*显示器开、光标开、光标允许闪烁*/
 w_commend(0x0f);
 /*文字不动,光标自动右移*/
 w_commend(0x06);
}

void w_commend(uchar commend)/******写入命令子程序*****/
{

 P1=commend;             
 RS=0;
 RW=0;
 E=0;
 
 busy();
 E=1;
 
 }

/************延时程序****************/
void busy()
{

 P1=0xff;
 RS=0;
 RW=1;
 E=0;
 _nop_();
 E=1;
 
 while(P17);
}
 
/************写入数据***************/
void w_data(uchar _data)
{
 P1=_data;
 RS=1;
 RW=0;
 E=0;
 
 busy();
 E=1;
}

/*********写入字符串*******/
void w_s_char(uchar n,uchar char_arry[16])
{
 
 uchar i;
 for(i=0;i<n;i++)
 {
 w_data(char_arry[i]);
 r_ac_add();/*调用换行程序*/
 }
}


/************************当写入字符串超过第一行时,进行换行********/
void r_ac_add()
{
 uchar temp;
 RS=0;
 RW=1;
 E=0;
 _nop_();
 E=1;
 busy();
 temp=P1;
 temp=temp&0x7f;
 if(temp==0x10)/*换行*/
 w_commend(0xc0);
}




//************************查询调时位地址,并使光标移到该位*********
void find_add()
{
  w_commend(0x0e);
  /*显示器开、光标开、光标不允许闪烁*///????????????????????????????????????????????????????????
 switch(counter_0)
 {
  case 1:w_commend(0x80);break;
  case 2:w_commend(0x81);break;
  case 3:w_commend(0x83);break;
  case 4:w_commend(0x84);break;
  case 5:w_commend(0x86);break;
  case 6:w_commend(0x87);break;
  case 7:w_commend(0x8d);break;//alarm
  case 8:w_commend(0xc0);break;
  case 9:w_commend(0xc1);break;
  case 10:w_commend(0xc3);break;
  case 11:w_commend(0xc4);break;
  case 12:w_commend(0xc6);break;
  case 13:w_commend(0xc7);break;

 }
}

//*********************************键盘程序**********************


//**************************键盘密码****************************
uchar lock_key()
{
 uchar i;

 if(lock_status==1)//*若为1,则需要解码*******
 {

 m_code=get_key_code();
 if(m_code==16)
 {
  
  for(i=0;i<3;i++)
  {
  while(key_check()==0);//**********等待下一个键按下,避免虚跳********
  
  m_code=get_key_code();
  lock_code=m_code;//因为下面改变了M_CODE的值,所以要先保存好有效的值
  if(lock_code!=s_lock_code)
  
  break;
  }
  m_code=0;//***************************改变m_code值,避免在if(m_code==0x13)中循环************
  if(lock_code==s_lock_code)
  {
  lock_status=0;
  
  }
 }
 return 0;
 }
 
 else
 {
 m_code=get_key_code();
 if(m_code==16)
 {
  while(key_check()==0);
  m_code=get_key_code();
  if(m_code==16)  //********按两下锁上键盘**********
  {
  lock_status=1;
  m_code=0;
  
  }
 }
 return(m_code);
 
 }
}

/*
//*****************延时时间约为(16*N+24)us******************
void delay_key(unsigned int N)  
{
 int i;
 for(i=0;i<N;i++);
 }
*/


//**********************key_check*******
bit key_check()
{
 uchar PB_temp;
 
 PD=0x0;
 _nop_();
 PB_temp=PB;
 PB_temp=PB_temp&0x0f;
 
 if(PB_temp==0x0f)
 {
  delay50ms();
 PB_temp=PB;
 PB_temp=PB_temp&0x0f;
 if(PB_temp==0x0f)
 
 return(0);
 else
 return(1);
 }

}

//**********************************uchar get_key_code()************
uchar get_key_code()
{
 
 uchar PD_temp,PB_temp;
 uchar PB_code,key_code;
 uchar i;
 PD_temp=0x7f;

 for(i=0;i<5;i++)
 {
  PD_temp=_crol_(PD_temp,1);
  PD=PD_temp;
  _nop_();
   PB_temp=PB;
   PB_temp=PB_temp&0x0f;
   if(PB_temp!=0x0f)
   {
   while(key_check());         /*等待键松开*/
   PB_temp=~PB_temp;
   switch(PB_temp)
   {
    case 0xf1:PB_code=0;break;
	case 0xf2:PB_code=1;break;
	case 0xf4:PB_code=2;break;
	case 0xf8:PB_code=3;break;
   }

   key_code=i*4+PB_code;
  
  }

 }
 return(key_code);
}

⌨️ 快捷键说明

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