找回密码
 注册
关于网站域名变更的通知
查看: 570|回复: 2
打印 上一主题 下一主题

电子时钟_秒表_按键计数的单片机设计 C语言程序代码及仿...

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2018-11-26 10:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
电子时钟_秒表_按键计数的单片机设计 C语言程序代码及仿...
  d) J( A) O$ x( {) \: J" U. ^3 w+ W2 ]9 _/ C: L5 _
9 H( `( W+ d' ~7 `9 L
一、 电子时钟、秒表和计数器的设计
7 \1 d* Z; k4 }" o7 f2 G. q2 l
1、 实现的功能:
1)有key0key1两个功能按键,复位后,数码管会默认显示时钟模式 HH.MM
HH表示小时,MM表示分钟),
key0短按一次就进入到了秒表模式,数码管显示格式S.SS.S,(分别表示百秒,秒,毫秒)
key0再短按一次就进入到了计数器模式,数码管显示格式CCCC(分别为千位百位十位个位)
key0再短按一次,又进入到了时钟显示模式,就这样由key0控制模式的转换。
       2)有RST复位键,本身电路设计有上电自动复位功能,按下RST后,电路复位。
       3)有ckey0ckey1 两个计数按键,按下ckey0,计数加一,按下ckey1,计数减一。
4) 电子时钟和秒表时间计时方法是采用89S52内部计时器0的一种工作方式(详见后面的代码分析),通过计时器0中断来控制时间的运行。
    5)计数器是采用外部中断0和外部中断1这两个外部中断实现加1和减1的操作。
(1) 电子时钟模式:(以下“长按”表示按下按键的时间大于1“短按”表示按下的时间小于0.7  
1)长按key1一次,会进入到调整分钟的模式,短按key1一次,分钟会加一。
第二次长按key1,会进入到调整小时的模式,短按key1一次,小时加一。
     第三次长按key1,重新回到时钟显示模式,这时再短按key1,时间不会变化
2)长按key0一次,会进入到显示秒的模式
4 c+ v2 A; k8 n1 H  c  P6 J* Q
(2) 秒表模式:
1) key0控制进入秒表模式后,短按key1一次,秒表计时开始,再短按key1一次计时结束
2) 长按key1一次,秒表清零
(3) 计数器模式
1) ckey0一下,计数加一,数码管相应的显示的数值加一,
  ckey1一下,计数减一,数码管相应的显示的数值减一,
由于数码管的位数限制,最大只能显示到9999,此时按下ckey0无反应;考虑到
实际计数功能,没有设置负数,所以最小显示0000,这时按下ckey1 ,无反应。
2) 长按key1一次计数器清零。
. W9 b3 N7 k/ x( k9 V
单片机源程序:
#include <reg51.h>
sbit key0=P1^0;
sbit key1=P1^1;    //定义key0,key1接口
unsigned char flag,con,mcount;  //flag为计数到一秒时给时钟发的信号
unsigned char count = 0;   
unsigned char seccount =0; //作为时钟的秒的计量单位
unsigned char hour = 0;  //时钟的时
unsigned char min = 0;  //时钟的分
unsigned char sec = 0;   //时钟的秒
unsigned char keypress0,keypress1,mode,ms,s,ss,start;
unsigned char
Displaynum[]={0x14,0xd7,0x4c,0x45,0x87,0x25,0x24,0x57,0x04,0x05, 0x10,0xd3,0x48,0x41,0x83,0x21,0x20,0x53,0x00,0x01,0xff,0xfb};  
//数码管十六进制译码表   
unsigned char controlnum[]={0x08,0x04,0x02,0x01}; //控制四个数码管显示        
unsigned char DisplayBuff[]={0x00, 0x00, 0x00, 0x00}; //每个数码管的值     
void display_state(); //数码管显示子程序
void keyscan();  //键盘扫描子程序
void timer();  //秒表子程序
unsigned char count1,flag1,t_adjust=0,tm_adjust=0;
unsigned char bKey0Pressed = 0, bKey1Pressed = 0;
unsigned char ucStatus = 0;
void main()
{
     TMOD = 0x01; //定时器0工作在模式1,GATE=0,C/t=0,16位模
     TH0= (2^16-5000)/256;//定时器0 预存值,
     TL0= (2^16-5000)%256;
     TR0= 1;  //定时器0 启动      
     ET0= 1;  //定时器中断0 允许
     EA= 1;    //开中断
             IT0=1;   //外部中断0下降沿触发
     IT1=1;   //外部中断1 下降沿触发
     EX0=1;   //外部中断0允许
     EX1=1;   //外部中断1允许
     PX1=1;   //外部中断1 为高优先级中断
: C# q8 U* X! E( @+ D  Z
  while(1)   //死循环,  
  {
    if(flag == 1)    //时钟显示
    {
           flag = 0;
       sec++;
          if(sec ==60)
             {sec = 0;
              min++;
                if(min ==60)
                  {min = 0;
                    hour ++;
                     if(hour == 24)
                      {
                        hour = 0;
                       }
                  }
              }
      }
        display_state();
    keyscan();
    timer();  

" z9 T3 r  P& F% I5 n
     }
}
//////////////////////////////////ISR中断服务程序,每5ms产生一个定时器0 中断
void Display() interrupt 1
   {
       TH0  = (2^16-5000)/256;
       TL0  = (2^16-5000)%256;
" [  @0 z6 u3 k
       seccount ++;
           mcount ++;
           keypress0++;
           keypress1++;

& t' g  H9 O( N& [  u/ m; ]# u* l  l
       P2=0x00;  //P2口先清零
            P0 = Displaynum[DisplayBuff[count]]; //P0口输出
              P2 = controlnum[count];  //P2口输出
3 h- _7 M3 p! c$ z, e5 f9 }8 x
           count++;
           if(count==4)
           count=0;
       if(seccount == 200)  //200*5ms=1s
          { seccount =0;
            flag =1;  //每过1秒给时钟信号加一秒
          }

. C: ^- i& e) z7 Q5 f
    }

8 K/ [: |% k9 u8 f
///////////////////////////////////////////
void display_state()
{
  if(mode == 0)  //时钟模式,显示时间
   {
    DisplayBuff[0] = hour/10;
    DisplayBuff[1] = (hour%10)+10;    //"+10"是为了显示加点的数字
    DisplayBuff[2] = min/10;
    DisplayBuff[3] = min%10;
   }
  if(mode == 1)  //秒表模式,显示秒表
   {
    DisplayBuff[0] = ss +10; //"+10"是为了显示加点的数字
    DisplayBuff[1] = s/10;
    DisplayBuff[2] = (s%10)+10;
    DisplayBuff[3] = ms;
    }
   if(mode == 2)  // 计数器模式,显示计数
   {
    DisplayBuff[0] = count1/1000;  //千位
    DisplayBuff[1] = (count1-(count1/1000)*1000)/100; //百位
    DisplayBuff[2] = (count1-(count1/100)*100)/10; //十位
    DisplayBuff[3] = count1%10;  //个位
    }
        if(mode==3)   //显示时钟的秒,
        {
    DisplayBuff[0] = 20; //第一位不显示
    DisplayBuff[1] = 21; //第二位显示一个点
    DisplayBuff[2] = sec/10;//显示秒的十位
    DisplayBuff[3] = sec%10;//显示秒的个位
    }
* z5 Q( ]% W4 z+ ~' h4 p" Q
}  
4 J3 m& l' a( u7 q2 L& P: B% x
//**************//  
//键盘扫描子程序//
//**************//
void keyscan()
{
    if(!key0 && bKey0Pressed == 0)  //检测到key0按下
    {
        keypress0 = 0;
             bKey0Pressed = 1;  //防止重入此判断
        while(!key0);  //如果没放开,就等下去
    }
    if(key0 && bKey0Pressed == 1) //检测到key0放开
    {
            bKey0Pressed = 0;  //防止重入此判断
             if (keypress0<120)        //如果是短按
            {
          if(ucStatus == 0x02)
                         {
                        ucStatus = 0x00;  
                    mode = 0;   //时钟模式
                            t_adjust=0;
            }
                else if(ucStatus == 0x00)
                    {
                         ucStatus = 0x01;
                     mode = 1;  //秒表模式
            }
                        else if(ucStatus == 0x01)
                        {
                            ucStatus = 0x02;
                     mode = 2;   //计数模式
            }
        }
                else if(keypress0>200)  //如果是长按
                        mode=3;  //显示时钟的秒的模式
      }
                 ////////////////////////////////
  if(mode == 0)  //进入时钟模式后
  {        
    if(!key1 && (bKey1Pressed == 0))
         { keypress1 = 0;
             bKey1Pressed = 1;
        while(!key1);
           }
- ^0 ]2 J! x5 [0 h& V
    if(key1 && (bKey1Pressed == 1))
    {
               bKey1Pressed = 0;
           if(keypress1 >= 200)   //如果是长按
        {
                t_adjust++;
                        if(t_adjust==3)
                           t_adjust=0;
        }
           else if(keypress1 < 120)  
                   switch (t_adjust)
                         {
) Z) Q2 Y, J, z) x
                          case 1:{   //调整分
                                   min++;
                                   sec = 0;
                                           if(min == 60)
                                              min = 0;
                                          }
                                        break;
                           case 2: {   //调整时
                                    hour ++ ;
                                    sec = 0;
                                            if(hour == 24)
                                              hour = 0;
                                                }
                                        break;
                     default:break;
                          }
            }
        }

- w5 R) W: a, }  ~" S0 ^
        else if(mode == 1)  //进入秒表模式
      {   
          if(!key1 && bKey1Pressed == 0)
          {
             keypress1 = 0;
                   bKey1Pressed = 1;
            while(!key1);
          }        
          if(key1 && bKey1Pressed == 1)
          {
                  bKey1Pressed = 0;
                 if(keypress1 < 120)  //短按
                        {
                            if(flag1==0) { start=2;flag1=1;}  //start=2代表秒表开始计时
                                else {start=0;flag1=0;} //start=0,秒表停止计时
                         }
                         else if(keypress1>200)  //长按
                               start=1;   //秒表清零

: E! T9 V7 F# t6 ~
                  }
           }
}

! f6 v8 g  Y9 h5 z) I$ u
, `) a6 F1 R2 _9 y. ]# E  X2 O  o
void timer()  //秒表子程序
{
   if(mode==1) //进入秒表模式才执行
   {  
     if(start==1) //清零
     {  
ms = 0;
             s = 0;
             ss = 0;           
             mcount=0;
          }
         if(start==2)  //秒表开始计时
         {
       if(mcount==20)   //20*5ms=0.1s
            {
              mcount=0;
                   ms++;
                    if(ms == 10) // 10*0.1s=1s,s++
                           {ms = 0;
                            s ++;
                                 if(s == 100)  //100s
                                    {s = 0;
                                    ss ++;
                                         if(ss == 10)
                                           {ss = 0;
                                           s  = 0;
                                           ms = 0;
                                           }
                                    }
                            }
                }
        }
if (start==0);//秒表停止
        }

/ R" _" M$ V' |# I
}
//////////////////////
void it0(void) interrupt 0 using 1  //外部中断0 服务程序
{
    if(mode==2)   //只有在计数模式才执行
        {
      count1++;    //每响应一次,计数加一
      if(count1==10000)  //超出四位时,不能再加
      count1 =9999;
         }
}
void it2(void) interrupt 2 using 2  //外部中断0 服务程序
{
    if(mode==2)   //只有在计数模式才执行
        {
      if(count1!=0)
$ n1 h5 ~, D3 |  c- k9 W8 _

' y  H7 n; O+ ^7 ~
…………限于本文篇幅 余下代码请从论坛下载附件…………
游客,如果您要查看本帖隐藏内容请回复

. Q+ k- x4 U4 H/ S

该用户从未签到

3#
发表于 2019-1-24 16:08 | 只看该作者
不错,好东东,谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-19 16:02 , Processed in 0.156250 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表