找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5415|回复: 0
收起左侧

51单片机的时钟C语言程序,四个按键控制

[复制链接]
ID:452400 发表于 2018-12-22 23:17 | 显示全部楼层 |阅读模式
本帖最后由 diehualong 于 2018-12-22 23:19 编辑

#include<reg52.h>
#define uchar unsigned char
#define uint  unsigned int
sbit we = P2^7;
sbit du = P2^6;
sbit key_1 = P3^4;
sbit key_2 = P3^5;
sbit key_3 = P3^6;
sbit key_4 = P3^7;
uchar n1 = 0;//控制多长时间闪烁一次。
uchar  shi = 0;
uchar shi_1,shi_2;
uchar  fen = 0;
uchar fen_1,fen_2;
uchar  miao = 0;
uchar miao_1,miao_2;
uchar  n = 0;
bit shezhi = 0;
bit flag = 0;//控制设置时某些位的闪烁
uchar m = 0;//不亮的位置
uchar code leddata[]={

                0x3F,  //"0"
                0x06,  //"1"
                0x5B,  //"2"
                0x4F,  //"3"
                0x66,  //"4"
                0x6D,  //"5"
                0x7D,  //"6"
                0x07,  //"7"
                0x7F,  //"8"
                0x6F,  //"9"
                0x40,  //"-"
                         };
uchar code pos[] = {
                                                0xfe,
                                                0xfd,
                                                0xfb,
                                                0xf7,
                                                0xef,
                                                0xdf
                                        };
一部分:参数初始化函数
void init()
{
      TMOD = 0x11;//将定时器0和定时器1设为工作方式1,16位定时器
      TH0 = 0x4B;
      TL0 = 0xFC;  //设置定时器0的中断周期是50ms
      TH1 = 0x4B;
      TL1 = 0xFC;  //设置定时器1的中断周期是50ms
      PT0 = 1;         //设置定时器0中断的优先级高于定时器1中断
      ET0 = 1;         //开启定时器0中断
      ET1 = 1;         //开启定时器1中断
      TR1 = 1;         //定时器1开始计数
      TR0 = 1;         //定时器0开始计数
EA = 1;         //开启总中断
}   
第二部分:关于数码管点亮的函数
//--------------将小时对应的数码管的点亮的函数---------------//
voidhour_display()
{
      shi_1 = shi/10;         //将小时的十位数字赋值给shi_1
      shi_2 = shi%10;     //将小时的个位数字赋值给shi_2
      P0 = pos[0];        
      we = 1;
      we = 0;
      P0 = leddata[shi_1];
      du = 1;
      du = 0;
      delay(1);                     //将最左边的数码管点亮并显示小时的十位数字
      P0 = pos[1];
      we = 1;
      we = 0;
      P0 = leddata[shi_2];
      du = 1;
      du = 0;            //将左边第二个数码管点亮并显示小时的个位数字
      delay(1);
}   
//----------------将分钟对应的数码管的点亮的函数----------------//     
voidfen_display()
{
      fen_1 = fen/10;           //将分钟的十位数字赋值给fen_1
      fen_2 = fen%10;         //将分钟的个位数字赋值给fen_2
      P0 = pos[2];               
      we = 1;
      we = 0;
      P0 = leddata[fen_1];
      du = 1;
      du = 0;
      delay(1);                     //将左边第三个数码管点亮并显示分钟的十位数字
      P0 = pos[3];
      we = 1;
      we = 0;
      P0 = leddata[fen_2];
      du = 1;
      du = 0;
      delay(1);                  //将左边第四个数码管点亮并显示分钟的个位数字    }
//-------------将秒数对应的数码管的点亮的函数-------------//
voidmiao_display()
{
      miao_1 = miao/10;     //将秒数的十位数字赋值给miao_1
      miao_2 = miao%10;   //将秒数的个位数字赋值给miao_2
      P0 = pos[4];
      we = 1;
      we = 0;
      P0 = leddata[miao_1];
      du = 1;
      du = 0;
      delay(1);                     //将右边第二个数码管点亮并显示秒数的十位数字
      P0 = pos[5];
      we = 1;
      we = 0;
      P0 = leddata[miao_2];
      du = 1;
      du = 0;
      delay(1);                     //将右边第一个数码管点亮并显示秒数的个位数字
}
//------------判断当参数shezhi等于1时将小时、分钟、秒数所对应的数码管点亮并显示出相应数字的函数-------------//
void alldis()
{
      if(shezhi == 0)      //当参数shezhi等于0的时候所有数码管被点亮,并
      {                           //将小时、分钟、秒数所对应数码管显示出对应的数字
             hour_display();   
             fen_display ();
             miao_display();
      }     
}
//------------判断当参数shezhi等于0时将要修改的位(即小时或分钟或秒数对应的某两位数码管)出现闪烁效果的函数--------------//
void fourdis()
{
      if(shezhi == 1)
      {
             P0 = 0xff;
             we = 0;                //将所有的数码管关闭,以防受到前一次数码管打开
             we = 1;                //的影响,并为下面出现闪烁效果做准备
             if(flag == 0)        //判断当参数flag等于0时将所有数码管点亮
             {
                    hour_display();   
                    fen_display ();
                    miao_display();   
             }
             if(flag == 1)        //判断当数码管等于1时使需要修改的位置(即小时
             {                          //或分钟或秒数对应的某两位数码管)关闭
                    if(m == 0)    //判断当参数m为0时将小时对应的两位数码管关闭
                    {
                           fen_display ();
                           miao_display();
                    }
                    if(m == 1)   //判断当参数m为1时将分钟对应的两位数码管关闭
                    {
                           hour_display();
                           miao_display();
                    }
                    if(m == 2)   //判断当参数m为2时将秒数对应的两位数码管关闭
                    {
                           hour_display();
                           fen_display ();
                    }
             }            
      }     
}
//------------------汇总以上将数码管点亮的函数(数码管的状态将随参数的改变而变化----------------------//
void display()
{
      alldis() ;
      fourdis();      
}
第三部分:延时类函数
//---------通过数码管显示来做到延迟的函数,为按键延时消抖做准备---------//
voiddelay0(uchar z)
{
      for(;z > 0;z--)
             display();      //将数码管以现在的状态点亮的函数        
}
//------毫秒级延时函数;当z = 1时,即delay(1)代表运行时间为1ms-----//
void delay(uintz)                                   
{                                                            
      uint x,y;
      for(x = z;x > 0;x--)
             for(y = 114;y > 0;y--);
}   
第四部分:中断类函数
//-------------------定时器0中断函数(控制每秒秒数增1,秒数、分钟为60进制,小时为24进制)----------------------//
void timer_0()interrupt 1
{
      TH0 = 0x4B;
      TL0 = 0xFC;       //将定时器0设置为计时50ms中断1次
      n++;                     //参数n存储定时器0中断次数,来计时是否过1s
      n1++;                   //参数n1存储定时器0中断次数控制数码管闪烁频率
      if(n1 == 5)           //当n1等于5时将要修改位对应的数码管点亮(或关闭)
             flag = ~flag,n1 = 0;
      if(n >= 20)           //当n等于20时说明已中断1s,将n清零并使秒数增1
      {
             n = 0;
             miao++;
      }
      if(miao >= 60)     //当秒数等于60时使秒数清零并使分钟增1,使秒数满
      {                          //足60进制
             miao = 0;
             fen++;   
      }
      if(fen >= 60)       //当分钟等于60时使分钟清零并使小时增1,使分钟满                 {                          //足60进制
             fen = 0;
             shi++;
      }
      if(shi >= 24)        //当小时等于24时使小时清零,使小时满足24进制
             shi = 0;
}
//-----定时器1中断函数,每50ms中断1次,判断是否有按键按下-----//
void timer1()interrupt 3
{
      TH1 = 0x4B;
      TL1 = 0xFC;              //将定时器1设置为50ms计数
      if(key_3 == 0)            //判断K3按键是否按下
      {
             m = 0;
             delay0(10);          //按键延时消抖
             if(key_3 == 0)
                    shezhi = ~shezhi;      //打开数值设置或者关闭数值设置     
delay0(10);          //延时消抖
           //     while(!key_3)
      //            display();      
      }
      if(key_4 == 0&&shezhi == 1) //判断在开启设置数值状态K4是否按下
      {
             delay0(10);                        //按键延时消抖
             if(key_4 == 0)     
                    m++;                           //当K4按键按下使闪烁位后移两个
             if(m >= 3)                         //当闪烁位超过秒数两位时时,使之重新回
m = 0;                         //到小时对应的两位数码管使之闪烁
      delay0(10);                        //按键延时消抖
      //     while(!key_4)
      //            display();
      }
      if(key_2 == 0&&shezhi == 1)//判断在开始数值设置K2是否按下
      {
//--------此参数flag可以设置当按键按下时对应数码管是否闪烁---------//
flag = 1;        
             delay0(8);                         //延时消抖
             if(key_2 == 0)                  
             {
                    if(m == 0)                  //当m等于0,说明此时设置的是小时,
                           shi++;                  //小时数值上增1
                    if(m == 1)                  //当m等于1,说明此时设置的是分钟,
                           fen++;                  //分钟数值上增1
                    if(m == 2)                  //当m等于2,说明此时设置的是秒数,
                           miao++;               //秒数数值上增1
             }
//------这条语句可使在设置数值状态下,长按按键时数值连续增长------//
             delay0(8);                          //按键消抖延时
//------------------------------------------------------------------------------------------//
           //---这两条语句可以使在设置数值状态下,长按按键闪烁位也只增1---//
      //     while(!key_2)
           //     display();
           //------------------------------------------------------------------------------------------//
      }
      if(key_1 == 0&&shezhi == 1) //判断在开始数值设置K1是否按下
      {
      //--------此参数flag可以设置当按键按下时对应数码管是否闪烁---------//
flag = 0;                      //此时对应的数码管处于长亮状态
             delay0(8);                   //按键延时消抖
             if(key_1 == 0)
             {
                    if(m == 0)                         //当m等于0,说明此时设置的是小时,
                           shi--;                           //小时数值减1
                           if(shi == 255)
                                  shi = 23;
                    if(m == 1)                         //当m等于1,说明此时设置的是分钟,
                           fen--;                           //分钟数值减1
                           if(fen == 255)
                                  fen = 59;
                    if(m == 2)                         //当m等于2,说明此时设置的是秒数
                           miao--;                        //秒数数值减1
                           if(miao == 255)
                                  miao = 59;
             }
//------这条语句可使在设置数值状态下,长按按键时数值连续增长------//
             delay0(8);                                 
//------------------------------------------------------------------------------------------//
//---这两条语句可以使在设置数值状态下,长按按键闪烁位也只增1---//
             //while(!key_1)
             //     display();
//------------------------------------------------------------------------------------------//
      }     
}
void main()
{
        init();
        while(1)
                display();                                                                 
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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