proteus论坛|仿真论坛
直播中

bbxyliyang

12年用户 145经验值
擅长:电源/新能源 模拟技术 嵌入式技术 处理器/DSP 光电显示 EDA/IC设计
私信 关注
[经验]

基于51单片机时间可调整电子时钟程序

1 、此款电子时钟,时间可以设置,有4个按键,一个功能按键,一个加,一个减,一个确定按键。
2、按下功能按键一下,时钟走时停止,时两位数码管闪烁,代表此时再调时状态,这个时候加减按键就可以调整时钟,再次按下功能按键,就可以调整分钟,再按一下功能按键就可以设置秒。设置好时间后我们按确定按键,时钟开始走时。
3、这个程序将很好的教会我们怎么让数码管闪烁显示。
#include
typedef unsigned int UINT;
typedef unsigned char UCHAR ;
***it key1=P3^3;
***it key2=P3^4;
***it key3=P3^5;
***it key6=P3^6;
***it LE1 = P3^1;  //定义位控口   
***it LE2 = P3^2;  //定义段控口
UCHAR MODE ;
UCHAR page ;
signed char  HH = 0;  //小时初始值
signed char  MM = 0;  //分钟初始值
signed char SS = 0;  //秒初始值
UINT u1_10ms  = 0; //10ms计数
UINT u2_10ms  = 0;
bit T_CYCLE = 0;
extern void T0_Init(void); //初始化定时器,函数定义在timer.c
UCHAR code NUM[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};

void delay(UINT t) //延时t时钟周期
{
while (t--) ;
}

void H_Increase(void) //小时增1
{
if(HH<23) HH++;
else
{
  HH = 0;
}
}

void M_Increase(void)  //分钟增1
{
if(MM<59) MM++;
else
{
  MM = 0;

}
}

void S_Increase(void)  //秒增1
{
if(SS<59) SS++;
else
{
  SS = 0;

}
}
void H(void) //小时增1
{
if(HH>0) HH--;
else
{
  HH =23;
}
}

void M(void)  //分钟增1
{
if(MM>0) MM--;
else
{
  MM = 59;

}
}

void S(void)  //秒增1
{
if(SS>0) SS--;
else
{
  SS = 59;

}
}
void display(UCHAR SEG,UCHAR Digi) //显示一位数码管,SEG = 0-9数字,Digi = 第0-6位
{
LE2 = 1;
P0 = (0x01< LE2 = 0;
P0 = 0x00;
LE1 = 1;
P0 = NUM[SEG];
if (Digi==1||Digi==4) P1&= 0x7f ;  //显示分隔符
delay(50);
P0 = 0xff;
LE1 = 0;
}
void key()
{

if(key1==0)
{
  delay(2);
  if(key1==0)
  {
   while(!key1);
        TR0=0;
  
       if(MODE == 3) MODE = 1;
   else MODE ++;
   
  
     }
  }
   
  if(key2==0)
{
  delay(2);
  if(key2==0)
  {
   while(!key2);
  
     if(MODE == 1) H_Increase() ;
    if(MODE == 2) M_Increase() ;
     if(MODE == 3) S_Increase() ;
     
     }
  }
if(key3==0)
{
  delay(2);
  if(key3==0)
  {
   while(!key3);
  
           if(MODE == 1) H() ;
    if(MODE == 2) M() ;
     if(MODE == 3) S() ;
     
           }
  
  
   
  }

   if(key6==0)
{
  delay(2);
  if(key6==0)
  {
   while(!key6);
         TR0=1;
   MODE=0;
     }
  }
}
void main(void)
{
    P1 = 0xff;
    LE1 = 0;
    LE2 = 0;
T0_Init();
    while(1)
{
     key();
  if(MODE != 1 || T_CYCLE)
  {
   display(HH/10,0);  //显示小时十位数
   display(HH%10,1);  //显示小时个位数
      display(10,2);  
  }
  if(MODE != 2  || T_CYCLE)
  {
   display(MM/10,3);  //显示分钟十位数
   display(MM%10,4);  //显示分钟个位数
   display(10,5);  //显示小时个位数
  }
   if(MODE != 3  || T_CYCLE)
  {
  display(SS/10,6);  //显示秒十位数
  display(SS%10,7);  //显示秒个位数
  }
}
}
extern void key_Process(void);
extern void S_Increase(void);

void T0_Init(void)
{
TMOD = 0x11;
//定时器赋初始值,定时时间为10ms。
TH0 = 0xd8;
TL0 = 0xf0;
TH1 = 0xd8;
TL1= 0xf0;
ET0=1;
ET1=1;
TR0=1;
TR1=1;
EA=1;
}

void T0_INTSrv(void) interrupt 1
{
//定时器重新开始计时。
TH0 = 0xd8;
TL0 = 0xf0;
u1_10ms ++;
if (u1_10ms>99) // 1000 ms = 1 second
{
  u1_10ms = 0;
  SS++;
  if(SS==60)
  {
   SS=0;
   MM++;
   if(MM==60)
   {
    MM=0;
    HH++;
    if(HH==24)
    HH=0;
   }
  }
}
}
void T1_INTSrv(void) interrupt 3
{
//定时器重新开始计时。
TH0 = 0xd8;
TL0 = 0xf0;
u2_10ms ++;
if (u2_10ms%10==0) // 100 ms
{
  T_CYCLE = ! T_CYCLE; //闪烁循环
}
}

回帖(5)

bbxyliyang

2019-7-25 07:48:27
受到警告
提示: 作者被禁止或删除 内容自动屏蔽
举报

bbxyliyang

2019-7-29 15:00:47
用按键和数码管以及单片机定时器实现一个简易的可以调整的时钟,要求如下:
8位数码管显示,显示格式如下
时-分-秒
XX-XX-XX
要求:系统有三个按键,功能分别是调整,加,减。在第一次按下调整键时候,停止走时,显示秒的两位数码管以1 Hz 频率闪烁;如果第二次按下调整键,则分开始闪烁,秒恢复正常显示;如果第三次按下调整键,则时开始闪烁,分恢复正常显示;如果第四次按下调整键,时恢复正常显示,开始走时。在数码管闪烁的时候,按下加或者减键可以调整相应的显示内容。
/*****************************
作者:liyang
日期:2019年7月29日
目标MCU:STC89C51  晶振:11.0592M
******************************/
#include
typedef unsigned char uint8;
typedef unsigned int uint16;
uint8 LedBitCnt; //LedBitCnt控制数码管的位选
uint8 flagm=0,flagf=0,flags=0;//时分秒闪烁的控制标志位
uint8 ms2_flag; //2ms数码管动态扫描时标消息
uint ms10_flag,ms500_flag;
uint8 ms2_cnt,ms10_cnt,count,s1num;
uint8 dis_buff[8]={0};
uint8 shi=12,fen=23,miao=56;
uint8 code SegTab[]={0x3f,0x06,0x5b,0x4f,
                                         0x66,0x6d,0x7d,0x07,
                                         0x7f,0x6f,0x40,0x00};
***it ADDR0 = P2^0;//74hc138的输入控制端A
***it ADDR1 = P2^1;//74hc138的输入控制端B
***it ADDR2 = P2^2;//74hc138的输入控制端C
***it adjust=P3^2;
***it add=P3^3;
***it sub=P3^4;
void delayms(uint8  z)
{
         uint8 i,j;
         for(i=z;i>0;i--)
                 for(j=110;j>0;j--);
}

void disp()
{
         P0=SegTab[dis_buff[LedBitCnt]];
         switch(LedBitCnt)
         {
                 case 0:
                 ADDR0=0;ADDR1=0;ADDR2=0;
                 break;
                 case 1:
                 ADDR0=1;ADDR1=0;ADDR2=0;
                 break;
                 case 2:
                 ADDR0=0;ADDR1=1;ADDR2=0;
                 break;
                 case 3:
                 ADDR0=1;ADDR1=1;ADDR2=0;
                 break;
                 case 4:
                 ADDR0=0;ADDR1=0;ADDR2=1;
                 break;
                 case 5:
                 ADDR0=1;ADDR1=0;ADDR2=1;
                 break;
                 case 6:
                 ADDR0=0;ADDR1=1;ADDR2=1;
                 break;
                 case 7:
                 ADDR0=1;ADDR1=1;ADDR2=1;
                 break;
         }

}
void time_to_di***uff(void)
{
         if(flagm&(!ms500_flag))
         {   
                dis_buff[7]=11;
                 dis_buff[6]=11;
           }
           else
         {
                 dis_buff[7]=miao%10;
                 dis_buff[6]=miao/10;
         }
         dis_buff[5]=10;
         if(flagf&(!ms500_flag))
         {   
                dis_buff[4]=11;
                 dis_buff[3]=11;
           }
         else
         {
                 dis_buff[4]=fen%10;
                 dis_buff[3]=fen/10;
         }
         dis_buff[2]=10;
         if(flags&(!ms500_flag))
         {   
                dis_buff[1]=11;
                 dis_buff[0]=11;
           }
         else
         {
                 dis_buff[1]=shi%10;
                 dis_buff[0]=shi/10;
           }
}
void init()
{
         TMOD=0x11;
         TH1=0xf8;
         TL1=0xcd;
         TH0=0x4c;
         TL0=0x00;
         TR0=1;
         ET0=1;
         TR1=1;
         ET1=1;                        
}
void keyscan()
{
         if(adjust==0)
                 {
                         delayms(10);
                         if(adjust==0)
                                 {
                                         s1num++;
                                         while(!adjust);
                                         if(s1num==1)
                                         {
                                                 flagm=1;
                                                 TR0=0;
                                         }
                                 }
                 }
                 
                        if(s1num==2)
                 {
                         flagm=0;
                         flagf=1;
                 }

         if(s1num==3)
                 {
                         flagm=0;
                         flagf=0;
                         flags=1;
                 }
         if(s1num==4)
         {
                 TR0=1;
                 flags=0;
                 s1num=0;
         }
         if(adjust!=0)
                 {
                         if(add==0)
                         {
                                 delayms(10);
                                 if(add==0)
                                 {
                                         while(!add);
                                         if(s1num==1)
                                         {
                                                 miao++;
                                                 if(miao==60)
                                                         miao=0;
                                         
                                                
                                                
                                        }
                                         if(s1num==2)
                                         {
                                                 fen++;
                                                 if(fen==60)
                                                         fen=0;
                                                
                                       
                                        }
                                         if(s1num==3)
                                         {
                                                 shi++;
                                                 if(shi==24)
                                                         shi=0;
                                                
                                        }
                                 }
                         }
                         if(sub==0)
                         {
                                 delayms(10);
                                 if(sub==0)
                                 {
                                         while(!sub);
                                         if(s1num==1)
                                         {
                                         
                                                miao--;
                                                 if(miao==-1)
                                                         miao=59;
                                                
                                        }
                                         if(s1num==2)
                                         {
                                                 fen--;
                                                 if(fen==-1)
                                                         fen=59;
                                         
                                        }
                                         if(s1num==3)
                                         {
                                                 shi--;
                                                 if(shi==-1)
                                                         shi=23;
                                                
                                        }
                                 }
                         }
                 }
         
        
}
void main()
{
         init();
         EA=1;
         time_to_di***uff();
         P0=0x00;
         while(1)
         {               
                keyscan();
                 if(ms2_flag)
                         {
                                 ms2_flag=0;
                             LedBitCnt++;
                                 if(LedBitCnt>7)
                                 {
                                         LedBitCnt=0;
                                 }
                                 time_to_di***uff();
                                 disp();
                        
                        }        
                if(ms10_flag)
                         {
                                 ms10_flag=0;
                         }
         
        }
         
}
void timer0() interrupt 1
{
         TH0=0x4c;
         TL0=0x00;
         count++;
         if(count==20)
         {
                 count=0;
                 miao++;
                 if(miao==60)
                 {
                         miao=0;
                         fen++;
                         if(fen==60)
                         {
                                 fen=0;
                                 shi++;
                                 if(shi==24)
                                 {
                                         shi=0;
                                 }
                         }
                 }
         }

}
void timer1() interrupt 3  //定时1ms
{
         TH1=0xf8;
         TL1=0xcd;
         ms2_flag=1;   //用于数码管显示
         ms2_cnt++;
         if(ms2_cnt>=5)
         {
                 ms2_cnt=0;  
                 ms10_flag=1;//用于键扫描
                 if(++ms10_cnt>=50)
                         {
                                 ms10_cnt=0;
                                 ms500_flag=~ms500_flag;
                         }
         }
}
总结:1 先开辟一个数码管显示的缓冲区,动态扫描函数函数负责从这个缓冲区中取出数据,并扫描显示。而其他函数则可以修改该缓冲区,从而改变显示的内容。
2 要学会标志位的灵活应用
3 按键程序存在不足,使用了延时函数delayms(10),让控制器在这白白等待了10ms的时间,啥也没干。这是不可取的。其次while(!adjust);更是程序设计的大忌(极少的特殊情况例外)。原本是等待按键释放,结果CPU就一直死死的盯住该按键,其他事情都不管了。
4 要处理好按键程序不足,就得学习按键状态机

举报

bbxyliyang

2019-7-30 07:41:27
状态机的学习
有限状态机由有限的状态和相互之间的转移构成,在任何时候只
能处于给定数目的状态中的一个。当接收到一个输入事件时,状态机产生一个输出,同时也可能伴随着状态的转移。
#define key_input    PIND.7      // 按键输入口
#define key_state_0  0
#define key_state_1  1
#define key_state_2  2
char read_key(void)
{
static char key_state = 0;
char key_press, key_return = 0;
key_press = key_input;        // 读按键 I/O (状态机的输入)
switch (key_state)
{
case key_state_0:        // 按键初始态
        if (!key_press) key_state = key_state_1;  // 键被按下,状态转换到键确认态 , 确定下一次按键的状态值
break;
case key_state_1:        // 按键确认态
if (!key_press)
{
            key_return = 1;      // 按键仍按下,按键确认输出为“1”
            key_state = key_state_2;  // 状态转换到键释放态
}
else
            key_state = key_state_0;  // 按键已抬起,转换到 按键初始态
       break;
case key_state_2:
            if (key_press) key_state = key_state_0;  //按键已释放,转换到按键初始态
       break;
}  
      return key_return;
}
该简单按键接口函数 read_key()在整个系统程序中应每隔10ms
调用执行一次,每次执行时将先读取与按键连接的 I/O 的电平到变量 key_press 中,然后进入用 switch 结构构成的状态机。switch 结构中的 case 语句分别实现了 3 个不同状态的处理判别过程,在每个状态中将根据状态的不同,以及 key_press 的值(状态机的输入)确定输出值(key_return),和确定下一次按键的状态值(key_state) 。 函数 read_key()的返回参数提供上层程序使用。返回值为 0 时,表示按键无动作;而返回 1 表示有一次按键闭合动作,需要进入按键处理程序做相应的键处理。在函数 read_key()中定义了 3 个局部变量,其中 key_press和key_return为一般普通的局部变量,每次函数执行时,key_press 中保存着刚检测的按键值。key_return 为函数的返回值,总是先初始化为 0,只有在状态 1 中重新置 1,作为表示按键确认的标志返回。变量 key_state 非常重要,它保存着按键的状态值,该变量的值在函数调用结束后不能消失,
必须保留原值,因此在程序中定义为“局部静态变量” ,用static 声明。如果使用的语言环境不支持 static 类型的局部变量,应将 key_state 定义为全局变量(关于局部静态变量的特点请参考相关介绍 C 语言程序设计的书籍) 。
举报

bbxyliyang

2019-7-30 17:44:59
强制转化的应用:
1 、 uint a,b,c,d;
        a=At24c02Read(0); b=At24c02Read(1); c=At24c02Read(2); d=At24c02Read(3); MAX=((a*1000)+b*100+c*10+d);
        AT24C02函数是返回一个无符号字符,上面是我以前的代码,这个程序浪费个程序内存空间,其实用一个强制转化就可以解决问 题。 MAX=(((uint)At24c02Read(0)*1000)+(uint)At24c02Read(1)*100+(uint)At24c02Read(2)*10+(uint)At24c02Read(3));这样就可以节省很多内存空间。
举报

陈闽涛

2019-8-2 09:50:18
学习一下,分享的资料很详细呀
举报

更多回帖

发帖
×
20
完善资料,
赚取积分