- fchao-Sinus-Wechselrichter AliExpress         
Ergebnis 1 bis 6 von 6

Thema: kleine Entprellroutine - läuft nicht wie gedacht

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    25.08.2014
    Beiträge
    7

    kleine Entprellroutine - läuft nicht wie gedacht

    Anzeige

    E-Bike
    Hallo,

    ich habe eine kleine Routine zum Entprellen eines Tastersignals geschrieben. Ich benutze das MK2 Übungsboard mit einem 2MHz µC. Der Taster ist an Port D.3 angeschlossen. An den Ports B.1 bis B.3 sind die LEDs angeschlossen, an B.0 der Tongeber, der bei jedem Schalten einmal kurz piept. Über den externen Interrupt (bei fallender Flanke) werden die LEDs umgeschaltet (quasi in Form eines kleinen Binärzählers). Beim Drücken des Tasters wird leider öfter mehrere Male geschaltet, ich kann mir aber nicht erklären, warum das so ist.

    Hier die Entprellroutine:

    Code:
    #define bit_3 3
    
    .
    .
    .
    
    void entprellen()
    {
    	uint8_t zustand, alterzustand;
    	uint16_t countdown;
    	countdown = 255;
    	
    	while (countdown > 0)
    	{
    		zustand = PIND & (1<<bit_3);				// aktueller Schaltzustand (maskiert)
    		if (alterzustand != zustand) countdown = 255;	// bei Änderung zum vorherigen: Countdown von vorne
    		else countdown--;					// sonst: runterzählen
    		alterzustand = zustand;					// Schaltzustand merken
    	}
    	
    	return;
    }
    Zur Vollständigkeit die Interrupts:

    Code:
    ISR(INT1_vect)
    {
    	entprellen();
    	
    	temp = (PORTB>>1);
    	if (++temp == 8) temp = 0;
    	PORTB = (temp<<1);
    
           // Ton einschalten (Timer 0 Interrupt bei Überlauf aktiv)
           TIMSK0 = 1;
    }
    
    ISR(TIMER0_OVF_vect)
    {	
    	// aktuelles Ausgangssignal: Bits 1 bis 7 maskieren, bleiben unverändert
    	maske = PORTB & 0b11111110;
    	
    	// aktuelles Ausgangssignal: Bit 0 maskieren und umkehren
    	temp = PORTB & 1;
    	temp ^= 1;
    	
    	// Ausgabe des neuen Signals
    	PORTB = maske | temp;
                
           // Timer zurücksetzen
           TCNT0 = 190;
        
           // Ton unterbrechen
           if (++zaehler == 0) TIMSK0 = 0;
    }

    Ich hatte das ganze vorher schon in Assembler umgesetzt. Da funktioniert das Entprellen, beim Drücken des Tasters wird genau einmal weiter geschaltet. Aber meiner Meinung sind die C- und die Assembler-Version absolut gleichwertig.

    Code:
    entprellen:	; Register sichern
    	push r16
    	push r17
    	push r18
    	
    	ldi r16, 255
    	
    debounce:	; Zustand von PORT D einlesen und maskieren
    	in r17, PIND
    	andi r17, 0b00001000
    	
    	; Debounce-Zeit zurücksetzen, wenn der Schaltzustand anders ist
    	cpse r18, r17
    	ldi r16, 255
    	mov r18, r17
    	
    	; Countdown bis 0
    	dec r16
    	brne debounce
    	
    	; Register wiederherstellen
    	pop r18
    	pop r17
    	pop r16
    	
    	ret


    Wer weiß Rat?

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.683
    ... kleine Routine zum Entprellen eines Tastersignals ... Beim Drücken des Tasters wird leider öfter mehrere Male geschaltet ...
    Bei meinen Tastern (die 6Zent-Klasse ebenso wie die 20Zent-Klasse) stelle ich praktisch nie ein Prellen fest (seltsamerweise??) obwohl ich selten oder nicht bewußt irgendwelche Maßnahmen gegen EMV-Einflüsse treffe. Trotzdem habe ich manchmal Entprellmaßnahmen getroffen - allereinfachste Art, ich frage den Taster mehrfach hintereinander ab. Hier ein paar Codeschnippsel, das sollte reichen um den Vorgang zu verdeutlichen. Anm.: die Taster sind gegen GND geschaltet, daher gilt: PIN ist low => Taster gedrückt.

    Code:
      #define IsBitSet(ADDR,BIT)     (((ADDR)  &  (1<<BIT))?1:0)
                            // Fragt Bit = 1?
      #define IsBitClr(ADDR,BIT)     (!((ADDR)  &  (1<<BIT))?1:0)
                            // Fragt Bit ab
    
      #define PRTtstLCD     PIND
      #define Tst_A            6
    
      #define TAan          IsBitClr (PRTtstLCD, Tst_A)
                            // Taster A gedrückt ??
    
      if ( TAan && TAan )
                            // Das ist nun die eigentliche Abfrage
                            // .. kann natürlich öfter ver&&det werden
    Und ich kann über Fehlfunktionen wirklich nicht klagen *gg* .. dh es treten keine auf.
    Ciao sagt der JoeamBerg

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Ich verwende diese Miniaturtaster (nicht diese gewölbten Bleche ("Knackfrösche") direkt auf der Leiterplatte) auch, aber stets mit Unbehagen.
    Über das Prellverhalten habe ich noch keine Untersuchungen angstellt, aber ich bemerke häufig, dass diese Teile unter meinen Fingern trotz 1x knack-rein und 1x knack-raus gar keinen oder auch mehrere Schließereignisse produzieren.

  4. #4
    Erfahrener Benutzer Roboter-Spezialist Avatar von witkatz
    Registriert seit
    24.05.2006
    Ort
    NRW
    Alter
    54
    Beiträge
    542
    Blog-Einträge
    17
    Zitat Zitat von registriert Beitrag anzeigen
    Aber meiner Meinung sind die C- und die Assembler-Version absolut gleichwertig.
    Auch wenn du guten C-Code geschrieben hättest, sind C und Assemblerroutinen bestimmt nicht gleichwertig. Der Maschinencode, den der Compiler aus der C-Routine gemacht hat ist sicherlich länger und dauert in der Ausführung auch länger als der Assembler-Code.
    Außerdem hast du im Assembler ein 8-bit Register verwendet, in C aber uint16_t. Weißt du was der Compiler aus 16-Bit Zuweisungen, Arithmetik- und Vergleichsoperatoren für einen unnötigen Maschinencode - Overhead erzeugt und was das für die Ausführungszeit bedeutet? Vielleicht liegt in der Ausführungszeit der Routine, die im Interrupt aufgerufen wird die Ursache des Problems?

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    25.08.2014
    Beiträge
    7
    Ein (spätes) Danke für die ersten Beiträge.


    Zitat Zitat von witkatz Beitrag anzeigen
    Der Maschinencode, den der Compiler aus der C-Routine gemacht hat ist sicherlich länger und dauert in der Ausführung auch länger als der Assembler-Code.
    Außerdem hast du im Assembler ein 8-bit Register verwendet, in C aber uint16_t. Weißt du was der Compiler aus 16-Bit Zuweisungen, Arithmetik- und Vergleichsoperatoren für einen unnötigen Maschinencode - Overhead erzeugt und was das für die Ausführungszeit bedeutet? Vielleicht liegt in der Ausführungszeit der Routine, die im Interrupt aufgerufen wird die Ursache des Problems?

    Das sind natürlich gute Punkte. Die Zählvariable war zuerst eine 8-Bit-Zahl. Ich hab dann eine 16-Bit-Zahl draus gemacht, um die Entprellzeit verlängern zu können. Aber in beiden Fällen macht mein Schalter das gleiche.

    Und wenn die Ausführungszeit der C-Variante deutlich länger ist: Sollte das dem Entprellen nicht zu gute kommen? Das ist ja hier keine zeitkritische Anwendung, kann meinetwegen auch ne halbe Sekunde dauern

  6. #6
    Erfahrener Benutzer Roboter-Spezialist Avatar von witkatz
    Registriert seit
    24.05.2006
    Ort
    NRW
    Alter
    54
    Beiträge
    542
    Blog-Einträge
    17
    Zitat Zitat von registriert Beitrag anzeigen
    Das ist ja hier keine zeitkritische Anwendung, kann meinetwegen auch ne halbe Sekunde dauern
    Da wäre ich mir eben nicht sicher. Die Entprellfunktion wird in dem C-Projekt in einer Interrupt-Routine aufgerufen, wenn ich das richtig deute. Interrupt-Routinen sollten immer zeitkritisch betrachtet werden, v.a. wenn die MCU gleichzeitig noch andere Interrupts wie z.B. die Timer-Interrupts noch bedienen soll.

Ähnliche Themen

  1. Atmega48 läuft auf eigener Platine nicht wie er soll!?
    Von DanielSan im Forum AVR Hardwarethemen
    Antworten: 19
    Letzter Beitrag: 09.08.2011, 18:54
  2. [läuft+Code] Servotest an ATtiny13 läuft nicht
    Von oberallgeier im Forum Motoren
    Antworten: 4
    Letzter Beitrag: 18.10.2007, 17:49
  3. Antworten: 3
    Letzter Beitrag: 15.08.2005, 17:41
  4. For-Next-Schleife läuft nicht so wie gewollt :(
    Von jagdfalke im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 24
    Letzter Beitrag: 04.07.2005, 17:20
  5. Hilfe!!! Mein Programm läuft nicht so wie ich will
    Von MrQu im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 7
    Letzter Beitrag: 25.10.2004, 00:28

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests