komme nicht zurecht !Debounce

Neuuser

Mitglied
11. Aug. 2008
465
0
16
Sprachen
Hallo Leute,
ich versuche die tasten einer softclock mit Debounce zu entprellten und komme einfach nicht so richtig da hinter.
wen ich die Uhr stellen will springt die gleich um 2-5 stellen weiter.:eek:
verwende ich da die verkehrten Mittel oder ist alles nur nicht am richtigen Ort, kann jemand helfen ?

Gruß Neuuser


Code:
Declare Sub Schalter1
Declare Sub Schalter2

Portd.0 = 1                                                 'Taster1, Zeit/Datum stellen, PullUp ein, schaltet gegen Minus
Portd.3 = 1                                                 'Taster2,  Zahl hochzählen, PullUp ein, schaltet gegen Minus


Time$ = "00:00:00"                                          'Setzen auf Startwert
Date$ = "00/00/00"                                          'Setzen auf Startwert

Do
Debounce Pind.0 , 0 , Schalter1 , Sub
Debounce Pind.3 , 0 , Schalter2 , Sub

   Locate 1 , 1
   Lcd Time$                                                'Zeige Zeit in Zeile1
   Locate 2 , 1
   Lcd _day ; "/" ; _month ; "/0" ; _year                   'Zeige Datum in Form DD/MM/YYin Zeile2
'lcd Date$                                                     'zeige Datum in Form MM/DD/YY

   If Pind.0 = 0 Then Gosub Time                            'wiederhole Anzeige bis Taster 1 zum Stellen gedrückt, springe nach Sub "Time"
Loop
End


'Stunde

Time:
Waitms 200
Cls                                                         'lösche Zeilen
Do

Toggle Portd.3
Locate 1 , 1
Lcd "Set Hour:"                                             'Stunden setzen
Locate 2 , 1
Lcd _hour
Sub Schalter2 : If Pind.3 = 0 Then                          'Mit Taster 2
End Sub
Incr _hour                                       'hochzählen
           Locate 2 , 1
           Lcd _hour
         End If
If _hour > 23 Then                                          'Zählt bis Max, danach wieder ab 0
Cls
_hour = 00
End If
                                              'solange, bis Taster 1 gedrückt
Sub Schalter1 : Loop Until Pind.0 = 0
Waitms 200
Cls
End Sub
 
Hallo Neuuser,

sei mir bitte nicht böse aber irgendwie komme ich mit Deinem Code überhaupt nicht zurecht. Da herrscht ja Kraut & Rüben!

Time:
Waitms 200
Cls 'lösche Zeilen
Do
Toggle Portd.3
Locate 1 , 1
Lcd "Set Hour:" 'Stunden setzen
Locate 2 , 1
Lcd _hour

Frage: Wo bitte ist die zugehörige LOOP zum DO und wo bitte ist das RETURN zur Routine TIME:?
Warum toggelst Du Portd.3 wenn Du Debounce verwendest? Warum greifst Du überhaupt noch manuell auf die Schalter zu?

Sub Schalter2 : If Pind.3 = 0 Then 'Mit Taster 2
End Sub
Incr _hour 'hochzählen
Locate 2 , 1
Lcd _hour
End If
If _hour > 23 Then 'Zählt bis Max, danach wieder ab 0
Cls
_hour = 00
End If

Warum springst Du bei Pind.3 = 0 direkt aus der Subroutine?


Entweder Dir ist beim Kopieren ein Fehler unterlaufen oder hier herrschr wirklich Kraut und Rüben. Schau Dir doch Dein Programm nochmals genauer an, was Du hier treibst.

Ganz im Regen will ich Dich nicht stehen lassen aus diesem grund ein paar Kommentare von mir zur Hilfe:

[1] Thema DEBOUNCE
Üblichweise bruachst Du, wenn Du debounce verwendest keine weiteren Pinabfrage, Entprellungenusw. da debounce das alles für Dich erledigt.
Mit debounce kannst Du einen Schalter an einem bestimmten PIN abfragen. Beim debounce-Statement kannst Du angeben:
- an welchem PIN der Schalter hängt
- bei welchem Zustand (0 oder 1) des Pins zum Label gesprungen werden soll
- und ob der Label ein GOTO-Sprung oder eine Subroutine ist.

ACHTUNG: Subroutine in diesem Fall bezieht sich nicht auf SUB oder Funktion sondern auf eine GOSUB-Funktion die folgender Maßen definiert werden muss:

Code:
Funktion:
   ' mache dies
   ' mache das
Return

JEDE GOSUB-FUNKTION BENÖTIGT EIN RETURN!!!!!
Generell: Jede SUB benötigt ein "End SUB" und jede Fuktion ein "End function"!!!

Wenn Du ein Label mit SUB beim debounce angegeben hast so sprint debounce als GOSUB beim Eintreffen eines Ereignis zur jeweiligen Routine und kehrt nach RETURN dann an die Stelle wieder zurück.
Das ist notwendig damit Du normal im Hauptprogramm weiterarbeiten kannst.

Debounce überprüft Deine definierten Bedingungen an dem jeweiligen PIN, wartet 25 ms (da musst Du Dich nicht darum kümmern), prüft die Bedingung nochmals und springt dann erst Deine Routine an. Dieser Mechanismus dient zur Entprellung der Schalter.

Wird die angegebene Schalter-Bedingung nciht erfüllt (Schalter z.B. nicht gedrückt) dann macht BASCOm in der nächsten Zeile Deines Codes weiter.

Wenn BASCOM über das debounce Deine Unterfunktion angesprungen und bearbeitet hat und zurück kehrt, dann muss der Schalter-Pin erst wieder auf den anderen Zustand wechseln damit debounce wieder asugeführt werden kann.
Bedeutet: Im Leerlauf ist Pin = 0, du drückst den Schalter, Pin wird 1 und debounce springt auf Funktion. Dann muss Pin wieder 0 werden damit debnounce beim nächsten Mal bei Pin=1 wieder springt.
Auf diese Weise wird das dauerhafte drücken einer Taste verhindert. Bedeutet, drückst Du die Taste und hältst sie gedrückt wird nicht ständig in die Unterfunktion gesprungen. Sondern erst wieder wenn Du die Taste zwischendurch wieder losgelassen und neu gedrückt hast. Verstanden.

Debounce wartet auch nicht auf ein Eingabe. Wenn Du auf eine Eingabe warten musst so empfehle ich hier den BITWAIT zu verwenden.

Soviel zum Debounce. Ich hoffe es ist Dir nun klarer. Nun zurück zum Spaghetti-Code (sorry für den Ausdruck).

Also:
- Vollständig ist er ja auf keinem Fall den mir fehlen die kompletten Compiler-Directiven und die Konfiguration der SoftClock.
- Ich erwarte, dass das Einstellen Deiner Uhr über die zwei Tasten etwas aufwändiger wird als Du Dir das vielleicht gedacht hat. Du musst Dir quasi ein kleines Menü schreiben mit dem Du über Schalter 1 bestimmen kannst, ob Du nix oder Minute, oder Tage usw. einstellen kannst. Und wenn eine solche Auswahl aktiv ist, dass Du über Schalter 2 dann die Variable hochzählen kannst. Ist nicht ganz einfach aber über einige Hilfskonstrukte machbar. Schaus Dir an und wenn Du gezielte Fragen hast dann schieß los.

Grüße,
Markus
 
Hallo Neuuser,
sei mir bitte nicht böse aber irgendwie komme ich mit Deinem Code überhaupt nicht zurecht. Da herrscht ja Kraut & Rüben!


Hallo Markus !

Puh, da bin ich aber erleichtert!!!

Ich hatte den Beitrag gestern Abend schon gesehen und bin da absolut nicht durchgestiegen..... :hmmmm:

Nun bin ich aber erleichtert, dass es nicht nur mir so ging..... sondern auch dem Profi. ;)

Also bin ich auf dem richtigen Weg....... :D

Grüße,
Cassio !
 
Auch Hallo !

Ich hatte den Beitrag gestern Abend schon gesehen und bin da absolut nicht durchgestiegen..... :hmmmm:

Nun bin ich aber erleichtert, dass es nicht nur mir so ging..... sondern auch dem Profi. ;)

Ich möchte hier keinem auf den Schlips treten ;) aber es sieht wirklich etwas
unstrukturiert aus. Da muß man noch etwas lesbarkeit reinbringen. Bei Basic
sollte das mit Einzügen (TABs sind da immer gerne gesehen oder 2 Spaces)
eigentlich recht gut gehen.

Für nen Quick-And-Very-Dirty-Test :D reicht so ein Code. Aber nach spätestens
ner Woche steigt da keiner mehr durch.

Ich hab mir schon seit langer Zeit angewöhnt, ne Menge Kommentare reinzuschreiben.
Mein Code besteht zu ungefähr 2/3 aus Kommentaren und 1/3 aus Befehlen. Hat
sich über die Jahre bewährt.

Sieht dann ungefähr so aus ...
Code:
; ##################################################################
; ##################################################################
; #### USART-Subroutinen ###########################################
; ##################################################################
; ##################################################################
 
; ==================================================================
; ===== USART initialisieren (9k6 8n1) =============================
; ==================================================================
usartinit:
	push r16			; r16 auf Stack retten (fuer wiederherstellung)
;
; ===== BAUDRATE fuer USART =====
;
; U2X=0  Baud = fosc / 16(UBBR+1)  ,  UBBR = ( fosc / 16Baud )-1
; U2X=1  Baud = fosc / 8(UBBR+1)   ,  UBBR = ( fosc / 8Baud )-1
; Baud = bps , fosc = SystemClock , UBBR = UBBRH+UBBRL (0-4095)
;
; 9600 Baud => bei U2X=1 UBBR=155
;
; UBRRL - USART Baud Rate Register Low Byte
; * Bit 0..7 : USART Baud Rate Register bit 0..7
;
; UBRRH - USART Baud Rate Register High Byte
; * Bit 0 : USART Baud Rate Register bit 8
; * Bit 1 : USART Baud Rate Register bit 9
; * Bit 2 : USART Baud Rate Register bit 10
; * Bit 3 : USART Baud Rate Register bit 11
; * Bit 4 : 0
; * Bit 5 : 0
; * Bit 6 : 0
; * Bit 7 : USRSEL (Register Select) 1=UCSRC 0=UBRRH
;
	ldi r16,0			; Baudrate-Register HighByte
	out UBRRH,r16		; Highpart = 0
	ldi r16,155			; Baudrate-Register LowByte
	out UBRRL,r16		; Lowpart = 155
; 
; UCSRA - USART Control and Status Register A
; * Bit 0 : MPCM Multi-processor Communication Mode
; * Bit 1 : U2X  Double the USART transmission speed
; * Bit 2 : UPE  Parity Error
; * Bit 2 : PE = UPE For compatibility
; * Bit 3 : DOR  Data overRun
; * Bit 4 : FE   Framing Error
; * Bit 5 : UDRE USART Data Register Empty
; * Bit 6 : TXC  USART Transmitt Complete
; * Bit 7 : RXC  USART Receive Complete
;			  76543210
	ldi r16,0b00000010	; U2X=1
	out UCSRA,r16		; 
;
; URSEL UMSEL UPM1 UPM0 USBS UCSZ1 UCSZ0 UCPOL
;   7     6    5    4    3     2     1     0   UCSRC
;
; UCSRC - USART Control and Status Register C
; * Bit 0 : UCPOL Clock Polarity
; * Bit 1 : UCSZ0 Character Size Bit 0
; * Bit 2 : UCSZ1 Character Size Bit 1
; * Bit 3 : USBS  Stop Bit Select    0 = 1Stop-Bit , 1 = 2 Stop-Bits
; * Bit 4 : UPM0  Parity Mode Bit 0
; * Bit 5 : UPM1  Parity Mode Bit 1
; * Bit 6 : UMSEL USART Mode Select Async=0 Sync=1
; * Bit 7 : URSEL Register Select
;
; UPM 00 Disabled		UCSZ 000 5-Bit , 100 Reserved
;     01 Reserved		     001 6-Bit , 101 Reserved
;     10 Even Parity	     010 7-Bit , 110 Reserved
;     11 Odd Parity		     011 8-Bit , 111 9-Bit
;
; SyncMode	TxD Changed		RxD Sampled
; UCPOL 0	Rising XCK Edge	Falling XCK Edge
;       1	Falling XCK Edge	Rising XCK Edge
;			  76543210
	ldi r16,0b10000110	; URSEL=1 (UCSRC) , USBS=0 UCSZ=3 => Frame-Format 8Bit/1Stop
	out UCSRC,r16		; 
;
; UCSRB - USART Control and Status Register B
; * Bit 0 : TXB8  Transmit Data Bit 8
; * Bit 1 : RXB8  Receive Data Bit 8
; * Bit 2 : UCSZ2 Character Size Bit 2
; * Bit 2 : CHR9 = UCSZ2 For compatibility
; * Bit 3 : TXEN  Transmitter Enable
; * Bit 4 : RXEN  Receiver Enable
; * Bit 5 : UDRIE USART Data register Empty Interrupt Enable
; * Bit 6 : TXCIE TX Complete Interrupt Enable
; * Bit 7 : RXCIE RX Complete Interrupt Enable
;			  76543210
	ldi r16,0b00011000	; UCSZ2=0 (8Bit) , TXEN + RXEN => Enable Receiver/Transmitter
	out UCSRB,r16		; 

	pop r16				; r16 wiederherstellen
	ret					; Subroutine Ende

 
; ==================================================================
; ===== USART - Daten senden =======================================
; ==================================================================
usartwr:				; Wait for empty transmit buffer (ca 1ms bei 9k6/8n1)
	sbis UCSRA,5		; Skip if Bit 5 is Set : UDRE USART Data Register Empty
	rjmp usartwr		; Sende-Buffer noch nicht leer
	out UDR,r16		; Put data (r16) into buffer, sends the data
	ret				; Subroutine Ende


; ==================================================================
; ===== USART - Daten empfangen ====================================
; ==================================================================
usartrd:				; Wait for data to be received (ca 1ms bei 9k6/8n1)
	sbis UCSRA,7		; Skip if Bit 7 is Set : RXC  USART Receive Complete
	rjmp usartrd		; Noch nichts empfangen
	in r16, UDR		; Get and return received data from buffer
	ret				; Subroutine Ende


; ==================================================================
; ===== USART - Daten senden/empfangen (Echo) ======================
; ==================================================================
usartecho:				; Wait for data to be received (ca 1ms bei 9k6/8n1)
	ldi r16,0x00		; 0x00 als Leermeldung laden (nix empfangen)
	sbis UCSRA,7		; Skip if Bit 7 is Set : RXC  USART Receive Complete
	rjmp usartechoend	; Noch nichts empfangen
	in r16, UDR		; Get and return received data from buffer
usartechowr:
	sbis UCSRA,5		; Skip if Bit 5 is Set : UDRE USART Data Register Empty
	rjmp usartechowr	; Sende-Buffer noch nicht leer
	out UDR,r16		; Put data (r16) into buffer, sends the data
usartechoend:
	ret				; Subroutine Ende
Die Tabs sind jetzt gegenüber dem AVR-Studio etwas verhunzelt aber im Großen
und Ganzen bin ich mit meinem Code recht zufrieden :D

Und so kann man das auch bei BASCOM, C, Perl, PHP, ... machen. Nur das bei
"Hochsprachen" die Schleifen-/Funktions-/...-Innereien auch zur besseren
Lesbarkeit noch 2 Leerzeichen oder 1 Tab eingerückt werden können.

Diese Vorgehensweise würde ich allen "Programmier-Anfängern" ans Herz legen :flirt:

Gruß
Dino
 
Hallo Dino,

danke für Deinen Beitrag. Ich glaube das sind wir uns einig :kiss3:

Auch mit BASCOM kann man sehr sauber strukturiereten Code schreiben.
Wen's interessiert der soll sich mal meine BASCOm Beispiele und Teilprojekte und Threads hier im Forum ansehen.

Grüße,
Markus
 
Hallo Markus!

Wen's interessiert der soll sich mal meine BASCOm Beispiele und Teilprojekte und Threads hier im Forum ansehen.

Sieht recht strukturiert aus :D kann man so sehen :dirol:
(Ich hab mir mal das SHT71 angesehen)

Ich pack in meinen Quellcode am Anfang immer noch die Fuse-Map vom PonyProg
und das Pinout des uC mit der Verwendung der einzelnen Pins rein. Dazu kommt dann
noch ne Kurzbeschreibung wofür das getippe eigentlich sein sollte.
(OK bei dem Beispiel ist jetzt keine Fuse-Map dabei - war das erste Projekt)

Code:
; ############################################
; ############################################
; ##### RGBW-Dimmer fuer denn Magierstab #####
; ############################################
; ############################################
;
; (c) 19. Mai 2008 
;
; Dies ist ein Dimmer-Programm fuer einen Magierstab. Es werden 5 Luxeon K2-Emitter
; fuer die Beleuchtung einer Bergkristall-Kugel verwendet. Rot, Gruen, Weiss und
; 2x Blau. Die weisse LED wird bei der Betaetigung aller 3 Taster zugeschaltet (Boost)
; Die Helligkeiten der LEDs koennen bei Mischfarben ueber eine Farbmisch-Tabelle 
; angepasst werden, um z.B. ein sauberes violett oder gelb zu erreichen.
;
; ATMEL AVR AT90S2313
; 2kByte Flash
; 128Byte EEPROM
; 32 Register + 128Byte RAM
; 
; Es wird ohne Stack (Subroutinen) gearbeitet. Es wird aber der LPM-Befehl benoetigt.
; Ohne Farbmischtabelle koennte man auch den kleineren AT90S1200 benutzen (pinkompatibel).
; Wegen dem LPM-Befehl muss aber auf den etwas groesseren AT90S2313 zurueckgegriffen
; werden.
;
;                        AT90S2313
;                   +-----------------+
;           RESET --| 1 Reset   VCC 20|-- +Vcc
;    Taster Rot <---| 2 PD0     PB7 19|-- SCK
;  Taster Gruen <---| 3 PD1     PB6 18|-- MISO
;            Quarz--| 4 XTAL2   PB5 17|-- MOSI
;            Quarz--| 5 XTAL1   PB4 16|---> Takt Spannungsverdoppler
;   Taster Blau <---| 6 PD2     PB3 15|---> MOSFET Weiss
;  Betriebs-LED <---| 7 PD3     PB2 14|---> MOSFET Blau
;                   | 8 PD4     PB1 13|---> MOSFET Gruen
;                   | 9 PD5     PB0 12|---> MOSFET Rot
;             GND --|10 GND     PD6 11|
;                   +-----------------+
;
;	r16 Eingangsregister Tasten
;	r17 Entprellte Tasten
;	r18 Ausgangsregister
;
;	r1  Entprell-Register Rot
;	r2  Entprell-Register Gruen
;	r3  Entprell-Register Blau
;
;	r4  Dimmer Rot
;	r5  Dimmer Gruen
;	r6  Dimmer Blau
;	r7  Dimmer Weiss
;
;	r21 Dimm-Maxwert Rot
;	r22 Dimm-Maxwert Gruen
;	r23 Dimm-Maxwert Blau
;
;	r0  LPM-Datenregister
;
;	r24 Rampenzaehler fuer PWM
;
;	r28 Pausenzaehler Low (Bit7 = Spannungsverdoppler-Takt)
;	r29 Pausenzaehler High
;
;	r30 Pointer auf Farbmischtabelle - Low
;	r31 Pointer auf Farbmischtabelle - High
;
;	r19 Arbeitsregister 1
;	r20 Arbeitsregister 2
;
; Der folgende Plan ist von der ersten Version ohne die Farbmischtabelle.
;
;     bl  gn  rt
;     PD2 PD1 PD0     Taster nach +Vss (gedrueckt = 1)
;      |   |   |
;      V   V   V
; r16 [2] [1] [0]
;      |   |   |
;      :   :   |
;              V
;             [T]
;              |
;              |
;              V
;           ->[C]-----------------------
;          |                            |
;   Rot r17 -[7][6][5][4][3][2][1][0]<--
;(Gruen r18)  |  |  |  |  |  |  |  |
; (Blau r19)  1  1  1  1  1  1  1  1 (255) -> 1 
;             0  0  0  0  0  0  0  0  (0)  -> 0
;                                             |
;                                     :   :   |
;                                     |   |   V
;                                r20 [2] [1] [0]
;                                     |   |   |
;                                     |   |   |\__ 1|
;                                     |   |\__|___ 1|--> RGB gedrueckt = weiss 
;                                     |\__|___|___ 1|                      |
;                                     |   |   |                            |
;                                     |   |   |                            V
;                                     |   |   |                           inc
;                                     |   |   |                           dec
;  r27 Verzoegerungszaehler Low       |   |   |                            |
;  r28 Verzoegerungszaehler High      |   |   |                            |
;                                     |   |   |                            V
;                                     :   :   |                           r25 Weiss
;                                             V
;                                            [T] -> 1 => inc (wenn <> 255)
;                                             '---> 0 => dec (wenn <> 0)
;                                                         |             
;             /|/|/| Rampenzaehler r21                    |             
;             0,1,..,254,255,0,1,.. |                     V               
;                                    ------  <  ---------r22 Rot (r23 Gruen , r24 Blau)
;                                            |
;                                :   :   :   |  >r21 = 1 , <r21 = 0 ==> PWM
;                                |   |   |   V
;                       r26 [4] [3] [2] [1] [0]
;                            |   |   |   |   |
;                            V   V   V   V   V
;Takt Spannungsverdoppler<--PB4 PB3 PB2 PB1 PB0   zu den MOSFET-Treibern
;                            |  ws  bl  gn  rt
;                            -               |              |\     | |----- Led --- +Vss
;                         C1 =                --------------| >----| 
;                            |                              |/|    | |---
;                  +Vss-->|--+-->|--+--o 2xVss ---------------           |
;                        D1     D2  |                    Treiber  MOSFET |
;                                   = C2                                GND
;                                   -      Spannungsverdoppler fuer hoehere Gate-Spannung
;                                   |      fuer die MOSFETs, damit staerker durchgesteuert
;                                  GND     wird (kleinerer Innenwiderstand). Die benoetigen
;                                          mindestens 6-7V zum sauberen durchschalten. Mehr
;                                          ist besser. Strom wird nicht so viel benoetigt.
;

.include "2313def.inc"		;Definitionsdatei laden
.cseg						;Beginn eines Code-Segmentes
.org 0						;Startadresse=0
;
;
.def rt_prm = r1			;Entprell-Register Rot - Memory
.def gn_prm = r2			;Entprell-Register Gruen - Memory
.def bl_prm = r3			;Entprell-Register Blau - Memory

.def rt_dim = r4			;Dimm-Wert Rot - Memory
.def gn_dim = r5			;Dimm-Wert Gruen - Memory
.def bl_dim = r6			;Dimm-Wert Blau - Memory
.def ws_dim = r7			;Dimm-Wert Weiss - Memory

.def rt_mx = r21			;Dimm-Maximalwert Rot
.def gn_mx = r22			;Dimm-Maximalwert Gruen
.def bl_mx = r23			;Dimm-Maximalwert Blau

.def lpmreg = r0			;LPM-Datenregister

.def ramp  = r24			;Rampenzaehler fuer PWM
.def cntlo = r28			;Pausenzaehler
.def cnthi = r29			;Schleifendurchlaeufe

.def tst_in = r16			;Eingangsregister mit Tastendruecken
.def tst_pr = r17			;Entprellte Tastendruecke
.def outdrv = r18			;Ausgangstreiber-Register

.def areg1 = r19			;Arbeitsregister 1
.def areg2 = r20			;Arbeitsregister 2

.def zhi = r31				;Pointer High (fuer LPM)
.def zlo = r30				;Pointer Low (fuer LPM)

Damit weiß man immer, wie die umliegende Hardware an den Halbleiterbrocken
angeschlossen werden muß ;)

Und hier mal ne Fuse-Map

Code:
;
; ========== ATmega8 ==========
;
; * SUT1 und SUT0 (Zustand=11): Start-up Time 65ms nach Reset,
;   Einstellung fuer Quarzoszillator und langsam ansteigende 
;   Betriebsspannung (Tabelle 5 des Datenblattes)
; * CKSEL3-CKSEL0 (Zustand=1111): Quarzoszillator im Bereich 3-8MHz 
;   (Tabelle 4 des Datenblattes)
; * CKOPT (Zustand=1): schneller Quarzoszillator (Tabelle 4 des Datenblattes)
; * BODEN (Zustand=0): Brown-out einschalten
; * BODLEVEL (Zustand=1): Brown-out Schwelle auf 2,7V setzen
;
;  Unter Beachtung der invertierten Logik der Fuse-Bits sollte man 
;  also die Fuses so setzen wie im folgenden Bild: 
; 
; ( )7 ( )6 [ ]BootLock12 [ ]BootLock11 [ ]BootLock02 [ ]BootLock01 [ ]Lock2 [ ]Lock1
;
; [ ]S8535C [ ]WDTON (X)SPIEN [ ]CKOPT  [ ]EESAVE [X]BOOTSZ1 [X]BOOTSZ0 [ ]BOOTRST
;
; [ ]BODLEVEL [X]BODEN [ ]SUT1 [ ]SUT0 [ ]CKSEL3 [ ]CKSEL2 [ ]CKSEL1 [ ]CKSEL0
;  ______________________
; |                      |
; | [X] Bit=0  [ ] Bit=1 | ( ) -> Nicht anwaehlbar  [ ] -> Anwaehlbar
; | progr.     unprogr.  |
; |______________________|
;
Dann weiß man nachher auch, was man außer dem Hex-File noch in das Teil
packen muß.

Gruß
Dino
 
Hi, zusammen!

Ups, da war Markus wieder schneller.....

Tja, Dino, das kannst du bei BASCOM natürlich auch machen. ;)

Trotzdem machen einige doppelte Abfragen (wie Markus es schon beschrieben hat) keinen Sinn.
Schließlich prüft und "merkt" sich "Debounce", ob sich der angegebene Pin geändert hat.
Dies ist aber nicht nur zum Entprellen von Schaltern interessant.
Wenn ich mich nicht täusche, dann reagiert das Programm auch nicht,
selbst wenn das Programm vom "Return" zurück kommt und durch die "DO-LOOP Schleife" an der selben Stelle ankommt, solange sich der Status des Pins nicht mindestens einmal geändert hat.

Vielleicht sollte Neuuser aber lieber mit dem "BITWAIT" arbeiten.....
Ich ziehe den Befehl zum Entprellen auch immer dem Debounce vor.

Grüße zum Wochenende,
Cassio !
 
Ui Ui , da bekomme ich mal wieder was zu hören von euch, ist ja richtig :( und wollte eigentlich nur den teil ausschnitt hier reinbringen den ich probiert hatte.
Nun habe ich ja schon von Markus einige Fehler erklärt bekommen, ich habe sie aber noch nicht ausprobiert, werde ich nachher gleich testen aber hier noch mal zum ganzem Programm, wo ich bei der Stundeneingabe rum gehackt habe.

Gruß Neuuser

Code:
'Lcd An Portb , Taster Zum Stellen An Pd.0
'zum Hochzählen An Pd.3.
'zwischen XTAL ist ein 32.xxx Uhrenquarz

$regfile = "m8def.dat"
$regfile = 1000000

Config Lcdpin = Pin , Rs = Portb.0 , E = Portb.1 , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , Db7 = Portb.5
Config Lcd = 24 * 2
Initlcd
Cursor Off
Cls

Enable Interrupts

Config Date = Mdy , Separator = /
Config Clock = Soft
Config Portd = Input
Declare Sub Schalter1
Declare Sub Schalter2

Portd.0 = 1                                                 'Taster1, Zeit/Datum stellen, PullUp ein, schaltet gegen Minus
Portd.3 = 1                                                 'Taster2,  Zahl hochzählen, PullUp ein, schaltet gegen Minus


Time$ = "00:00:00"                                          'Setzen auf Startwert
Date$ = "00/00/00"                                          'Setzen auf Startwert

Do

Debounce Pind.0 , 0 , Schalter1 , Sub
Debounce Pind.3 , 0 , Schalter2 , Sub
   Locate 1 , 1
   Lcd Time$                                                'Zeige Zeit in Zeile1
   Locate 2 , 1
   Lcd _day ; "/" ; _month ; "/0" ; _year                   'Zeige Datum in Form DD/MM/YYin Zeile2
'lcd Date$                                                     'zeige Datum in Form MM/DD/YY

'Toggle Portd.0
   If Pind.0 = 0 Then Gosub Time                            'wiederhole Anzeige bis Taster 1 zum Stellen gedrückt, springe nach Sub "Time"

Loop
End


'Stunde


Time:
Waitms 200
Cls                                                         'lösche Zeilen
Do
Locate 1 , 1
Lcd "Set Hour:"                                             'Stunden setzen
Locate 2 , 1
Lcd _hour
Sub Schalter2:
If Pind.3 = 0 Then                                          'Mit Taster 2
End Sub
           Incr _hour                                       'hochzählen
           Locate 2 , 1
           Lcd _hour
         End If
If _hour > 23 Then                                          'Zählt bis Max, danach wieder ab 0
Cls
_hour = 00
'Sub Schalter1:
End If                                                      'solange, bis Taster 1 gedrückt
Loop Until Pind.0 = 0
Waitms 200
'End Sub


'Minute
Cls
Do
Locate 1 , 1
Lcd "Set Minute:"
Locate 2 , 1
Lcd _min
         If Pind.3 = 0 Then
           Incr _min
           Locate 2 , 1
           Lcd _min
         End If
If _min > 59 Then
Cls
_min = 00
End If
Loop Until Pind.0 = 0
Waitms 200
Cls



'Tag
Cls
Do
Locate 1 , 1
Lcd "Set Day :"
Locate 2 , 1
Lcd _day
         If Pind.3 = 0 Then
           Incr _day
           Locate 2 , 1
           Lcd _day
         End If
If _day > 31 Then
Cls
_day = 01
End If
Loop Until Pind.0 = 0
Waitms 200
Cls



'Monat
Cls
Do
Locate 1 , 1
Lcd "Set Month :"
Locate 2 , 1
Lcd _month
         If Pind.3 = 0 Then
           Incr _month
           Locate 2 , 1
           Lcd _month
         End If
If _month > 12 Then
Cls
_month = 01
End If
Loop Until Pind.0 = 0
Waitms 200
Cls



'Jahr
Cls
Do
Locate 1 , 1
Lcd "Set Year :"
Locate 2 , 1
Lcd _year
         If Pind.3 = 0 Then
           Incr _year
           Locate 2 , 1
           Lcd _year
         End If
If _year > 10 Then
Cls
_year = 00
End If
Loop Until Pind.0 = 0
Waitms 200
Cls


_sec = 00                                                   'Springe Nach Setzen Von Zeit / Datum Wieder Zurueck
Return
 
Hallo Neuuser!

Nee, nee, dir wollte bestimmt keiner etwas um die Ohren hauen.....


Ich habe mir eben auf die Schnelle mal deinen Code durchgesehen und frage mich, warum du den Ablauf des Programms nicht "andersherum" machst?

Besser gesagt... Die Uhrzeit und das Datum werden im DO-LOOP solange angezeigt, bis z.B. ein DEBOUNCE es in eine SUB schickt, um dort die Uhr bzw. das Datum zu stellen.

Das wird dann auch wesentlich übersichtlicher.

Obendrein kannst du auch zum Anzeigen der Uhr bzw. des Datums eine eigene SUB schreiben, die vom DO-LOOP jedesmal aufgerufen wird.
Der Vorteil ist, du kannst diese "Anzeige-SUB" dann auch aus den SUB`s für die Einstellungen anspringen und sparst auch noch Code und Speicher dadurch. ;)


Wie aber oben schon erwähnt.... Zum Entprellen der Taster würde ich den BITWAIT nehmen.
Einziger Nachteil ist... du MUSST dann immer die Taste drücken und wieder loslassen. Sprich... zum Einstellen von 59 Minuten dies auch 59 mal machen. ;)
Das ist einer der Gründe, warum ich immer Plus- und Minustasten programmiere. :D


Vielleicht bringen dich meine Zeilen ja auf ein paar neue Ideen.

Gruß,
Cassio !
 
Hi Cassio,
keine schlechte Idee mit der Anordnung der eingaben, aber da brauche ich bestimmt ein bissel, ich brauche dazu immer ein an schau Modell.
hast du ein für BITWAIT, habe ich bisher noch nicht verwendet und finde ich auch nicht in meinen Buch.

Gruß Neuuser
 
Hallo Neuuser!

Ich habe zwar gerade wenig Zeit, möchte dir aber trotzdem schnell ein paar Infos zu BITWAIT geben.

Die Syntax ist:
Bitwait var , Set (bzw. Reset)

Die Variable kann auch ein Pin sein, z.B. Pind.0

Du musst halt nur drauf achten, dass ein Taster im gedrückten Zustand am Pin eine "0" (also "Reset") zur Folge hat und das Loslassen eine "1" (also "Set").

Wenn du nun einen Taster z.B. an Pind.0 hast und den drückst du, um in eine Subroutine zu wechseln, dann folgt in der SUB ggf. als erstes der Befehl "BITWAIT".

Ein gaaaaanz kurzes Beispiel:

Do
If Pind.0 = 0 Then Gosub ISR1
.
.
.
Loop


ISR1:
Bitwait Pind.0, Set (warte, bis Pind.0 wieder 1 ist.... also losgelassen wurde.)
.
.
.
Return


Ich hoffe, du kannst es trotz der Kürze ein wenig verstehen. :hmmmm:


Welches Buch benutzt du denn, wenn da nichts von BITWAIT steht?
In der Hilfe von BASCOM ist das BITWAIT aber auch erklärt. Vielleicht solltest du da noch mal reinschauen..... und dann mit rumspielen bzw. ausprobieren. ;)


Viel Spaß beim tüfteln. :ciao:
Cassio
 
Hallo Neuuser,

wenn du dann gerade bei der Bascom-Hilfe bist, kannst du ja auch mal schauen, was da bei "Config Date" steht. Dann kannst du nämlich auch die Variable Date$ verwenden ;)
 
Hey Stevie....

wir hatten doch gesagt, wir wollten ihm nicht gleich alles um die Ohren hauen. ;)


Lass ihn erst mal in Ruhe ein Problem lösen...... und dann geht es weiter. :D


Gruß,
Cassio :ciao:
 
Hallo Neuuser!


DOCH, ich habe mich geirrt! :eek:

Die Aussage ist genau falsch herum:
Wenn ich mich nicht täusche, dann reagiert das Programm auch nicht,
selbst wenn das Programm vom "Return" zurück kommt und durch die "DO-LOOP Schleife" an der selben Stelle ankommt, solange sich der Status des Pins nicht mindestens einmal geändert hat.


.... ichTrottel!

Das Programm springt erst in die ISR, wenn du den Taster wieder losgelassen hast!

DEBOUNCE wartet also solange, bis der Pin wieder wechselt und springt dann erst zur SUB.

Allerdings musst du den Begriff "Warten" nicht als "wait" sehen, denn dein Programm läuft trotzdem weiter.


Sorry noch mal......

Gruß,
Cassio !
 
Ja erst mal das mit dem Entprellen hin bekommen dann schauen wir weiter.
hm, habe nun versucht das dort ein zu binden, Cassio, aber so wie es nun ist meckert er und wartet auf das ende der Anweisung finde nicht raus warum.
Habe die Bascom Hilfe auch noch angeschaut und sollte doch so funktionieren ?
Habe das Buch von Roland Walter.

dieses ist nur ein ausschnitt des Programm-es :D



Code:
Config Date = Mdy , Separator = /
Config Clock = Soft
Config Portd = Input
Bitwait Pind.3 , Set                                        'Reset
Dim Pind.3 As Bit
Portd.0 = 1                                                 'Taster1, Zeit/Datum stellen, PullUp ein, schaltet gegen Minus
Portd.3 = 1                                                 'Taster2,  Zahl hochzählen, PullUp ein, schaltet gegen Minus

Time$ = "00:00:00"                                          'Setzen auf Startwert
Date$ = "00/00/00"                                          'Setzen auf Startwert

Do
  Locate 1 , 1
   Lcd Time$                                                'Zeige Zeit in Zeile1
   Locate 2 , 1
   Lcd _day ; "/" ; _month ; "/0" ; _year                   'Zeige Datum in Form DD/MM/YYin Zeile2

  If Pind.0 = 0 Then Gosub Time                            'wiederhole Anzeige bis Taster 1 zum Stellen gedrückt, springe nach Sub "Time"

Loop
End
'Stunde#########################################################################

Time:
Waitms 200
Cls                                                         'lösche Zeilen
Do
Locate 1 , 1
Lcd "Set Hour:"                                             'Stunden setzen
Locate 2 , 1
Lcd _hour

If Bitwait Pind.3 , Reset = 0 Then                          'Mit Taster 2
           Incr _hour                                       'hochzählen
           Locate 2 , 1
           Lcd _hour
End
If _hour > 23 Then                                          'Zählt bis Max, danach wieder ab 0
Cls
_hour = 00
 
Hallo Casio!

Das Programm springt erst in die ISR, wenn du den Taster wieder losgelassen hast!
DEBOUNCE wartet also solange, bis der Pin wieder wechselt und springt dann erst zur SUB.
Allerdings musst du den Begriff "Warten" nicht als "wait" sehen, denn dein Programm läuft trotzdem weiter.

Hier muss ich Dir leider wiedersprechen!!!!!

DEBOUNCE springt definitiv sofort bzw. nach der Wartezeit / Prüfung von 25 ms (Default). Die Aussage, das Debounce erst spring wenn der Pin wieder wechselt ist falsch!

Zu überprüfen ist das ganz einfach mit folgenden Code:

Code:
$regfile = "m128def.dat"
$crystal = 16000000

$baud = 38400

Config Portc = Output
Portc = &HFF

Config Porta = Input
Porta = &HFF

Do
   Debounce Pina.0 , 0 , Led_pin_1 , Sub
Loop

Led_pin_1:
   Toggle Portc.0
Return

Außerdem ist es sehr gefährlich in Verbindung mit Debounce von ISR und Interrupt-Service-Routinen zu sprechen. Das erweckt ein völlig falsches Bild!

Debounce verwendet keinerlei interne HW-Ressoucen wie z.B. Timer, oder Interrupts. Das einzige was Debounce anlegt ist für jeden angesprochenen Port ein Byte im SRAm wobei darin jeweils nur das jeweilige Port-Pin-Bit verwendet wird.

Allerdings konnte ich auf die Schnelle noch nicht genau heraus finden, wie Debounce die 25 ms Wartezeit genau macht. Diese ist übrigens über "Config Debounce" auch noch konfigurierbar.
Aufgrund des Verhaltens beim Rumprobieren mit Config Debounce gehe ich von folgendem aus:
- Mit Config Debounce kann eine Byte-Variable (Wert 0-255 ms) konfiguriert werdenm
- Größere Werte ergeben gegenüber 255 keine Änderung mehr
- Debounce wartet nach eintritt des Ereignis1 hart und unabdingbar die Zeit und prüft danach nochmal.
- Ich gehe davon aus, dass bei der Verwendung eines Debounce die resltiche Programmbearbeitung um 1-255ms (Default = 25ms) "steht".

Damit ist es total diskrekt programmiert!!!

Grüße,
Markus
 
ja was soll ich den nun am besten verwenden um zu entprellen, DEBOUNCE, oder
Bitwait :confused: ich habe beide versucht dort ein zu binden entweder das Programm läuft und es funktioniert mit den Tastern keine Entprellung oder das Programm macht komplett nur Mist wen ich sie bediene.
Langsam habe ich den Eindruck das ist was anderes faul, kann BITTE jemand das Programm so wie es ist probieren und mir sagen ob die Einstellung der zeit über die tasten in Minuten zu machen ist ohne das sie gleich bis zu 5 stellen hoch springen ?

Gruß Neuuser

Code:
'Lcd An Portb , Taster Zum Stellen An Pd.0
'zum Hochzählen An Pd.3.
'zwischen XTAL ist ein 32.xxx Uhrenquarz


$regfile = "m8def.dat"
$crystal = 1000000                                          'intern

Config Lcdpin = Pin , Rs = Portb.0 , E = Portb.1 , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , Db7 = Portb.5
Config Lcd = 24 * 2
Initlcd
Cursor Off
Cls

Enable Interrupts

Config Date = Mdy , Separator = /
Config Clock = Soft
Config Portd = Input


Portd.0 = 1                                                 'Taster1, Zeit/Datum stellen, PullUp ein, schaltet gegen Minus
Portd.3 = 1                                                 'Taster2,  Zahl hochzählen, PullUp ein, schaltet gegen Minus


Time$ = "00:00:00"                                          'Setzen auf Startwert
Date$ = "00/00/00"                                          'Setzen auf Startwert

Do
   Locate 1 , 1
   Lcd Time$                                                'Zeige Zeit in Zeile1
   Locate 2 , 1
   Lcd _day ; "/" ; _month ; "/0" ; _year                   'Zeige Datum in Form DD/MM/YYin Zeile2
'lcd Date$                                                     'zeige Datum in Form MM/DD/YY

   If Pind.0 = 0 Then Gosub Time                            'wiederhole Anzeige bis Taster 1 zum Stellen gedrückt, springe nach Sub "Time"
Loop
End


'Stunde
Time:
Waitms 200
Cls                                                         'lösche Zeilen
Do
Locate 1 , 1
Lcd "Set Hour:"                                             'Stunden setzen
Locate 2 , 1
Lcd _hour
         If Pind.3 = 0 Then                                 'Mit Taster 2
           Incr _hour                                       'hochzählen
           Locate 2 , 1
           Lcd _hour
         End If
If _hour > 23 Then                                          'Zählt bis Max, danach wieder ab 0
Cls
_hour = 00
End If                                                      'solange, bis Taster 1 gedrückt
Loop Until Pind.0 = 0
Waitms 200



'Minute
Cls
Do
Locate 1 , 1
Lcd "Set Minute:"
Locate 2 , 1
Lcd _min
         If Pind.3 = 0 Then
           Incr _min
           Locate 2 , 1
           Lcd _min
         End If
If _min > 59 Then
Cls
_min = 00
End If
Loop Until Pind.0 = 0
Waitms 200
Cls



'Tag
Cls
Do
Locate 1 , 1
Lcd "Set Day :"
Locate 2 , 1
Lcd _day
         If Pind.3 = 0 Then
           Incr _day
           Locate 2 , 1
           Lcd _day
         End If
If _day > 31 Then
Cls
_day = 01
End If
Loop Until Pind.0 = 0
Waitms 200
Cls



'Monat
Cls
Do
Locate 1 , 1
Lcd "Set Month :"
Locate 2 , 1
Lcd _month
         If Pind.3 = 0 Then
           Incr _month
           Locate 2 , 1
           Lcd _month
         End If
If _month > 12 Then
Cls
_month = 01
End If
Loop Until Pind.0 = 0
Waitms 200
Cls



'Jahr
Cls
Do
Locate 1 , 1
Lcd "Set Year :"
Locate 2 , 1
Lcd _year
         If Pind.3 = 0 Then
           Incr _year
           Locate 2 , 1
           Lcd _year
         End If
If _year > 10 Then
Cls
_year = 00
End If
Loop Until Pind.0 = 0
Waitms 200
Cls


_sec = 00                                                   'Springe Nach Setzen Von Zeit / Datum Wieder Zurueck
Return
 
Hallo Neuuser,

an Deinem Code ist mir bei ersten Überfliegen folgendes aufgefallen:

[1] Timer
Du verwendest ein Label Time und ein Sprungziel für GOSUB Timer. Timer ist gleichzeitig unter BASCOM der Name einer Funktion Time()

Returns a time-value (String or 3 Byte for Second, Minute and Hour) depending of the Type of the Target

Der Compiler meldet keinen Fehler. Ich selbst hatte in der Vergangeheit schon immer weider ganz große Probleme mit BASCOM die daruch entstanden sind, dass ich bereits schon vorhandenen Namen von Funktionen und variablen nochmals in meinem eigenen Code verwendet hatte. BASCOM hatte in der Vergangenheit mir das ziemlich über mit Fehlfunktionen heimgezahlt.

Um hier auf der sicheren Seite zu sein und Wechselwikrungen die ich auch nicht mehr verstehe auszuschließen, solltest Du immer nur Namen / Labels / Variablen definieren die nicht nochmals irgendwo vorkommen.

Vorschlag :nurse: : Benenne Deine Routine Time einfach in Time_change um und damit bist Du auf der sicheren Seite!


Dein grundproblem versuche ich mir heute Abend mal genauer anzuschauen und auf meinem STK500 auszuprobieren. Vielleicht habe ich auch noch Lust Dir dann eine Musterlösung zu basteln :stupido2:

Grüße,
Markus
 
Hallo Casio!

Hier muss ich Dir leider wiedersprechen!!!!!

DEBOUNCE springt definitiv sofort bzw. nach der Wartezeit / Prüfung von 25 ms (Default). Die Aussage, das Debounce erst spring wenn der Pin wieder wechselt ist falsch!


Hallo Markus!

Das macht ja nichts. Wie gut, dass immer einer mit "auspasst". ;)

Ich habe es nicht mehr überprüft.... sondern habe mich bei einer alten Steuerung von der Anzeige meines Displays täuschen lassen.

Letztlich ist es aber zur Zeit für Neuuser noch egal.... ;)

Danke dir trotzdem, für die Berichtigung!






Hallo Neuuser !

Wie schon erwähnt, bringt dir der DEBOUNCE nur etwas, wenn du an eine andere Stelle in das Programm springen möchtest.
Um deinen Taster zum Einstellen zu entprellen, kannst du BITWAIT nehmen.

Versuche es aber doch mal so:
(Nur mal eine Quick`n Dirty-Lösung aus dem Stehgreif)

Code:
.
.
.
'--------------------------------------
' Uhreinstellungen
Config Date = Dmy , Separator = .
Config Clock = Soft

Enable Interrupts

Time$ = "00:00:00"
Date$ = "01.01.08"
'--------------------------------------
.
.
.


Do

Debounce Pind.0 , 0 , Std_einstellen , Sub     ' Springt zum Stunden einstellen
   Locate 1 , 1
   Lcd Time$
   Locate 2 , 1
   Lcd Date$
                                                   
Loop

End

'------------------------------
Std_einstellen:
Cls
Locate 1 , 1
Lcd "Std. einstellen"

Do
If Pind.3 = 0 Then Incr _hour
Bitwait Pind.3 , Set                   ' Wartet bis Pind.3 losgelassen wurde
If _hour > 23 Then _hour = 0 

Locate 2 , 1
Lcd Time$

Loop Until Pind.0 = 0               ' Wiederholung, sofern du nicht Pind.0 drückst
Gosub Min_einstellen               ' Springt zum Minuten einstellen
Return                                  ' Sorgt für den Schritt zurück

'-----------------------------
Min_einstellen:
Locate 1 , 1
Lcd "Min. einstellen"

Bitwait Pind.0 , Set

Do
If Pind.3 = 0 Then Incr _min
Bitwait Pind.3 ,  Set
If _min > 59 Then _min = 0

Locate 2 , 1
Lcd Time$

Loop Until Pind.0 = 0
Gosub Sec_einstellen
Return

'------------------------------
Sec_einstellen:
Locate 1 , 1
Lcd "Sec. einstellen"

Bitwait Pind.0 , Set

Do
.......und so weiter





Hast du nun in etwa verstanden, wie ich das mit dem DEBOUNCE und dem BITWAIT gemeint habe?

Ich hoffe, es ist verständlich rüber gekommen und mir sind zur späten Stunden keine groben Fehler unterlaufen. ;)

Schöne Grüße,
Cassio
 

Ü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)