用51单片机定时器中断设计电子钟

发布者:暮烟微雨最新更新时间:2015-08-18 来源: eefocus关键字:51单片机  定时器  中断设计  电子钟 手机看文章 扫描二维码
随时随地手机看文章
把前天设计的时钟的功能补全了一些,贴上来,

 

#include
#define uchar unsigned char
sbit rd=P2^6;
sbit wr=P2^5;
sbit lcde=P2^7;
sbit k1=P1^0;
sbit k2=P1^1;
sbit k4=P1^3;
sbit k8=P1^7;
uchar code table1[]="2011-11-05";
uchar code table2[]="00:00:00";
uchar code table3[][3]={{"MON"},{"TUE"},{"WED"},{"THU"},{"FRI"},{"SAT"},{"SUN"}};         //定义了二维数组存放星期
uchar t,s1num;
char shi,fen,miao,week,nian;
uchar yue=1,ri=1;
void delay(uchar z)       //延迟zms函数
{
 uchar x,y;
 for(x=z;x>0;x--)
 for(y=110;y>0;y--);

}

 

void write_com(uchar com)       //液晶写指令操作
{
 rd=0;
 wr=0;
 delay(5);
 lcde=1;
 P0=com;
 lcde=0; 
}

void write_date(uchar date)        //液晶写数据操作
{
 rd=1;
 wr=0;
 delay(5);
 lcde=1;
 P0=date;
 lcde=0; 
}

void write_sfm(uchar add,uchar date)       //更新时分秒
{
 uchar shi,ge;
 shi=date/10;
 ge=date;
 write_com(0x80+0x40+add);
 write_date(0x30+shi);
 write_date(0x30+ge);
}

void write_week(uchar i)             //更新星期
{
 uchar j;
 write_com(0x80+0x0b);
 for(j=0;j<3;j++)
 {
  write_date(table3[i][j]);
  
 }
}


void write_riqi(uchar add,uchar riqi)    //更新年月日
{
 uchar shi,ge;
 shi=riqi/10;
 ge=riqi;
 write_com(0x80+0x00+add);
 write_date(0x30+shi);
 write_date(0x30+ge);
}

void init()                //初始化函数
{
 uchar i,j;

 


 write_com(0x38);
 write_com(0x0c);
 write_com(0x06);
 write_com(0x01);

 write_com(0x80+0x00);
 for(i=0;i<10;i++)
 write_date(table1[i]);

 write_com(0x80+0x00+0x0b);
 for(j=0;j<3;j++)
 write_date(table3[week][j]);

 write_com(0x80+0x46);
 for(i=0;i<8;i++)
 write_date(table2[i]);

 TMOD=0x01;              //定时器0工作方式1
 TH0=(65536-50000)/256;         //设定定时器初值
 TL0=(65536-50000)%6;         //12M晶振时50ms数为50000
 EA=1;
 ET0=1;
 TR0=1;
}

void keyscan()            //键盘扫描函数
{
 if(k1==0)               //按下k1键确定调时分秒
 {
 delay(5);
 if(k1==0)
 {
  s1num++;
  while(!k1)
  ;
  delay(5);
  while(!k1);
   if(s1num==1)     
   {
   TR0=0;                   //暂停计时器
   write_com(0x80+0x4d);     //光标在秒的位置闪烁
   write_com(0x0f);
   }
  
   if(s1num==2)         //光标在分的位置
   {
   TR0=0;
   write_com(0x80+0x4a);
   write_com(0x0f);
   }

   if(s1num==3)         //光标在小时的位置
   {
   TR0=0;
   write_com(0x80+0x47);
   write_com(0x0f);
   }
  if(s1num==4)         //光标在星期的位置
   {
   TR0=0;
   write_com(0x80+0x0d);
   write_com(0x0f);
   }
  if(s1num==5)         //光标在日的位置
   {
   TR0=0;
   write_com(0x80+0x09);
   write_com(0x0f);
   }
  if(s1num==6)         //光标在月的位置
   {
   TR0=0;
   write_com(0x80+0x06);
   write_com(0x0f);
   }
  if(s1num==7)         //光标在年的位置
   {
   TR0=0;
   write_com(0x80+0x03);
   write_com(0x0f);
   }
   if(s1num==8)       //按下第8下时接着走时
   {
    s1num=0;
    write_com(0x0c);
    TR0=1;
   }

  }
 }
 if(s1num!=0)
 {
  if(s1num==1)
  
  if(k2==0)            //按k2键秒加1
  {
   delay(5);
  if(k2==0)
  {
   while(!k2);
   delay(5);
   while(!k2);
 
   miao++;
   if(miao==60)
   miao=0;

   write_sfm(0x0c,miao); 
   write_com(0x80+0x4d);
  }
  }
 }


  if(s1num==2)
  {
  if(k2==0)           //分加1
  {
   delay(5);
  if(k2==0)
   {
   while(!k2);
   delay(5);
   while(!k2);
   fen++; 
   if(fen==60)
   fen=0;

   write_sfm(0x09,fen); 
   write_com(0x80+0x4a);
   }
  }
  }
  
  if(s1num==3)
  {
   if(k2==0)           //时加1
  {
   delay(5);
   if(k2==0)
   {

   while(!k2);
   delay(5);
   while(!k2);
   shi++; 
   if(shi==24)
   shi=0;

   write_sfm(0x06,shi); 
   write_com(0x80+0x47);
   }
  }
  }

  if(s1num==4)
  {
   if(k2==0)           //星期加1
  {
   delay(5);
   if(k2==0)
   {

   while(!k2);
   delay(5);
   while(!k2);
   week++; 
   if(week==7)
   week=0;

   write_week(week); 
   write_com(0x80+0x0d);
   }
  }
  }

  if(s1num==5)
  {
   if(k2==0)           //日加1
  {
   delay(5);
   if(k2==0)
   {

   while(!k2);
   delay(5);
   while(!k2);
   ri++; 
   if(ri==31)
   ri=1;

   write_riqi(0x08,ri);
   write_com(0x80+0x09);
   }
  }
  }


  if(s1num==6)
  {
   if(k2==0)           //月加1
  {
   delay(5);
   if(k2==0)
   {

   while(!k2);
   delay(5);
   while(!k2);
   yue++; 
   if(yue==12)
   yue=1;

   write_riqi(0x05,yue);  
   write_com(0x80+0x06);
   }
  }
  }

  if(s1num==7)
  {
   if(k2==0)           //年加1
  {
   delay(5);
   if(k2==0)
   {

   while(!k2);
   delay(5);
   while(!k2);
   nian++; 
   if(nian==100)
   nian=0;
   write_riqi(0x02,nian); 
   write_com(0x80+0x03);
   }
  }
  }

 

 

 if(k4==0)  //判断k4是否被按下
 {
  delay(5);
  if(k4==0)
  {
   while(!k4);
   delay(5);
   while(!k4);
   if(s1num==1)
   {
    miao--;        //秒减1
    if(miao==-1)
    miao=59;
    write_sfm(0x0c,miao); 
    write_com(0x80+0x4d);
   }
   if(s1num==2)
   {
    fen--;         //分减1
    if(fen==-1)
    fen=59;
    write_sfm(0x09,fen); 
    write_com(0x80+0x4a);
   }
   if(s1num==3)
   {
    shi--;         //时减1
    if(shi==-1)
    shi=23;
    write_sfm(0x06,shi); 
    write_com(0x80+0x47);
   }
  if(s1num==4)
   {
    week--;         //星期减1
    if(week==-1)
    week=6;
    write_week(week); 
    write_com(0x80+0x0d);
   }
  if(s1num==5)
   {
    ri--;         //日减1
    if(ri==0)
    ri=30;
    write_riqi(0x08,ri);
    write_com(0x80+0x09);
   }
  if(s1num==6)
   {
    yue--;         //月减1
    if(yue==0)
    yue=12;
    write_riqi(0x05,yue);  
    write_com(0x80+0x06);
   }
  if(s1num==7)
   {
    nian--;         //年减1
    if(nian==-1)
    nian=99;
    write_riqi(0x02,nian); 
    write_com(0x80+0x03);
   }
  }
 }
 }
 if(k8==0)        // 按下k8退出调时  
 {
  delay(5);
  if(k8==0)
  {
   while(!k8);
   delay(5);
   while(!k8);
   s1num=0;
   write_com(0x0c);
   TR0=1; 
  }
 }
}
 
void main()
{
 init();
    while(1)
 {
 keyscan();
 }
}

void timer0() interrupt 1       //中断服务程序
{

 TH0=(65536-50000)/256;         //设定定时器初值
 TL0=(65536-50000)%6;         //12M晶振时50ms数为50000
 t++;
  if(t==20)           //定时器中断20次为1秒
 {
 t=0;
 miao++;
 if(miao==60)
 {
 miao=0;
 fen++;
 if(fen==60)
 {
  fen=0;
  shi++;
  if(shi==24)
  {
   shi=0;
   ri++;
   week++;
   if(week==7)
    week=0;
    write_week(week);                //刷新星期
    if(ri==31)
    {
     ri=1;
     yue++;
     if(yue==13)
      {
       yue=1;
       nian++;
       if(nian==100)
       nian=0;
       write_riqi(0x02,nian);   //刷新年
      }

      write_riqi(0x05,yue);   //刷新月
      }
  write_riqi(0x08,ri);  //刷新日  
  }
 write_sfm(0x06,shi);    //刷新时
 }
 write_sfm(0x09,fen);     //刷新分
 }
 write_sfm(0x0c,miao);     //刷新秒
}
}

 


// 还可以加上整点报时和断电记忆的功能,还可以加上24小时和12小时制转换功能,还可以加上秒表功能,原理都是一样的,但由于51单片机内存有限,只有
//4k,所以没加
//由于单片机晶振不是严格的12MHz,所以要想时钟精确的话还要进行中断时间的调整//其中年只能改变后两位,即从2000到2099年,其实也可实现全调,原理是一样的,但没这个必要

关键字:51单片机  定时器  中断设计  电子钟 引用地址:用51单片机定时器中断设计电子钟

上一篇:霍尔传感器信号采集与显示系统设计
下一篇:1602液晶动态显示

推荐阅读最新更新时间:2024-03-16 14:29

51单片机,点阵显示汉字(C语言)
#include #include #define uint unsigned int #define uchar unsigned char sbit SH_595=P2^1; sbit DATA_595=P2^0; sbit ST_CP_595=P2^2;//74HC595(12)-ST_CP上升沿-移位寄存器的数据进入数据存储寄存器 输出锁存器的时钟信号端口 sbit MR_595=P2^3; //74HC595(10)-MR 为0将移位寄存器的数据清0 sbit E1_154=P2^4;//74HC154(18)-E1为0开列(col)输出 显示允许 控制信号端口 uchar keynum; uchar tem
[单片机]
51单片机矩阵键盘的软硬件设计
  下面以51单片机综合学习系统为硬件平台,介绍矩阵式键盘的编程方法。具体功能为:按下其键后,在一位数码管上显示出键值。0到16个键分别对应显示0到F。   1、硬件原理      本实验可以直接在配套开发板上完成,电路图如下图所示。   根据电路原理图,键盘扫描方法是:行线P1O~P13为输出线,列线P14~P17为输入线。一开始单片机将行线(P1O-P13)全部输出低电平,此时读入列线数据,若列线全为高电平说明没有键接下,若有列线为低电平则调用延时程序来去除按键抖动。延时后再读入列线看是否有低电平,如果列线数据还是有低电平,说明确实有键接下,接下来便是确定键值。下面以第二行的S5键为例,看接下S5后我们应该怎么得到这个键值。当
[单片机]
<font color='red'>51单片机</font>矩阵键盘的软硬件<font color='red'>设计</font>
基于MCS-51单片机使用定时器编写时钟程序(汇编)
1、仔细想想还不错的思路 用定时器写一个时钟程序,想想都觉得头大。撇开其他花里胡哨的功能,先从最基本的时间显示开始吧,剩下的以后再说。 我们一般希望的是时钟能不停地计时,在需要的时候调用显示来显示当前时间,同时也可以干其他事,所以当然不能用延时来写,不然这个时钟除了只能显示时间之外就是个废物了。 我们希望每定时到一秒的时候来个中断,在中断里使存储里的时间序列加一秒(时间序列以时分秒各一个字节的方式存储)。51单片机定时器0方式1的最大定时时间是216=65536μs,也就是大约65ms出头。但我们可以每50ms来一次中断,中断到第20次的时候时间序列加一秒;或者每20ms来一次中断,到第50次的时候时间序列加一秒。一般来说
[单片机]
基于MCS-<font color='red'>51单片机</font>使用<font color='red'>定时器</font>编写时钟程序(汇编)
51单片机“积木式”实验板的制作
这套实验板每块板上的元件数不多,采用万能板和敷铜板丙种方法制作均可,上图中的实物就是用l5xLOCm万能板制作的。主控板的制作要注意的是PO口的引出端,从主控板原理下图可以看到,PO口引出端接线柱的排列方向和51 芯片 的PO口引脚的排列方向正好相反,所以要接跳线,别的三个 端口 的对外接线柱排列方向和51芯片的端口引脚方向一致。这样安排主要是保证不管主板怎样摆放,板上边两个端口各自的8个接线柱排列从左到右分别按PX.7、PX.6、...、PX.1、PX.0(X为0、1、2、3)的顺序,这样容易记忆,特别是外接数码管驱动时尤为方便。 另外要注意各元件的安装高度,保证40脚锁紧式插座装上芯片后,锁紧柄按下不被板上所装的元件挡住。
[单片机]
<font color='red'>51单片机</font>“积木式”实验板的制作
51单片机AD转换之PCF8591
PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。 AD转换即(模拟量)Analog 转换成 (数字量)Digital 1.引脚分析 PCF8591具有4个模拟输入(AIN0~AIN3)、1个模拟输出(AOUT)和1个串行I²C总线接口(SDA、SCL)。 PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。 OSC:外部时钟输入端,内部时钟 EXT:内部、外部时钟选择线,使用内部时钟时 EXT 接地。 VD
[单片机]
<font color='red'>51单片机</font>AD转换之PCF8591
基于PID算法和51单片机的温度控制系统
0 引 言 温控技术无论是在工业生产,还是日常生活中都起着非常重要的作用。在冶金、石油、化工、电力和现代农业等行业,温度是极为重要而又普遍的热工参数之一,在普通家庭里热水器、电饭煲、电烤箱等依赖于温控技术的家电设备也是必不可少。可以说温度控制技术无处不在。 常规的温度控制方法以设定温度为临界点,超出设定允许范围即进行温度调控:低于设定值就加热,反之就停止或降温。这种方法实现简单、成本低,但控制效果不理想,控制温度精度不高、容易引起震荡,达到稳定点的时间也长,因此,只能用在精度要求不高的场合。 而采用PID算法进行温度控制,它具有控制精度高,能够克服容量滞后的特点,特别适用于负荷变化大、容量滞后较大、控制品质要求又很高的控
[单片机]
基于PID算法和<font color='red'>51单片机</font>的温度控制系统
如何使用555定时器构建一个简单的节拍器
555定时器IC是一种多功能元件,可用于各种电路,包括节拍器。节拍器是音乐家在练习过程中用来保持稳定节奏的装置。在本教程中,您将学习如何使用555定时器IC构建一个简单的节拍器。 零件清单 1×9V电池 1×555定时器IC 1×电位器,VR1250kΩ 1×电阻,R11kΩ 2×电容器,C1和C222μF 1×扬声器,8Ω 555定时器配置为非稳态模式,这意味着它可以生成连续的脉冲序列。这些脉冲的频率决定了节拍器的速度。 时序组件:电阻(VR1和R1)和电容器(C1)决定脉冲间隔,可以通过改变VR1的电阻来调整。 电容放电:输出在高电平和低电平状态之间切换,导致C2充电和放电,进而在扬声器中产生声音。 喇叭输出:当输出引
[嵌入式]
如何使用555<font color='red'>定时器</font>构建一个简单的节拍器
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved