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

📄 时钟_1602.c

📁 基于51单片机的1602显示的时钟c语言程序及汇编程序
💻 C
字号:
#include<reg51.h> 
#include<intrins.h>
#define uchar unsigned char

uchar tmp[4]= {"28^C"};
uchar num[12]={"0123456789 :"};//数字数数组
uchar time[8]={0};
uchar t1_set[4]={0};
uchar adj[6]={"adjust"};
uchar adj_0[6]={"  time"};
uchar adj_1[6]={"  t1  "};


uchar off[4]={"off "};
uchar ON[4]= {"on  "};//ON[]两个字母均为大写,用小写时会出错,也不知为什么

uchar hour0=12,hour1=12,minute0=0,minute1=0,second=0;//设置初始值,显示12。00
uchar ten_hour,hour,ten_minute,minute;//
uchar key=0,right=0,set=0;//

bit key_flag=0;//
bit s_flag=0;
bit adj_flag=0;
bit dp_flag=0;
bit time_flag=0;
bit out=1,out1;

sbit set_key=P3^2;
sbit up_key=P3^3;
sbit right_key=P3^4;
sbit on_off_key=P3^5;

sbit p_out1=P1^0;

void t0(void);//定时0中断函数声明
void t1(void);//定时1中断函数声明
void time_display(void);//走时显示子程序
void t_adj(void);//走时调整子程序
void t1_adj(void);//
void t1_out(void);
void key_scan(void);//键盘扫描子程序

/******************************************************************
  1602程序部分
  数据总线接到p2口    用到1ms延时程序    <intrins.h>函数
*******************************************************************/

uchar  command[]={0x38,0x38,0x38,0x38,0x08,0x01,0x06,0x0c}; /* P2=0x01;//清屏并光标复位
                                                P2=00111000;//显示模式设置,8位总线,2行,5*7
                                                P2=0x0c;//开显示。光标和闪烁
                                                P2=0x06;//文字不动,光标自动右移
                                                P2=0x80;//写入的起始位置,第1行第1列*/

sbit e=P3^7;
sbit rw=P3^6;
sbit rs=P3^0;
sbit busy=P2^7;


//--------------------------延时程序-------------------------------
void delay(uchar i)
{  uchar a;
   while(i--)
      {for(a=0;a<=125;a++)
         {;}
       }
}  
//--------------------查LCD是否忙程序-----------------------
 void wait(void)
{   do
    { P2=0xff;
      rs=0;//
	  rw=1;//
	  e=0;
	  _nop_();
      e=1; }
    while(busy==1);
}


//-------------------数据写入函数-------------------------
void dataw(uchar da)
{  wait();
   rs=1;
   rw=0;
   e=1;
   P2=da;
   e=0;
}


//-------------------指令和显示地址写入子函数------------

void comw(uchar da)
{  wait();
   rs=0; 
   rw=0;
   e=1;
   P2=da;
   e=0;
}


//--------------------------初始化--------------------------------
void init(void)
{  uchar i; 
   delay(20);
    e=1; 
    for(i=0;i<8;i++)
     {comw(command[i]);
      delay(5);
     }
  
}
//--------------------------清屏-----------------------------------
void clen(void)
{ uchar i;
  comw(0x80);
  for(i=0;i<16;i++)
      dataw(0x02);
  comw(0xc0);
  for(i=0;i<16;i++)
      dataw(0x02);

}
/****************************************************************************
 主函数

*****************************************************************************/
main()
{ uchar i=0;
   
	 TMOD=0x11; //设置工作方式,T0 50ms 中断计时,T1定时10ms中断,数码管和键盘扫描

     TH0=(65536-46080)/256;//     
     TL0=(65536-46080)%256;// 50ms定时

     TH1=(65536-10000)/256;
     TL1=(65536-10000)%256;//10ms定时
     TR1=1; //
     TR0=1; // 
     ET0=1; //
     ET1=1; //
     EA=1;  //
     init();//1602初始化
    while(1)
      {
	     if(key_flag) key_scan();//当确定有键按下了,就调用键盘扫描程序,判断那个键按下了

		    switch(set) //根据set的值判断该显示哪个
	          { case 0:{if(s_flag==1){s_flag=0;time_display();}} break;//走时显示
	            case 1:{if(adj_flag==1){adj_flag=0;t_adj();}}break;//走时调整显示
				case 2:{if(adj_flag==1){adj_flag=0;t1_adj();}}break;}//定时输出1调整显示
				//case 3:t2_adj();break;}//定时输出2调整显示

		        t1_out();//判断定时输出1时间到了没有
			//	t2_out();//判断定时输出2时间到了没有
			
	   }
 
 
 
   }



/****************************************************************************************
 显示时间子程序

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

void time_display(void)
{  uchar i=0;
  
   time[0]=hour0/10;//
   time[1]=hour0%10;
   time[3]=minute0/10;
   time[4]=minute0%10;   
   time[6]=second/10;
   time[7]=second%10;//将时间拆分
   clen();
////////////////////////////////////////////////////////////
//第1行
   comw(0x84);
   for(i=0;i<8;i++)
      { if(i==2||i==5) dataw(num[11]);
	       else dataw(num[time[i]]);
	  //  if(i==2&&time[7]%2) P2=num[10];//秒闪
	  }
////////////////////////////////////////////////////////////
//第2行
   comw(0xc6);
   for(i=0;i<=3;i++)
      dataw(tmp[i]);
}



/****************************************************************************************
显示时间调整子程序

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

void t_adj(void)
{  uchar i;
   time[0]=hour0/10;//
   time[1]=hour0%10;
   time[3]=minute0/10;
   time[4]=minute0%10;//将时间拆分
   
   if(dp_flag==1){if(right<2) time[right]=10;
                     else if(right>=2) time[right+1]=10;}//判断是否是当前调整位 ,是当前调整位闪烁
//////////////////////////////////////////////////////
//第1行 
   comw(0x80);
   for(i=0;i<6;i++)
      dataw(adj[i]); //" adjust"
   for(i=0;i<6;i++)
      dataw(adj_0[i]);//" time "
/////////////////////////////////////////////////////
//第2行
   comw(0xc5);
   for(i=0;i<5;i++)
      {if(i==2)dataw(num[11]);
	     else  dataw(num[time[i]]);}
}



/****************************************************************************************
 显示闹钟1调整子程序

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

 void t1_adj(void)
{     uchar i;
      t1_set[0]=hour1/10;//
      t1_set[1]=hour1%10;
      t1_set[3]=minute1/10;
      t1_set[4]=minute1%10;//将定时1设定的时间拆分
/////////////////////////////////////////////////////////////////////////////////////////////////
   if(dp_flag==1){if(right<2) t1_set[right]=10;
                    else if(right>=2) t1_set[right+1]=10;}//判断是否是当前调整位 ,是当前调整位闪烁
///////////////////////////////////////////////////////////////////////////////////////////////////
   comw(0x02);
//第1行 
   comw(0x80); 
   for(i=0;i<6;i++)
      dataw(adj[i]); //" adjust"
   for(i=0;i<6;i++)
      dataw(adj_1[i]);//" t1 "
///////////////////////////////////////////////////////////////////////////////////////////////////
//判断显示t1是显示on还是off 
      if(out==1){for(i=0;i<4;i++) dataw(off[i]);} 
	     else {for(i=0;i<4;i++)dataw(ON[i]);}//ON[]两个字母均为大写,用小写时会出错,也不知为什么
/////////////////////////////////////////////////////
//第2行
   comw(0xc5);
   for(i=0;i<5;i++)
      {if(i==2)dataw(num[11]);
	     else  dataw(num[t1_set[i]]);}    
}



/****************************************************************************************
 定时控制1输出子程序

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

    void t1_out(void)
{       if(out1==0) p_out1=0;
           else p_out1=1;
        if(hour0==hour1&&minute0==minute1) {p_out1=1;out1=1;}
}



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

*****************************************************************************************/
 void key_scan (void)

{  
     key_flag=0;//将键盘按下标志位清零

	 if(set_key==0) { set++;if(set==3) set=0;//设置加1,切换状态
	                   while(set_key==0);//等待键松开
                      }
	 if(right_key==0){right++;if(right==4) right=0;//右移,切换调整位
	                   while(right_key==0) {;}}//等待键松开

  	 switch(set) //根据当前调整,将其时间传送给调整的缓存数组
	   { case 1: {ten_hour=hour0/10,hour=hour0%10,ten_minute=minute0/10,minute=minute0%10; adj_flag=1;} break;//时间调整
	     case 2: {ten_hour=hour1/10,hour=hour1%10,ten_minute=minute1/10,minute=minute1%10;adj_flag=1;} break;//定时1调整
		 //case 3: {ten_hour=hour2/10,hour=hour2%10,ten_minute=minute2/10,minute=minute2%10;} break;//定时2调整
	   }

	 if(up_key==0) {  switch(right)//根据调整位进行相应调整
	                   { case 0:{ten_hour++;if(ten_hour==3)ten_hour=0;} break;//十时调整
					     case 1:{hour++;if((ten_hour!=2&&hour==10)||(ten_hour==2&&hour==4)) hour=0;} break;//时调整
						 case 2:{ten_minute++;if(ten_minute==6) ten_minute=0;} break;//十分调整
						 case 3:{minute++;if(minute==10) minute=0;} break;//分调整
					    }
					  while(up_key==0) {;}//等待键松开
					}

      if(on_off_key==0)out=~out;//设置是否启动定时
	  while(on_off_key==0){;};//等待键松开

   switch(set) //将调整后的时间传送回去
	 { case 1:{hour0=ten_hour*10+hour;minute0=ten_minute*10+minute;}break;
	   case 2:{hour1=ten_hour*10+hour;minute1=ten_minute*10+minute;out1=out;}break;
	//  case 3:{hour2=ten_hour*10+hour,minute2=ten_minute*10+minute,out2=out;}break;
	 }
}

/****************************************************************************************
T0中断子程序

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

 void t0(void) interrupt 1 using 1 
{ uchar a,b;
   b++;a++;

  TH0=(65536-46080)/256;//     
  TL0=(65536-46080)%256;// 50ms定时
  if(a==5)  {a=0;dp_flag=~dp_flag;}
  if(b==20) {b=0;s_flag=1;second++;}//够1s则将数码管小数点取反,则看到闪烁
  if(second==60){second=0;minute0++;}//够1分钟则加分钟计数加1
  if(minute0==60){minute0=0,hour0++;}////够1小时则小时计数加1
  if(hour0==24)hour0=0;//够24小时则清零
}
/****************************************************************************************
 T1中断子程序

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

void t1(void) interrupt 3 using 2
 { 
   uchar j,key_1;
   j++;

   TH1=(65536-10000)/256;
   TL1=(65536-10000)%256;//10ms定时
   
   P3=0xff;//键盘扫描程序
   if(j==2){j=0,key=P3&00111100;
            if(key=key_1) key_flag=1; }
   key_1=P3&00111100;//10ms内若两次的结果一样,表明有按键按下
   
 }


⌨️ 快捷键说明

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