Bascom Entprellen mit Pinchg-Int. Schnell, kurz, zuverlässig...

Mikel

Neues Mitglied
22. Jan. 2013
2
0
0
Sprachen
Moin,moin...

Hab die Entprell- und Entstör-Routinen nochmal überarbeitet. Es wird jetzt durch nochmalige Abfrage des Pinchg-Int-Bits
(PCIF alias GIFR.5) am Anfang der Timer-Isr gesichert, daß die gecapturten PINB-Bits über mindestens ein komplettes Timerintervall unverändert statisch waren. Falls während der Initialisierung der Timer-Isr ein PCHg-Ereignis dazwischenfunken sollte, wird der anstehende Update-Zyklus verworfen und der Prozess der Pchg_isr zur erneuten Auswertung überlassen.

Somit ist jetzt eine lückenlose Überwachung der Bit-Zustände auch bis nach der Initialisierung der Timer-Isr gegeben. Das wurde zusätzlich nötig, nachdem ich den Pchg_int auf ein einmaliges Auslösen pro Bit und Timer-Intervall begrenzt hatte.


Habe zwei Versionen der Timer_Isr, die sich in der Funktionsweise ünterscheiden:

Die erste, simplere Version, aktualisiert entweder das gesamte Byte, falls im vorherigen Timerintervall kein Pinchg. auftrat. Andernfalls werden die im vorigen Intervall unruhigen Bits beim Transfer ausmaskiert.

Die zweite Version (ganz unten) geht den umgekehrten Weg. Es werden nur jene Bits verfolgt, die im vorherigen Intervall unruhig waren und erst dann explizit zum Aktualisieren des Ausgangsbytes maskiert, wenn sie nach dem unruhigen, ein komplett ruhiges Intervall hinter sich haben.

Code:
'********************************************************
'********************************************************

$regfile = "attiny85.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 40
$framesize = 40

Clkpr = 128
Clkpr = 0

Dim Last_pins_state As Byte
Dim Capt_pins As Byte
Dim Changed_pins As Byte
Dim Changed_pins_sum As Byte
Dim Chps_old As Byte
Dim Chps_old_inv As Byte
Dim Stable_pins As Byte
Dim Deb_pinb As Byte
Dim Pcmsk_set As Byte

Dim W As Long
Dim Softcounter As Byte
Dim Flags As Byte

Set Gimsk.5                                                 'Pchg_int
Pcmsk_set = &B01000
Pcmsk = Pcmsk_set

On Pcint0 Pchg_isr
On Wdt Wd_isr
'Watchdogtimer im Int-Modus starten:
Wdtcr = &B01000000

Enable Interrupts

Ddrb = &B00011
Portb = &B11100
Last_pins_state = Pinb


'************************************************
'Loop für Ein- und Ausgabe
'Hat nichts mit dem Debouncing zu tun,
'generiert nur den Testablauf:

'An PinB.3 (Pullup on) hängt der Eingabe-Taster gegen Gnd.
'An PortB.1 hängt die LED1 über 330Ohm gegen Gnd.
'Solange diese leuchtet, kann über den Taster eine Impulsfolge
'reingehackt werden. Wenn die LED1 erlöscht werden keine weiteren
'Impulse angenommen und die Ausgabe der gezählten Impulse über LED2
' beginnt. LED2 hängt über 330Ohm an PortB.0 ebenfalls gegen Gnd....
'Im Byte Deb_pinb werden parallel die entprellten Eingangszustände
'von PinB abgelegt. Über das Maskenregister PCMSK_copy werden jene Eingänge
'von PinB ausgewählt, die entprellt werden sollen.

'Bei Bedarf können über eine weitere AND-Maske im Pchg_int jene
'Eingänge, die nicht entprellt werden sollen, auf eine andere
'Routine umgelenkt werden.


Do

 Softcounter = 0

 Portb.1 = 1
 For W = 0 To 500000
  If Deb_pinb.3 = 0 Then
    If Flags.0 = 1 Then Incr Softcounter
    Reset Flags.0
  Else
     Set Flags.0
  End If
 Next W

 Portb.1 = 0
 Waitms 1000

While Softcounter > 0
  Portb.0 = 1
 Waitms 200
  Portb.0 = 0
 Waitms 250
 Decr Softcounter
Wend
 Waitms 500

Loop


'*************************************************
'*************************************************
'Der folgendende, kurze Code generiert mittels Bitmanipulation
'in den ISRs die gesamte, schnelle und zuverlässige Entprellung
'simultan und parallel auf Bytebreite.! Er ist gleichermassen
'für Low- und High-aktive Taster geeignet.
'Durch den Pinchg-Int werden (im Gegensatz zum Polling-Verfahren)
'alle Störimpulse erfasst und eliminiert, die im Bereich der jeweiligen
'Systemtaktauflösung möglich sind.
'Dennoch wird auch bei stark prellenden Tastern pro Timerintervall
'nur EIN EINZIGER Pinchange-Int ausgelöst!

'Statt des Watchdog-Timer-Int kann natürlich ggf. auch ein schon 
'vorhandener anderer Timer_int im Bereich weniger zig Millisekunden 
'genutzt werden.

'******************                                       ;
 Pchg_isr:

  Changed_pins = Last_pins_state Xor Pinb
  Last_pins_state = Pinb
  Changed_pins_sum = Changed_pins_sum Or Changed_pins
  Stable_pins = Not Changed_pins_sum
  Pcmsk = Pcmsk And Stable_pins

 Return

 '*****************

  Wd_isr:

       Capt_pins = Pinb
       Pcmsk = Pcmsk_set

    If GIFR.5 = 0 Then
       Last_pins_state = Capt_pins

      If Changed_pins_sum = 0 Then
       Deb_pinb = Last_pins_state
      Else
       Deb_pinb = Deb_pinb And Changed_pins_sum
       Stable_pins = Stable_pins And Last_pins_state
       Deb_pinb = Deb_pinb Or Stable_pins
      End If

    End If
     Changed_pins_sum = 0

  Return


'**************************************************
'**************************************************

Die zweite Version der Timer-Isr:

'*****************

  Wd_isr:

   Capt_pins = Pinb
   Pcmsk = Pcmsk_set

   If GIFR.5 = 0 Then
     Last_pins_state = Capt_pins

     Chps_old = Chps_old Or Changed_pins_sum
     Chps_old = Chps_old Xor Changed_pins_sum

     If Chps_old = 0 Then Goto Upd

     Chps_old_inv = Not Chps_old
     Deb_pinb = Deb_pinb And Chps_old_inv

     Last_pins_state = Last_pins_state And Chps_old
     Deb_pinb = Deb_pinb Or Last_pins_state
   End If

   Upd:
     Chps_old = Changed_pins_sum
     Changed_pins_sum = 0

  Return

  '*********************

Falls Bugs auftauchen, nur her damit... ich kümmer mich drum... ;-)
 
Hi,

Code:
'*************************************************
'*************************************************
'Der folgendende, kurze Code generiert mittels Bitmanipulation
'in den ISRs die gesamte, schnelle und zuverlässige Entprellung
'simultan und parallel auf Bytebreite.! Er ist gleichermassen
'für Low- und High-aktive Taster geeignet.
'Durch den Pinchg-Int werden (im Gegensatz zum Polling-Verfahren)
'alle Störimpulse erfasst und eliminiert, die im Bereich der jeweiligen
'Systemtaktauflösung möglich sind.
'Dennoch wird auch bei stark prellenden Tastern pro Timerintervall
'nur EIN EINZIGER Pinchange-Int ausgelöst!

'Statt des Watchdog-Timer-Int kann natürlich ggf. auch ein schon 
'vorhandener anderer Timer_int im Bereich weniger zig Millisekunden 
'genutzt werden.

'******************                                       ;
 Pchg_isr:

[B]  Changed_pins = Last_pins_state Xor Pinb
  Last_pins_state = Pinb[/B]
  Changed_pins_sum = Changed_pins_sum Or Changed_pins
  Stable_pins = Not Changed_pins_sum
  Pcmsk = Pcmsk And Stable_pins

 Return
Falls Bugs auftauchen, nur her damit... ich kümmer mich drum... ;-)

Dann zu den Bugs ... Die beiden fett gedruckten Zeilen ... sowas nennt man Race Condition :p
Zwischen den beiden Zeilen kann sich der Zustand von Pinb ändern und man hat bei jeder Abfrage ein anderes Ergebnis.
Richtig wäre es so ...
Code:
  [B]Pinb_temp = Pinb[/B]
  Changed_pins = Last_pins_state Xor [B]Pinb_temp[/B]
  Last_pins_state = [B]Pinb_temp[/B][/B]
Wobei der Atmel sehr schnell ist. Es könnte also sein das er die beiden Ereignisse "PinChangeInt" und "Abfrage PinB" innerhalb eines Prellimpulses schafft.

Gruß
Dino
 
Hi Dino,

ja hast recht, man muß konsequenter Weise bei einem Snapshot bleiben, in solche Fällen... thx..
Präzision ist bei Nutzung des Pchg-Int ja möglich, im Unterschied zu dem eher zufälligen 'stochern' beim Polling.

Das Polling kann durchaus z.B. 4 mal hintereinander Low pollen und zu dem irrtümlichen Schluss gelangen, daß der Eingang stabil ist.
Aber die 4 Lows können zufällig gepollte Lows aus einer Störimpulsserie sein.

Polling ist in seiner Funktion als digitaler Lowpass bzw. Störfilter nicht sicher. Bei einem mit 1MHz ins PIN gelatchten Signal kann der Pegel zwischen den z.B. 10ms Pollingstichproben, theoretisch 10.000mal wechseln. Das Polling wäre in solch einem Fall nur ein Zufallsgenerator, der mit einer Wahrscheinlichkeit von 1:16 hintereinander 4 gleiche Pegel erwischen kann und daraus irrtümlich einen für 40ms statischen Eingang interpretiert.. Je nach Frequenzverhältnis von Pollingfrequenz und Störfrequenz, können auch langsame Schwebungsphasen entstehen, die bei entsprechender, relativer Phasenlage, lange Serien von x-fach-Zufallstreffern mit gleichem Pegel erzeugen.

Diese Überlegung war es auch, die mich veranlasste ein sicheres Procedere mit reproduzierbar eindeutigem Verhalten zu finden. Mit dem Pchg_Int wird hardwaremässig jeder(!) Flankenwechsel erkannt und kann entsprechend sichere Maßnahmen einleiten...

Das größte Manko dabei war die Tatsache, daß bei vielfachem Prellen, eine ganze Serie von Interrupts, samt Push/Pull-Overhead, anfallen.
Deswegen war ja 'Taster und Pchg-Int' gewissermassen ein Tabu beim Debouncing.
Das habe ich nun dadurch in den Griff bekommen, daß der erste Flankenwechsel eines bestimmten Pins gespeichert und die nachfolgenden für das laufende Intervall ausmaskiert werden.
Die logischen Bitoperationen sind kurz, schnell und sicher und bewerkstelligen die bedingte und selektive Maskierung von Quell- und Zielbits, und ggf. deren Aktualisierung simultan auf der gesamten Portbreite.

Gruß Mikel
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)