/* Beispielprogramm zur Tastenentprellung und -dekodierung. Beim æP AT90S8515 werden die Eingaenge von PortA (int. pullup) gegen 0V geschaltet (aktiv-low). Beim 1. Tastendruck wird der normale Code 'A' - 'H' erzeugt (bit0 -> bit7). Wird die Taste gedrueckt gehalten, wird der betreffende repeat Code erzeugt, sofern dieser nicht mit ' ' deaktiviert ist. In 'main()' wird auf einen Tastendruck gewartet und eine an PortC geschaltete LED gegen 0V aktiviert. Weitere Tastendruecke (oder repeat) togglen die LED. Es wird jeweils nur eine Taste ausgewertet; diese kann aber gedrueckt bleiben, ohne andere Tasten zu blockieren: n-key-rollover. Schalter und Taster koennen daher gemischt verwendet werden. Der aktuelle, entprellte Zustand von PortA findet sich in 'entprellte_tasten'. Compiler: icca90 Alle Angaben ohne Gewaehr. Michael Nowak, www.mino-elektronik.de */ #include #include #define MAX_BITS 8 // hier nur ein Port-Byte #define TASTENWERT unsigned char // auch short oder long #define T0_NACHLADEWERT -39 // fuer ca. 100 Hz bei 4 MHz #define ENTPRELL_ZEIT 5 // 5 Zyklen -> 50ms entprellen #define FIRST_REPEAT 50 // 0,5 Sek. Pause bei gedrueckter Taste #define NEXT_REPEAT 10 // danach Wiederholung alle 0,1 Sek. static char taste; // 0 oder Tastencode static TASTENWERT entprellte_tasten; // zur externen Verwendung flash char tast_tab[] = "ABCDEFGH"; // 1. Tastencode flash char rep_tast_tab[] = "a c e g "; // repeatcode teilweise zulassen char lese_taste() { char temp; TIMSK &= 0xfd; // T0_overflow-interrupt kurz verbieten temp = taste; // Tastencode lesen taste=0; // und loeschen TIMSK |= 0x02; // T0-int wieder freigeben return(temp); } static void dekodiere_taste() { char n; TASTENWERT temp, aenderung; static TASTENWERT temp_tasten, letzte_aenderung; static char rep_flag=0, entprell_ctr=0, rep_ctr=0; temp = PINA; // PortA als aktiv-low Eingang temp = ~temp; // alle Bits invertieren if(rep_ctr) rep_ctr--; // repeat-counter dekrementieren entprell_ctr++; // Entprell-counter inkrementieren if(temp != temp_tasten) { // Aenderung der Bits ? temp_tasten=temp; // ja, speichern entprell_ctr=0; // und neu entprellen return; // mehr nicht } if(entprell_ctr < ENTPRELL_ZEIT) return; // Entprellzeit abwarten entprell_ctr=0; // und neu starten // Tasten sind entprellt // jetzt auf positive Aenderungen testen aenderung = (temp_tasten ^ entprellte_tasten) & temp_tasten; entprellte_tasten = temp_tasten; // und letzten Zustand merken if(aenderung) { // falls neue Tasten aktiviert letzte_aenderung = aenderung; // Aenderung merken rep_ctr = FIRST_REPEAT; // und 1.Repeat aktivieren rep_flag = 0; } else if(rep_ctr == 0 && rep_flag) { // keine neue Taste aber repeat aktiv aenderung = entprellte_tasten & letzte_aenderung; // letzte Aenderung rep_ctr = NEXT_REPEAT; // wiederholen, mit kurzer repeat-Zeit } // Auswertung der Tasten temp = aenderung; n=0; do { // bit suchen if(temp & 1) { // bit gefunden if(temp == 1) { // und nur eine Taste if(!rep_flag) { // kein repeat: normale Codes verwenden n = tast_tab[n]; rep_flag = 1; // aber beim naechsten Mal repeat ! } else n = rep_tast_tab[n]; // repeat ist schon aktiv if(n != ' ') taste = n; // repeat nur mit gueltigem Code else rep_flag = 0; // kein repeat, wenn keine gueltige taste } return; // taste erkannt, dekodierung fertig } n++; temp >>= 1; } while(n < MAX_BITS); return; // keine taste gefunden } void interrupt [TIMER0_OVF0_vect] timer0_int() { TIMSK &= 0xfd; // weitere T0_overflow-interrupt verbieten _SEI(); // und Interrupts global zulassen TCNT0 = T0_NACHLADEWERT; dekodiere_taste(); TIMSK |= 0x02; // T0-int wieder freigeben } void main() { char temp; TCNT0 = T0_NACHLADEWERT; TCCR0 = 0x05; // timer0 mit /1024 Vorteiler TIMSK |= 0x02; // timer0 overflow int PORTA = 0xff; // PortA pullups einschalten _SEI(); DDRC = 0xff; // alle LEDs zun„chst eingeschaltet PORTC = 0; // aktiv-low for(;;) { while(!(temp = lese_taste())); // auf Tastendruck warten switch(temp) { case 'A': case 'a': DDRC ^= 1; // nur LED invertieren break; case 'B': case 'b': DDRC ^= 2; break; case 'C': case 'c': DDRC ^= 4; break; case 'D': case 'd': DDRC ^= 8; break; case 'E': case 'e': DDRC ^= 16; break; case 'F': case 'f': DDRC ^= 32; break; case 'G': case 'g': DDRC ^= 64; break; case 'H': case 'h': DDRC ^= 128; break; } } }