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.
Falls Bugs auftauchen, nur her damit... ich kümmer mich drum... ;-)
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... ;-)