如何制作atmega 128电子表和秒表?

How to make atmega 128 electronic watch and stopwatch?

`#include <mega128.h>

unsigned int   KEYs_NUMs = 0, FLAG_RUNs = 0, TIME_DAYs = 1, TIME_HOUR = 0, TIME_MINs = 0, TIME_SECs = 0, TIME_10ms = 0, TIME_CNTs = 0 ;
unsigned int   TIME_TMR0 = 0, TIME_IMSI, SEGs_NUMs = 0  ;
unsigned int   TIME_S0, TIME_S1, TIME_M0, TIME_M1, TIME_H0, TIME_H1 ; 
unsigned int   IMSI = 0, DAT5 = 0, DAT4 = 0, DAT3 = 0, DAT2 = 0, DAT1 = 0, DAT0 = 0 ;
unsigned int   mode = 0 ;
unsigned char  SEG7[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7C, 0x07, 0x7F, 0x67} ;
unsigned char  FNDs[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7C, 0x07, 0x7F, 0x67} ;

 interrupt [EXT_INT4] void ext_int4_isr(void)
 {
   KEYs_NUMs += 1 ;
   if(KEYs_NUMs == 1)       { mode = 1 ; }  
   else                     { mode = 0 ; KEYs_NUMs = 0 ; }    
 }

  interrupt [EXT_INT5] void ext_int5_isr(void)
 {
   if(mode == 1)
   {   
     KEYs_NUMs += 1 ;
     if(KEYs_NUMs == 1)       { FLAG_RUNs = 1 ; }
     else if(KEYs_NUMs == 2)  { FLAG_RUNs = 0 ; }
     else                     { FLAG_RUNs = 1 ; KEYs_NUMs = 1 ; } 
   }
 }

  interrupt [EXT_INT6] void ext_int6_isr(void)
 { 
   if(mode == 1)
   {
     KEYs_NUMs -= 1 ;
     if(KEYs_NUMs == 1)       { TIME_MINs = 0, TIME_SECs = 0, TIME_10ms = 0, TIME_CNTs = 0 ; }
   }
 }

 interrupt [EXT_INT7] void ext_int7_isr(void)
 {
  
 }

 interrupt [TIM0_OVF] void timer0_ovf_isr(void)
 {   
   TCNT0 = 0x06 ;
 // Place your code here 
   TIME_TMR0 += 1 ;  // 1ms
   if(TIME_TMR0 >= 1000)
   {  TIME_TMR0 = 0 ;  TIME_SECs += 1 ;  }
   if(TIME_SECs > 59)
   {  TIME_SECs = 0 ;  TIME_MINs += 1 ;  }
   if(TIME_MINs > 59)
   {  TIME_MINs = 0 ;  TIME_HOUR += 1 ;  }
   if(TIME_HOUR > 23)  
   {  TIME_HOUR = 0 ;  TIME_DAYs += 1 ;  }
   if(TIME_DAYs > 31)
   {  TIME_DAYs = 1 ;  }
   
   TIME_IMSI = TIME_HOUR ;
   TIME_H1 = TIME_IMSI/10 ;
   TIME_H0 = TIME_IMSI - TIME_H1*10 ;

   TIME_IMSI = TIME_MINs ;
   TIME_M1 = TIME_IMSI/10 ;
   TIME_M0 = TIME_IMSI - TIME_M1*10 ;   

   TIME_IMSI = TIME_SECs ;
   TIME_S1 = TIME_IMSI/10 ;
   TIME_S0 = TIME_IMSI - TIME_S1*10 ;
   
   if(SEGs_NUMs > 6)  { SEGs_NUMs = 0 ;  }
   SEGs_NUMs += 1 ;
   if(SEGs_NUMs == 1)
   { 
      PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ;  PORTA.1 = 1 ;
      PORTD = SEG7[TIME_S0] ; 
      PORTA.0 = 0 ;
   }
   else if(SEGs_NUMs == 2)
   {
      PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ;  PORTA.0 = 1 ;
      PORTD = SEG7[TIME_S1] ; 
      PORTA.1 = 0 ;   
   }
   else if(SEGs_NUMs == 3)
   {
      PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.1 = 1 ;  PORTA.0 = 1 ;
      PORTD = SEG7[TIME_M0] ; 
      PORTA.2 = 0 ;   
   }      
   else if(SEGs_NUMs == 4)
   {
      PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ;  PORTA.0 = 1 ;
      PORTD = SEG7[TIME_M1] ; 
      PORTA.3 = 0 ;   
   }
   else if(SEGs_NUMs == 5)
   {
      PORTA.5 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ;  PORTA.0 = 1 ;
      PORTD = SEG7[TIME_H0] ; 
      PORTA.4 = 0 ;   
   }
   else
   {
      PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ;  PORTA.0 = 1 ;
      PORTD = SEG7[TIME_H1] ; 
      PORTA.5 = 0 ;    
   }
       
   if(TIME_TMR0 < 500)  {  PORTA.7 = 1 ;  }   // LED off
   else                 {  PORTA.7 = 0 ;  }   // LED on  
   
 } 

 void main(void)
 {
   DDRA=(1<<DDA7) | (0<<DDA6) | (1<<DDA5) | (1<<DDA4) | (1<<DDA3) | (1<<DDA2) | (1<<DDA1) | (1<<DDA0);
   PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
   DDRD=(1<<DDD7) | (1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
   PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
   ASSR=0<<AS0;
   TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (1<<CS02) | (0<<CS01) | (0<<CS00);
   TCNT0=0x06; OCR0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
   TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (1<<TOIE0);
   ETIMSK=(0<<TICIE3) | (0<<OCIE3A) | (0<<OCIE3B) | (0<<TOIE3) | (0<<OCIE3C) | (0<<OCIE1C);
// External Interrupt(s) initialization
   EICRA=(0<<ISC31) | (0<<ISC30) | (0<<ISC21) | (0<<ISC20) | (0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
   EICRB=(1<<ISC71) | (0<<ISC70) | (1<<ISC61) | (0<<ISC60) | (1<<ISC51) | (0<<ISC50) | (1<<ISC41) | (0<<ISC40);
   EIMSK=(1<<INT7) | (1<<INT6) | (1<<INT5) | (1<<INT4) | (0<<INT3) | (0<<INT2) | (0<<INT1) | (0<<INT0);
   EIFR=(1<<INTF7) | (1<<INTF6) | (1<<INTF5) | (1<<INTF4) | (0<<INTF3) | (0<<INTF2) | (0<<INTF1) | (0<<INTF0);
// Globally enable interrupts
   #asm("sei")

   while (1)
   { 
     if(mode == 1)
     { 
       if(FLAG_RUNs)  { TIME_CNTs += 1 ;  }  // 1ms
  
       if(TIME_CNTs > 99 )  { TIME_CNTs = 0 ;  TIME_SECs += 1 ; }
       if(TIME_SECs > 59 )  { TIME_SECs = 0 ;  TIME_MINs += 1 ; }
       if(TIME_MINs > 59 )  { TIME_MINs = 0 ;  }
       TIME_10ms = TIME_CNTs/10 ;

       SEGs_NUMs ++ ; 
       if(SEGs_NUMs > 5)  { SEGs_NUMs  = 0 ; }  

      switch(SEGs_NUMs)
      {
         case 0 :  PORTA.0 = 0 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 1 ; 
                   PORTA.5 = 1 ;
                   PORTD = FNDs[DAT0] ;  break; 
         case 1 :  PORTA.0 = 1 ; PORTA.1 = 0 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 1 ; 
                   PORTA.5 = 1 ;
                   PORTD = FNDs[DAT1] ;  break; 
    
         case 2 :  PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 0 ; PORTA.3 = 1 ; PORTA.4 = 1 ; 
                   PORTA.5 = 1 ; 
                   PORTD = FNDs[DAT2] ;  break;  
         case 3 :  PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 0 ; PORTA.4 = 1 ; 
                   PORTA.5 = 1 ;
                   PORTD = FNDs[DAT3] ;  break; 
    
         case 4 :  PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 0 ; 
                   PORTA.5 = 1 ;
                   PORTD = FNDs[DAT4] ;  break;  
         case 5 :  PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 1 ; 
                   PORTA.5 = 0 ;
                   PORTD = FNDs[DAT5] ;  break;   
      }
         IMSI = TIME_MINs ;
         DAT5 = IMSI/10 ;
         DAT4 = IMSI - DAT5*10 ;
      
         IMSI = TIME_SECs ;
         DAT3 = IMSI/10 ;
         DAT2 = IMSI - DAT3*10 ;
      
         IMSI = TIME_10ms ;
         DAT1 = IMSI/10 ;
         DAT0 = IMSI - DAT1*10 ;
     } 
   }
 }

` 我编写了一个代码,通过将时钟代码放入定时器中断并将秒表代码放入 'while' 来按下模式按钮来更改模式。如果您更改模式,它会根据经过的时间移动到秒表,如果您启动秒表,计数器会从分钟数字开始计时。当您重置时钟并 return 时,时钟从头开始计数。即使我改变了模式,我怎样才能保持定时器运行?以及如何防止计时器的时间被传输到秒表?

根据问题的评论:

interrupt [EXT_INT4] void ext_int4_isr(void)
{
    // just toggle the mode, no need for counting any occurrences...
    mode = !mode; // alternatively mode = 1 - mode

    if(mode)
    {
        // reset the stop watch on having been enabled:
        flagRuns = 0;
        // reset the counter as well!
        // TODO: common function for!
        // should work calling ext_int6_isr directly, too
    }
}

interrupt [EXT_INT5] void ext_int5_isr(void)
{
    // can toggle unconditionally, as the flag is not evaluated if not
    // in stop watch mode and is reset upon ENTERING the mode (this changed
    // compared to your original version!)
    flagRuns = !flagRuns;
}

interrupt [EXT_INT6] void ext_int6_isr(void)
{ 
    if(mode && !flagRuns)
    {
        // reset, common function, see above
    }
}

您很可能需要声明跨 ISR 和主例程或跨不同 ISR volatile 写入和读取的变量,以避免缓存效应。