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

📄 clock.c

📁 用C写的单片机中断时钟
💻 C
字号:
/************************************************************************************/
/*  程序名:多功能时钟                                                              */
/*  晶振:   12M                      单片机型号:AT89S51                           */
/*  作者:   邓波   李杰   苏昆                                                     */
/*  功能描述:本开发板P0口接数码管的段选,P2口接数码管的位选,四个按键调节控制        */
/*             本程序具有时钟,闹钟,年月日功能,均可以调节,而且还能够整点报时功能  */
/*  说明:P3的4,5,6,7口连接键盘,有一列线接地。P1_0连接蜂鸣器。                  */
/*  时间:2007年4月5号                                                              */
/*  地点:湖南科大                                                                  */
/************************************************************************************/
#include<reg51.h>

#define _TH0_TL0_ 	(65536 - 50000)  
#define HI 			(_TH0_TL0_ / 256) //给高8位赋值3C
#define LO 			(_TH0_TL0_ % 256) //给低8位赋值B0
#define M 			20                //(1000/50)1秒要50个中断的累计
 
sbit P1_0=P1^0;      //定义位变量
sbit P2_0 = P2 ^ 0;  
sbit P2_1 = P2 ^ 1;
sbit P2_2 = P2 ^ 2;
sbit P2_3 = P2 ^ 3;
sbit P2_4 = P2 ^ 4;
sbit P2_5 = P2 ^ 5;
sbit P2_6 = P2 ^ 6;
sbit P2_7 = P2 ^ 7;
sbit P3_4 = P3 ^ 4;
sbit P3_5 = P3 ^ 5;
sbit P3_6 = P3 ^ 6;
sbit P3_7 = P3 ^ 7;

#define BEEP_on   P1_0=0;                 //蜂鸣器蜂鸣,可以整点报时,可以闹钟
#define BEEP_off   P1_0=1;

struct Time{                        
            unsigned char hour;
			unsigned char min;
			unsigned char sec;
			}clock={12,58,50};
struct calendar{
                unsigned int year;
				unsigned char month;
				unsigned char day;
               }rili={1997,04,03};
struct alarm{
                unsigned char shi;
				unsigned char fen;
				unsigned char miao;
               }naozhong={12,40,00};
			   
unsigned char SEG_TAB1[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};//0-9数字
unsigned char SEG_TAB2[] = {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};//0.-9.数字
unsigned char Led[6];  
unsigned char tt[8];

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

void Delay(unsigned char a)            //延时程序
{
	unsigned char j; 
	while(--a != 0)
	{
		for (j = 0; j < 125; j++);
	}
}

/*********************************************************************************************/
void Disp1(void)                                  //数码管显示时钟模块
{
		P2_0 = 0;            //第一个数码管显示时的十位		
		Led[0] = clock.hour / 10;
		P0 = SEG_TAB1[Led[0]];
		Delay(2);
		P2_0= 1;

		P2_1 = 0;          //第2个数码管显示时的个位
		Led[1] = clock.hour % 10;
		P0 = SEG_TAB1[Led[1]];
		Delay(2);
		P2_1 = 1;
        
		P2_2=0;P0=0xbf;Delay(4);P2_2=1;
		
		P2_3= 0;         //第4个数码管显示分的十位
		Led[2] = clock.min / 10;
		P0 = SEG_TAB1[Led[2]];
		Delay(2);	
		P2_3= 1;

		P2_4 = 0;        //第5个数码管显示分的个位		
		Led[3] = clock.min % 10;
		P0 = SEG_TAB1[Led[3]];
		Delay(2);
		P2_4 = 1;
        
		P2_5=0;P0=0xbf;Delay(4);P2_5=1;
		
		P2_6 = 0;        //第7个数码管显示秒的十位
		Led[4] = clock.sec / 10;
		P0 = SEG_TAB1[Led[4]];
		Delay(2);	
		P2_6 = 1;

		P2_7 = 0;         //第8个数码管显示秒的个位。
		Led[5] = clock.sec % 10;
		P0 = SEG_TAB1[Led[5]];	
		Delay(2);	
		P2_7= 1;
        
        if(clock.sec==0&&clock.min==0)     //增加整点报时功能,
         {
		  BEEP_on;
		  Delay(100);
          BEEP_off;
		 }
}
       
void Disp2(void)                             //数码管显示日历模块
{        
        P2_7=0;       //后两个数码管显示日期
        tt[0]=rili.day%10;
        P0 = SEG_TAB1[tt[0]];
        Delay(4);
        P2_7=1;

        P2_6=0;
        tt[1]=rili.day/10;
        P0 = SEG_TAB1[tt[1]];
        Delay(4);
        P2_6=1;

        P2_5=0;       //中间两个数码管显示月份
        tt[2]=rili.month%10;
        P0 = SEG_TAB2[tt[2]];
        Delay(4);
        P2_5=1;

        P2_4=0;
        tt[3]=rili.month/10;
        P0 = SEG_TAB1[tt[3]];
        Delay(4);
        P2_4=1;
    
        P2_3=0;       //前四个数码管显示年
        tt[4]=rili.year%10;
        P0 = SEG_TAB2[tt[4]];
        Delay(4);
        P2_3=1;

        P2_2=0;
        tt[5]=rili.year/10%10;
        P0 = SEG_TAB1[tt[5]];
        Delay(4);
        P2_2=1;

        P2_1=0;
        tt[6]=rili.year/100%10;
        P0 = SEG_TAB1[tt[6]];
        Delay(4);
        P2_1=1;

        P2_0=0;
        tt[7]=rili.year/1000%10;
        P0 = SEG_TAB1[tt[7]];
        Delay(4);
        P2_0=1;
}

void Disp3(void)                              //数码管显示闹钟模块
{
		P2_0 = 0;   //第一个数码管显示闹钟时的个位		
		Led[0] = naozhong.shi / 10;
		P0 = SEG_TAB1[Led[0]];
		Delay(3);
		P2_0= 1;

		P2_1 = 0;//第2个数码管显示闹钟时的十位
		Led[1] = naozhong.shi % 10;
		P0 = SEG_TAB1[Led[1]];
		Delay(3);
		P2_1 = 1;
        
		P2_2=0;P0=0xbf;Delay(4);P2_2=1;
		
		P2_3= 0;//第4个数码管显示闹钟分的个位
		Led[2] = naozhong.fen / 10;
		P0 = SEG_TAB1[Led[2]];
		Delay(3);	
		P2_3= 1;

		P2_4 = 0;//第5个数码管显示闹钟分的十位		
		Led[3] = naozhong.fen % 10;
		P0 = SEG_TAB1[Led[3]];
		Delay(3);
		P2_4 = 1;
        
		P2_5=0;P0=0xbf;Delay(5);P2_5=1;
		
		P2_6 = 0;//第7个数码管显示闹钟秒的个位	
		Led[4] = naozhong.miao / 10;
		P0 = SEG_TAB1[Led[4]];
		Delay(3);	
		P2_6 = 1;

		P2_7 = 0;//第8个数码管显示闹钟秒的十位。
		Led[5] =naozhong.miao % 10;
		P0 = SEG_TAB1[Led[5]];	
		Delay(3);	
		P2_7= 1;
}			

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

void IsrTimer0(void) interrupt 1 using 1    //定时器0中断服务程序
{
	static unsigned char count = 0;	//定义静态变量count

	TR0 = 0;               //以下调整出栈入栈的时间误差
    TL0 += (_TH0_TL0_ + 9) % 256;
   	TH0 += (_TH0_TL0_ + 9) / 256 + (char)CY;
    TR0 = 1;

    count++;
	if(count == M)  //1秒种时间到
	{
		count = 0;	
		clock.sec++;		
		if(	clock.sec == 60)  //1分钟时间到
		{
			clock.min++;
			clock.sec = 0;
			if(	clock.min == 60)  //1小时时间到
			{
				clock.hour++;
				clock.min = 0;
				if(	clock.hour == 24)  //24小时时间到
				{
					clock.hour = 0;
					clock.min = 0;
					clock.sec = 0;
				    rili.day++;
                    if(rili.day==31)  //一天
                     {
                      rili.month++;
                      rili.day=0;
                      if(rili.month==13)  //一月
                       {
                        rili.year++;
                        rili.month=0;
                       }
                     } 
                 }
			}
		}
	}
}

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

int keypressed1()       //键盘调节时间函数
{
   if(P3_4 == 0)
    {
      Delay(50);
      if(P3_4 == 0)
          clock.sec ++;

    }
   
	if(P3_5 == 0)
    {
      Delay(50);
      if(P3_5 == 0)
          clock.min ++;
    }
   
	if(P3_6 == 0)
    {
      Delay(50);
      if(P3_6 == 0)
          clock.hour ++;
    }
   
    if(clock.sec ==60) clock.sec =0;
    if(clock.min==60) clock.min =0;
    if(clock.hour==24) clock.hour =0;
}

int keypressed2()      //键盘调节日期函数
{
   if(P3_4 == 0)
    {
      Delay(50);
      if(P3_4 == 0)
          rili.day ++;
     }
    
	 if(P3_5 == 0)
    {
      Delay(50);
      if(P3_5 == 0)
          rili.month ++;
     }
    
	if(P3_6 == 0)
    {
      Delay(50);
      if(P3_6 == 0)
          rili.year ++;
    }
   
    if(rili.day ==31) rili.day =1;
    if(rili.month==13) rili.month =1;
    if(rili.year==2031) rili.year =1997;
}

int keypressed3()     //键盘调节闹钟时间函数
{
   if(P3_4 == 0)
    {
      Delay(50);
      if(P3_4 == 0)
          naozhong.miao++;
    }
   
	if(P3_5 == 0)
    {
      Delay(50);
      if(P3_5 == 0)
          naozhong.fen++;
    }
   
	if(P3_6 == 0)
    {
      Delay(50);
      if(P3_6 == 0)
          naozhong.shi++;
    }
   
    if(naozhong.miao==60) naozhong.miao=0;
    if(naozhong.fen==60)  naozhong.fen=0;
    if(naozhong.shi==24)  naozhong.shi=0;
}


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


void Timer0Init(void)    //初始化定时器0程序
{
	TMOD = 0x01;   //设置模式1 定时器0 工作方式0

	TH0 = HI;   //给TH0,TL0赋初始值
	TL0 = LO;

	TR0 = 1;  //启动定时器0
	ET0 = 1;  //定时器中断开
	EA = 1;	//总中断开
}


void main(void)
{
  int j=0,r=0;
  Timer0Init();
  while(1)
  {
    if(P3_7 == 0)
    {
      Delay(20);
      if(P3_7 == 0)
         r++;         //按键被按下次数
      if(r==6) r=0;	
	  if(r<2) j=0;	 
      if(r>=2&&r<=3)j=1 ;  //考虑到硬件不稳定,让每按两次才实现模块转换功能
      if(r<6&&r>4)j=2;}
      switch(j)
      {
	   case 0:Disp1();
             keypressed1();break;
       case 1:Disp3();
             keypressed3();break;
       case 2:Disp2();
            keypressed2();break;
       default:break;
	   }
       
   if(clock.sec==naozhong.miao&&clock.min==naozhong.fen&&clock.hour==naozhong.shi)
   {                      //闹钟和时钟时间相同,闹铃
	BEEP_on;      
	Delay(100);
    BEEP_off;
   }
  }
}

⌨️ 快捷键说明

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