-         

Ergebnis 1 bis 8 von 8

Thema: Taster entprellen und anschliessen

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.05.2006
    Alter
    29
    Beiträge
    122

    Taster entprellen und anschliessen

    Anzeige

    Hallo Leute

    Ich möchte einen (später noch ein paar mehr) Taster an den PORTB <7:4> drantun, der dann bei Betätigung einen Interrupt auslöst. Dieser Interrupt sollte dann dazu führen, dass der Timer 1 zu laufen beginnt.
    Ich dachte eigentlich, dass das ne ziemlich simple Sache sein sollte, doch so langsam bin ich mit meinem Latein am Ende und das Ding läuft noch immer nicht.
    Als Taster verwende ich so ein Ding: http://www.distrelec.com/ishopWebFro...ries/is/1.html
    Dieser ist einerseits an 5V, und über eine Pull-Down-Widerstand von 470 Ohm mit der Masse verbunden. Ich habe das ganze auch mal mit dem Multimeter getestet und bekomme bei offenem Taster 0.1mV und bei gedrücktem Taster 5.01V. Somit ist da noch das Problem des Entprellens, doch das sollte ich eigentlich softwaremässig mit einer Warteschleife von 20ms überbrückt haben.
    Doch auch so reagiert der PIC nicht auf die Betätigung des Tasters.

    Das Programm sieht dann so aus:
    Code:
    ISR						;interupt service routine
    	movwf	copyw
    	swapf	STATUS, W
    	bcf		STATUS, RP0
    	movwf	copys
    	
    	btfsc	PIR1, TMR1IF
    	goto	TMR1ISR
    	btfsc	PORTB, 7
    	goto	RBInt
    	goto	ISRend
    
    
    ..........
    
    
    RBInt
    	bcf		INTCON, RBIF
    	bsf		UPDRBI
    	goto	ISRend
    
    	
    ISRend						;interupt end routine
    	swapf	copys, w
    	movwf	STATUS
    	swapf	copyw, f
    	swapf	copyw, w
    	bsf		UPDLCD
    	retfie
    
    
    ...............
    
    
    InitTimer
    	bcf		STATUS, RP0
    	movlw	B'00110101'	;prescaler:  1:8; internal clock; no synchronize; Timer1 enabled
    	movwf	T1CON
    	bsf		STATUS, RP0
    	bcf		PIE1, TMR1IE
    	bcf		STATUS, RP0
    	bsf		INTCON, RBIE
    	bsf		INTCON, PEIE
    	bsf		INTCON, GIE
    	return
    
    	Main
    	btfsc	UPDLCD
    	goto	WriteLcd
    	call	Init
    	call	InitLCD
    	call	InitTimer
    	
    WriteLcd
    	bcf		UPDLCD
    	btfsc	UPDRBI
    	goto	TestRBI
    	call	printzehn
    	call	printseke
    	call	printsekz
    	call	printmine
    	call	printminz
    	call	printstde
    	call	printstdz
    	movlw	b'11001111'
    	call	OutLcdControl
    	movlw	D'10'
    	movwf	loops
    	call	WAIT
    	goto WriteLcd
    	
    TestRBI
    	bcf		UPDRBI
    	movlw	D'20'
    	movwf	loops
    	call	WAIT
    	btfsc	PORTB, 7
    	goto	StartTMR
    	goto	WriteLcd
    	
    StartTMR
    	bsf		STATUS, RP0
    	bsf		PIE1, TMR1IE
    	bcf		STATUS, RP0
    	goto	WriteLcd
    Die Hardware und der restliche Code sollten einwandfrei sein, da das ganze ohne den Taster ohne Probs funktionniert

    Etwas lustiges ist mir auch noch aufgefallen: Wenn ich den Pull-Down Widerstand am Taster entferne, und dann nur ein Bein des Widerstands an die Masse hänge, läuft der Timer/Uhr. (Das 2. Bein hängt in der Luft) Das ist irgendwie ein bisschen komisch. ^^

    Hat jemand schon mal so etwas gemacht, und könnte mir sagen, was ich ändern sollte?

    mfg orph

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.10.2004
    Ort
    Nordschwarzwald
    Alter
    34
    Beiträge
    506
    Zwei Sachen:
    - Bitte sagen welchen PIC du nimmst, damit ich mir die ISR-Register im Datenblatt mal anschaun kann
    - deinen Code (zumindest im relevanten Teil) etwas kommentieren, also hinschreiben was passieren soll. Dann ist das überprüfen und nachvollziehen durch andere viel leichter.

    MfG
    Stefan

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.05.2006
    Alter
    29
    Beiträge
    122
    Ok, dann also mal folgende Angaben:
    - PIC 16F88


    Code:
    ISR                  ;interupt service routine 
       movwf   copyw        ;Status und W retten
       swapf   STATUS, W 
       bcf      STATUS, RP0 
       movwf   copys 
        
       btfsc   PIR1, TMR1IF ;testet Timer 1 Interrupt-Flag
       goto   TMR1ISR        ; wenn gesetzt, zur Timer-Inkrementierung gehen
       btfsc   PORTB, 7       ; wenn nicht gesetzt, testen ob der Taster den Interrupt ausgelöst hat (nur Reaktion, wenn aufsteigende Flanke den Interrupt ausgelöst hat)
       goto   RBInt             ; wenn ja, zur Taster-Rutine gehen
       goto   ISRend          ; wenn nicht, ISR beenden
    
    
    .......... 
    
    
    RBInt                              ;Taster-ISR
       bcf      INTCON, RBIF    ;PORTB-Interrupt-Flag löschen
       bsf      UPDRBI             ;Update-Flag für PORTB setzten (bedingt Reaktion im Hautprogramm)
       goto   ISRend              ; Interrupt beenden
    
        
    ISRend                  ;iRutine, um ISR zu beenden
       swapf   copys, w          ;Status, und w wieder laden
       movwf   STATUS 
       swapf   copyw, f 
       swapf   copyw, w 
       bsf      UPDLCD             ;Flag setzen, damit das LCD neu beschrieben wird
       retfie                      ;ISR-ende
    
    
    ............... 
    
    
    InitTimer                         ;Init des Timer, "PIE1, TMR1IE" wird noch nicht gesetzt (Timer1 interrupt enable-bit) 
       bcf      STATUS, RP0 
       movlw   B'00110101'   ;prescaler:  1:8; internal clock; no synchronize; Timer1 enabled 
       movwf   T1CON 
       bsf      STATUS, RP0 
       bcf      PIE1, TMR1IE 
       bcf      STATUS, RP0 
       bsf      INTCON, RBIE        ;PORTB-Interrupt an
       bsf      INTCON, PEIE        ;Periphäre-Interrupts an
       bsf      INTCON, GIE          ;Global-Interrupt an
       return 
    
       Main 
       btfsc   UPDLCD              ;Testen, ob das LCD neu beschrieben werden muss (bei Reset nicht der Fall)
       goto   WriteLcd 
       call   Init                       ;Initialisierungen
       call   InitLCD                        ;Initialisierungen
       call   InitTimer                        ;Initialisierungen
        
    WriteLcd                             ;Endlosschleife des Hauptprogramms,
       bcf      UPDLCD                ;LCD-Update-Flag löschen
       btfsc   UPDRBI                 ;testen, ob der Taster gedrückt wurde
       goto   TestRBI                 ;zur Taster-Rutine gehen
       call   printzehn                  ;LCD schreiben
       call   printseke                   ;LCD schreiben
       call   printsekz                   ;LCD schreiben
       call   printmine                   ;LCD schreiben
       call   printminz                   ;LCD schreiben
       call   printstde                   ;LCD schreiben
       call   printstdz                   ;LCD schreiben
       movlw   b'11001111'         ;Cursor an letzte Position
       call   OutLcdControl 
       movlw   D'10'                   ;Warteschleife, um LCD nicht zu überlasten
       movwf   loops 
       call   WAIT 
       goto WriteLcd                    ;Endlosschleife
        
    TestRBI                              ;Testen, ob der Taster wirklich gedrückt wurde
       bcf      UPDRBI                 ;Flag löschen
       movlw   D'20'                   ;Warteschleife, um prellen abzuwarten
       movwf   loops 
       call   WAIT 
       btfsc   PORTB, 7                ;Ist der Taster immer noch angeschaltet?
       goto   StartTMR                 ;wenn ja, zur Timer-Start-Rutine gehen
       goto   WriteLcd                  ;wenn nein, abbruch
        
    StartTMR                             ;Timer starten
       bsf      STATUS, RP0         ;bank 1
       bsf      PIE1, TMR1IE         ;Timer1 Enable-Bit setzten
       bcf      STATUS, RP0          ;Bank 0
       goto   WriteLcd                 ;zurück zum Hauptprogramm

    So, sorry, dass ich die Kommentare vergessen habe. Diese sollten weiterhelfen.

    Guss orph

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.10.2004
    Ort
    Nordschwarzwald
    Alter
    34
    Beiträge
    506
    Die erste Sache, die mir in den Sinn kommt:
    möglicherweise wird die ISR zu oft nacheinander aufgerufen...
    Wäre denkbar, aber müsste sich (glaub ich zumindest) anders verhalten.

    Was ich als erstes prüfen würde:
    - in der ISR einen Portpin setzen und damit schaun, ob die wirklich aufgerufen wird
    - im Hauptprogramm in der TestRBI-Routine einen Portpin setzen und damit schaun, ob die wirklich aufgerufen wird

    Nach dem Ausprobieren bitte hier posten - dann kann man weiterverfolgen wo der Fehler liegt.

    Btw. hast du die Tristate-Register (TRISB) richtig gesetzt?

    MfG
    Stefan

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.05.2006
    Alter
    29
    Beiträge
    122
    moin

    Durch den Test mit den LED's habe ich bemerkt, dass der PIC irgendwie gleich nach dem Reset (Timer1 ausgeschaltet, Uhr läuft nicht, Taste nicht gedrückt) zu der ISR springt.
    Ich habe nun mal eine 100nF-Kondensator parallel zum Taster geschaltet, um die Software-Entprellung zu umgehen, doch nun läuft die Uhr wieder gleich nach dem Reset los. Manchmal werden auch einzelene Stellen auf dem LCD ohne Grund mit einer "0" überschrieben.

    Hier mal der gesamte Code:
    Code:
    	list 	p=16F88
    #include 	<p16f88.inc>
    
    
    	__CONFIG    _CONFIG1, _CP_OFF & _LVP_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _HS_OSC
    
     
    ; variables
    copyw		Equ	0x20
    copys		Equ 0x21
    LcdDaten	Equ	0x22
    LcdStatus	Equ	0x23
    loops		Equ	0x24
    loops2		Equ	0x25
    stde		Equ	0x27
    stdz		Equ 0x2C
    mine		Equ 0x2D
    minz		Equ 0x30
    seke		Equ	0x31	; einerstelle sekunden
    sekz		Equ	0x32	;zehnerstelle sekunden
    Flags		Equ	0x40
    zehn		Equ	0x41
    
    
    ; constants
    PORTD		Equ	PORTB
    
    #define	LcdE		PORTA, 2
    #define	LcdRw		PORTA, 0
    #define	LcdRs		PORTA, 1
    #define UPDLCD		Flags, 0
    #define	UPDRBI		Flags, 1
    
    
    	
    	
    	org		0x00
    	goto Main
    
    	org 	0x04
    
    ISR						;interupt service routine
    	movwf	copyw
    	swapf	STATUS, W
    	bcf		STATUS, RP0
    	movwf	copys
    	
    	btfsc	PIR1, TMR1IF		;Test TMR1 Interrupt-Flag
    	goto	TMR1ISR
    	btfsc	INTCON, RBIF		;Test PORTB Interrupt-Flag
    	goto	RBInt
    	goto	ISRend
    
    TMR1ISR	
    	bcf		STATUS, RP0
    	bcf		PIR1, TMR1IF	;clear interupt flag
    	
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	
    	movlw   0x0B
    	movwf	TMR1H 			
    	movlw  	0xDA
    	movwf  	TMR1L
       
    	incf	zehn, f
    	movfw	zehn
    	sublw	.10
    	btfss	STATUS, Z
    	goto	ISRend
    	clrf	zehn
    	incf	seke, f			;seke +1
    	movfw	seke		
    	sublw	.10				;seke -10 ;result negativ => z=0
    	btfss	STATUS, Z		;test z, if z=1 => skip next order
    	goto 	ISRend	
    	clrf	seke
    	incf	sekz, f
    	movf	sekz, w
    	sublw	.6
    	btfss	STATUS, Z
    	goto	ISRend
    	clrf	sekz
    	incf	mine, f
    	movf	mine, w
    	sublw	.10
    	btfss	STATUS, Z
    	goto	ISRend
    	clrf	mine
    	incf	minz, f
    	movf	minz, w
    	sublw	.6
    	btfss	STATUS, Z
    	goto	ISRend
    	clrf	minz
    	incf	stde, f
    	movf	stde, w
    	sublw	.10
    	btfss	STATUS, Z
    	goto	ISRend
    	clrf	stde
    	incf	stdz, f
    	movf	stdz, w
    	sublw	.10
    	btfss	STATUS, Z
    	goto	ISRend
    	clrf	stdz
    	goto	ISRend
    	
    RBInt
    	bcf		INTCON, RBIF
    	bsf		UPDRBI
    	goto	ISRend
    
    	
    ISRend						;interupt end routine
    	swapf	copys, w
    	movwf	STATUS
    	swapf	copyw, f
    	swapf	copyw, w
    	bsf		UPDLCD
    	retfie
    
    Init
    
    	bcf		INTCON, GIE
    	bcf		INTCON, PEIE
    	bcf		INTCON, RBIE
    	bsf		STATUS, RP0
    	movlw	B'11110000'
    	movwf	TRISB
    	movlw	B'00000000'
    	movwf	TRISA
    	movlw	B'00000000'
    	movwf	ANSEL
    	bcf		STATUS, RP0
    	clrf	stde
    	clrf	stdz
    	clrf	mine
    	clrf	minz
    	clrf	seke
    	clrf	sekz
    	clrf	zehn
    	clrf	LcdDaten
    	clrf	LcdStatus
    	return
    
    InitTimer
    	bcf		STATUS, RP0
    	movlw	B'00110101'	;prescaler:  1:8; internal clock; no synchronize; Timer1 enabled
    	movwf	T1CON
    	bsf		STATUS, RP0
    	bcf		PIE1, TMR1IE
    	bcf		STATUS, RP0
    	bsf		INTCON, RBIE
    	bsf		INTCON, PEIE
    	bsf		INTCON, GIE
    	return
    
    	Main
    	btfsc	UPDLCD
    	goto	WriteLcd
    	call	Init
    	call	InitLCD
    	call	InitTimer
    	
    WriteLcd
    	bcf		UPDLCD
    	btfsc	UPDRBI
    	goto	TestRBI
    	call	printzehn
    	call	printseke
    	call	printsekz
    	call	printmine
    	call	printminz
    	call	printstde
    	call	printstdz
    	movlw	b'11001111'
    	call	OutLcdControl
    	movlw	D'10'
    	movwf	loops
    	call	WAIT
    	goto WriteLcd
    	
    TestRBI		
    	bcf		UPDRBI
    	goto	StartTMR
    	
    StartTMR
    	bsf		STATUS, RP0
    	bsf		PIE1, TMR1IE
    	bcf		STATUS, RP0
    	goto	WriteLcd
    
    WAIT
    wai		movlw	.249
    		movwf	loops2
    wai2	nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    		nop
    	nop
    		decfsz	loops2, F
    		goto	wai2
    		
    		decfsz	loops, F
    		goto 	wai
    		return
    
    InitLCD
    	movlw	D'10'
    	movwf	loops
    	call	WAIT
    	movlw	B'00000010'
    	call	OutLcdControl	
    	movlw	B'00101000'
    	call	OutLcdControl	
    	movlw	B'00001101'
    	call	OutLcdControl
    	movlw	B'00000001'
    	call	OutLcdControl
    	movlw	B'00000110'
    	call	OutLcdControl
    	movlw	'C'
    	call	OutLcdDaten
    	movlw	'l'
    	call	OutLcdDaten
    	movlw	'o'
    	call	OutLcdDaten
    	movlw	'c'
    	call	OutLcdDaten
    	movlw	'k'
    	call	OutLcdDaten
    	movlw	':'
    	call	OutLcdDaten
    	movlw	' '
    	call	OutLcdDaten
    	movlw	'r'
    	call	OutLcdDaten
    	movlw	'u'
    	call	OutLcdDaten
    	movlw	'n'
    	call	OutLcdDaten
    	movlw	B'11000011'
    	call	OutLcdControl
    	movlw	'0'
    	call	OutLcdDaten
    	movlw	'0'
    	call	OutLcdDaten
    	movlw	':'
    	call	OutLcdDaten
    	movlw	'0'
    	call	OutLcdDaten
    	movlw	'0'
    	call 	OutLcdDaten
    	movlw	':'
    	call	OutLcdDaten	
    	movlw	'0'
    	call	OutLcdDaten
    	movlw	'0'
    	call 	OutLcdDaten
    	movlw	'.'
    	call	OutLcdDaten
    	movlw	'0'
    	call	OutLcdDaten
    	return
    
    LcdBusy
        bsf     STATUS, RP0
    	movlw	B'11111111'
    	movwf	TRISB
        bcf     STATUS, RP0
    BusyLoop		
    	bcf		LcdRs
    	bsf		LcdRw
    	bsf		LcdE
    	nop
    	movf	PORTD, w
    	movwf	LcdStatus
    	bcf		LcdE
    	nop
    	bsf		LcdE
    	nop
    	bcf		LcdE
    	btfsc	LcdStatus, 3
    	goto 	BusyLoop
    	bcf		LcdRw
        bsf     STATUS, RP0	
    	movlw	B'11110000'
    	movwf	TRISB
        bcf     STATUS, RP0
    	return	
    
    OutLcdControl
    	movwf	LcdDaten
    	call	LcdBusy
    	swapf	LcdDaten, w
    	andlw	H'0F'
    	movwf	PORTD	
    	bsf		LcdE
    	nop
    	bcf		LcdE	
    	movf	LcdDaten, w
    	andlw	H'0F'
    	movwf	PORTD	
    	bsf		LcdE
    	nop
    	bcf		LcdE	
    	return
    
    OutLcdDaten
    	movwf	LcdDaten
    	call	LcdBusy
    	swapf	LcdDaten, w
    	andlw	H'0F'
    	movwf	PORTD	
    	bsf		LcdRs	
    	bsf		LcdE	
    	nop
    	bcf		LcdE	
    	movf	LcdDaten, w
    	andlw	H'0F'
    	movwf	PORTD		
    	bsf		LcdRs	
    	bsf		LcdE
    	nop
    	bcf		LcdE	
    	bcf		LcdRs		
    	return
    	
    printzehn
    	movlw	b'11001100'
    	call	OutLcdControl
    	movfw	zehn
    	addlw	'0'
    	call	OutLcdDaten
    	return
    	
    printseke	; ausgabe von seke
    	movlw	b'11001010'
    	call	OutLcdControl
    	movfw	seke
    	addlw	'0'
    	call	OutLcdDaten
    	return
    	
    printsekz
    	movlw	b'11001001'
    	call	OutLcdControl
    	movfw	sekz
    	addlw	'0'
    	call	OutLcdDaten
    	return
    	
    printmine
    	movlw	b'11000111'
    	call	OutLcdControl
    	movfw	mine
    	addlw	'0'
    	call	OutLcdDaten
    	return
    	
    printminz
    	movlw	b'11000110'
    	call	OutLcdControl
    	movfw	minz
    	addlw	'0'
    	call	OutLcdDaten
    	return
    
    printstde
    	movlw	b'11000100'
    	call	OutLcdControl
    	movfw	stde
    	addlw	'0'
    	call	OutLcdDaten
    	return
    	
    printstdz
    	movlw	b'11000011'
    	call	OutLcdControl
    	movfw	stdz
    	addlw	'0'
    	call	OutLcdDaten
    	return
    	
    	end
    Was kann hier nur so falsch sein?

    mbg hans

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.10.2004
    Ort
    Nordschwarzwald
    Alter
    34
    Beiträge
    506
    Hast du mal geschaut, ob er aus der ISR auch noch rauskommt?

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.05.2006
    Alter
    29
    Beiträge
    122
    Hallo

    Den Test mit den LEDs habe ich jetzt nochmals gemacht. Ich habe 2 LEDs am PORTA. Eines sollte zu Beginn der ISR kurz blinken, und das andere beim Verlassen der ISR. Nach einem Reset beginnen jedoch beide LEDs "optisch gleichzeitig" dauerhaft zu leuchten. Respektive, sie blinken in enorm kleinen Abständen, heisst so viel wie der PIC ist in einer ISR-Endlosschleife. Ich werde dann das Problem heute nochmals angehen.

    Noch eine andere Frage: Es ist schon richtig, dass beim offenen Taster 0V am PORT-Pin liegt und beim gedrückten Taster 5V, nicht umgekehrt?

    gruss, Hans-Jakob

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.12.2005
    Ort
    Euskirchen-Großbüllesheim
    Alter
    67
    Beiträge
    2.063
    Hallo Hans-Jakob,
    wenn Du in Assembler programmierst, dann kannst Du Dir mal meine Assemblerbeispiele unter http://www.domnick-elektronik.de/picasm.htm bei 'EntprTast1' in der 'Isr_TMR2' anschauen.
    Die Philosophie ist folgende:
    Jede Millisekunde wird per Timer-Interrupt eine ISR aufgerufen. Die wird natürlich so kurz wie möglich gehalten und nur das erledigt, was zeitkritisch ist.
    Das Abfragen eines Tasters ist so eine zeitkritische Sache. Immerhin benötigt man 30...80ms Entprellzeit. Bei mir wird das meistens so geregelt, daß bei Taster = aktiv eine Zählervariable jede Millisekunde incrementiert wird, bis sie eben 30...80 erreicht. Dann setze ich ein Flag / Bit und inkrementiere nicht weiter. Ist der Taster inaktiv, wird die Zählvariable bis auf Null dekrementiert und das Flag wieder gelöscht.
    Wenn der Taster stark prellt, wird der Zähler rauf ... runter ... rauf ... zählen, bis der Taster nur noch aktiv bleibt und dann bis 30...80 hochgezählt werden kann.
    Du benötigst für jeden Taster eine Zählvariable und ein Bit / Flag.
    In der Haupschleife kannst Du dann hin und wieder mal nachschauen, ob ein Flag gesetzt ist und dann verzweigen.
    Entgehen kann nichts, weil die Taster im Interrupt abgefragt werden. Das ist wie eine Garantie (wenn Du auch aus der ISR wieder raus gehst).
    MfG Karl-Heinz
    HobbyElektronik hier klicken ....

Berechtigungen

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