Hallo mare_crisium,

herrlich - eine ZAK (ZustandsAutomatenKanone), made by mare_crisium. Einfach perfekt. Und ein schönes Lehrstück zur Tastenverwaltung. Ich muss mal sehen, was davon ich abkupfern kann (ich nehme mir einfach diese Freiheit *ggg* - und danke schon mal dafür).

Das Thema interessiert mich, weil ich derzeit seit vielen Tagen (wieder mal) an einem Pacer arbeite - das ist ein Blinker (vllt. mit Piepsmöglichkeit), der mit zwei LEDs und zwei Tastern ausgestattet ist und mir für Lauftraining eine Schrittfrequenz vorgibt. Also eine Art Metronom. Kein Display - ausser den beiden LEDs.

Die Tasten dienen zum Einschalten des aktiven Modus, zum Ausschalten, zum Ändern der Frequenz rauf und runter, zum Ein-/Ausschalten des Piepsers, zum Ändern eines Zeit-Mess-Taktes - weil das Dings ohne Quarz läuft und daher nicht wirklich stabil in der Frequenz ist. Dieses Gimmik ist auch ne Kanone - aber es soll halt alles den Anschein von Perfektion haben. Vielleicht noch mehr Gimmiks.

Nun habe ich meine Tasten nicht nur zu entprellen gehabt, sondern wollte auch in einem Horizont von etwa 2,5 sec wissen, wie lange die Taste schon gedrückt bzw. gelöst wurde. Damit kann/will ich im Menue herumtoben, je nachdem welche Taste in welcher Reihenfolge wie lange gedrückt wurde. Kennen wir von mancher alten Digital-Armbanduhr, von Fahrradcomputern etc. Also stelle ich den Tastenstatus der beiden Tasten TAB und TAU (Taste ABwärts und Taste AUfwärts) im 100 Hz Rhythmus in einer ISR fest - und zähle die jeweiligen Zeitabschnitte (in 10 ms-Schnitten) "gelöst" oder "gedrückt" ab dem letzen Wechsel. Damit kann ich dann recht gut spielen.

Das Ganze läuft dann so auf (m)einem tiny85:

Code:
/* >>   Sicherung 22Jan10 0930   ...C2..\PCR_80\PCR_80_tmr_x51.c
 Es folgt ein Auszug aus einem funktionierenden Teilprogramm
 ===================================================================================
 Target MCU        : ATtiny85
 Target Hardware   : Pacer ...
 Target cpu-frequ. : In der Quelle wählbar
 ===================================================================================
        Enthaltene Routinen:        Nur Timer
 ...
 void TC1TMR_init(void)         // Init Tmr/Cntr1, 8-Bit auf ca. 100 Hz = 0,01 s 50
 ...
 ISR(TIM1_COMPA_vect)           // Vektor 4 (1 ... 4 !!!)                 doc S  50
 ...
 ===================================================================================
  *** Versionsgeschichte:
 ====================
 x51 22Jan10 0930 Weiter in der Blink-organisation
 ...
 x00 07Dez09 2220 Übernahme vom Original, s.u., 
 ===================================================================================
  *** Aufgabenstellung : Timer für pacer80
  Original:  ...C2..\pacer_61\pcr61_tmr_x21.c       x21 11feb09
       war:  ...C2..\wallr_20\WR3_tmr_x03.c   30Nov08
 ================================================================================ */
// ================================================================================


// ================================================================================
// ===  Initialisierung fuer Timer1 tiny85 ========================================
 void TC1TMR_init(void)         // Init Tmr/Cntr1, 8-Bit auf ca. 100 Hz = 10 ms
 {	                          
  TCCR1  |=  (1<<CTC1);         // Timer im CTC-Mode, Top=OCRA            doc S  92
  TCCR1  |=  (1<<CS12)|(1<<CS11)|(1<<CS10);
                                // Prescaler Clock1/64                    doc S  93
  OCR1C   =   152;      // Preset/Preload = 152 => getestet ca. 0,010s @ 1,0Mhz
  TIMSK  |=  (1<<OCIE1A);       // Tmr/Cntr1 CompareA interrupt enabled
//SetBit (PB, rLED);            // Testphase: Zeitanzeige durch rLED 
 }                                
// ================================================================================


// ================================================================================
// ===  Nicht unterbrechbare ISR für timer1 =======================================
// Interrupt mit ca. 100 Hz/10 ms. Diese ISR wird benutzt
//   A  zum Auslesen der Tasten
//      Nach Ende der Routine sind die Tastenstati in den Statusbytes
//   B  Zum Setzen der LEDs 
//      Es werden beide LEDs durch das vorgegebene Bitmuster bedient ( 0 / 1 )
//      AUSNAHME : Wenn 
//
 ISR(TIM1_COMPA_vect)           // Vektor 4 (1 ... 4 !!!)                 doc S  50
 {                                
                // Ab hier mal ähnlicher Aufbau wie bei Timer0
 Izeit_1 ++;                    //  
 if (Izeit_1 >= 100)            //Interrupt-Timer = "Zeithorizont" begrenzen auf 
                                // 100 = Zeit für EINE Sekunde
 {                                
   Izeit_1   =  1;              // Rückstellen auf Eins
   Isecflag  = 55;              // .. und Sekundenflag setzen
 }                                
                                  
// - -  Tastenstatistik    - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - -  Es wird geprüft ob eine Taste gedrückt ist - - - - - - - - - - - - - - - -
//   WENN diese Taste gedrückt ist, wird einfach bis 254 hochgezählt
//   WENN diese Taste NICHT gedrückt ist, wird schnell (z.B.20) runtergezählt
// Änderung 01Jan10  WENN Taste NICHT gedrückt ist, wird *cnt auf Null gesetzt
                                  
// - -  Zuerst für TAB   - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                  
 TABsts = (!(PINB & (1<<TAB))); // GENAU so *ggg* -- Status von Taste TAB holen
                                  
 if (TABsts)                    // Taste TAB gedrückt?
 {                                
   if (TABcnt < 254)            // Wenn counter < 250
   {                              
     TABcnt     ++;             //   dann hochtackern
     nTABcnt    = 0;            //   und Not-TABcount auf Null setzen
   }                              
 }                                
 else                           // Taste TAB ist nicht gedrückt
 {                                
   if (nTABcnt < 254)           // Wenn not-counter < 250
   {                              
     nTABcnt    ++;             //   dann hochtackern
     TABcnt     = 0;            //   und TABcount auf Null setzen
   }                              
 }                                
// - -  .. und auch für TAU  - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                  
//  . . . .                       
                                  
// - -  Die Tastenstati sind ausgelesen  - - - - - - - - - - - - - - - - - - - - -
                                            
// . . . .                        
 return;                          
}                                 
// ================================================================================


// ================================================================================
// . . . .                        
// ================================================================================


// ================================================================================
// =====  ENDE    Subroutinen  ====================================================
// ================================================================================


// ================================================================================
// =====  Sonstige Angaben     ====================================================
// ================================================================================
                                  

 #define TAU     1              // Taster "Aufwärts", PB1
 #define TAB     2              // Taster "Abwärts",  PB2 = "Start"Taste
                                  
 #define PB     PORTB           // Kurzwort für PORTB
 #define gLED    4              // Grüne LED      PB4
                                // Typ LITEON-LTL1CHKGKNN = CSD-25-3020320
                                //      572 nm, 45°,    IF 20 mA bei UF 2,4 V
                                //      Peak FW 60 mA, DC FW 30 mA
 #define rLED    3              // Rote LED       auf PB3
                                  
 #define IsBitSet(ADDR,BIT)     (((ADDR)&(1<<BIT))?1:0) // Fragt Bit = 1?
 #define IsBitClr(ADDR,BIT)     (!((ADDR) & (1<<BIT)))  // Fragt Bit = 0?
                                  
volatile uint16_t Izeit_1;      // Timer1, ähnlich ~0
                                  
volatile uint8_t  Isecflag;     // Sekundenflag...55 = Sekunde in ISR erreicht
                                //                 0 = Sekunde in main übernommen
                                  
  volatile uint8_t TABsts;      // Status derTaste TAB
                                //   = 0 <=> nicht gedrückt, =1 <=> gedrückt
  volatile uint8_t TABcnt;      // Counter für Taste TAB, 0 ... 255
  volatile uint8_t nTABcnt;     // Counter für Taste notTAB, 0 ... 255
Dies vielleicht als Anhaltspunkt.