gulliver
22.05.2007, 14:29
Hallo Jungs
Irgendwie bin ich jetzt ziemlich ratlos und weiß nicht mehr weiter.
Habe mir ein Netzteil für meine Kameras gebaut, wo ich die unterschiedlichen Spannungen mittels Tiny11 wähle.
Normalerweise würde eine simple Widerstandsumschaltung mit Drehschalter o.ä. völlig ausreichen, aber mein Spieltrieb hat mir diesen Floh ins Ohr gesetzt. Hintergrund ist auch, daß ich nicht aus Versehen die Spannung umschalte, während eine Kamera dran hängt. Deswegen habe ich auch den Tasteninterrupt nach Ablauf der Zeit oder nach erkanntem Tastendruck abgeschaltet, so daß Fehlbedienungen ausgeschlossen sind. Eine andere Spannung kann erst nach Neueinschalten gewählt werden.
Das Programm dürfte wegen der üppigen Kommentare gut durchschaubar sein. Die Belegung der Pins sieht man im Kopf.
Nun zu meinem Problem:
Im Simulator macht es, was es soll, aber in der Schaltung schaltet die 3V-LED, die ich als Default-Spannung gewählt habe, nur einmal ein und dann wird gleich auf die 4,3V (PB2) umgeschaltet, ohne einen Taster gedrückt zu haben.
Zuerst dachte ich an einen Schaltungsfehler. Darum habe ich den Tiny mit Tastern und LED's auf ein Steckbrett gesetzt und da passiert genau dasselbe. Jetzt bin ich so ziemlich ausgelaugt und habe keine Ideen mehr und hoffe, daß jemand einen Tip für mich hat.
Danke schon mal im Voraus
Roger
;************************************************* *******************
; Netzteil für Kameras, 3V, 4,3V und 6V
;
; MCU: ATtiny11; interner Takt=1MHz
; Version: 1.2
; Entprellroutine im Timer-Interrupt
;
; - Taster-4,3V an PB2 (Pin7)
; - Taster-6V an PB1 (Pin6)
; - Schaltausgang 3V über PB0 (Pin5)
; - Schaltausgang 4,3V über PB3 (Pin2)
; - Schaltausgang 6V über PB4 (Pin3)
;
; - T-Bit fungiert als Merker für Taste entprellt und Zeitablauf
;************************************************* *******************
;
.nolist
.include "C:\Programme\AVR Tools\AvrAssembler2\Appnotes\tn11def.inc"
.list
;
; Konstanten
.equ key_port = PINB ; Eingabe
.equ t_43v = PB2 ; Taster-4,3V
.equ t_6v = PB1 ; Taster-6V
.equ t_maske = 0b00000110 ; für Tastenmaskierung
.equ schalt_port = PORTB ; Ausgabe
.equ a_3v = PB0 ; Schaltausgang für 3V
.equ LED_default = PB0 ; zugehörige LED
.equ a_43v = PB3 ; Schaltausgang für 4,3V
.equ a_6v = PB4 ; Schaltausgang für 6V
.equ ext_int = 0b00100000 ; Maskierung für PinChange Interrupt
.equ schlafen = 0b00100000 ; Sleep-Modus erlauben
.equ timerwert = 255-15 ; etwa 15ms
.equ zeitlimit = 3 ; 255 x15ms x3 ca.11sek, Zeit für Spannungswahl
.equ zeit_toggle = 3 ; 3x 15ms=45ms, Blinkintervall der 3V-LED
; leuchtet dauernd, wenn Zeit abgelaufen ist
; Register
.def Save = R2 ; wegen fehlendem Stack
.def key_ct0 = R3
.def key_ct1 = R4
.def key_state = R5
.def key_press = R6
.def mp = R16 ; Arbeitsregister
.def merker_t = R17 ; merken,ob Taste gedrückt wurde
.def zeit_L = R18 ; Gesamtzeit
.def zeit_H = R19
.def Blinker = R20 ; Zähler für Blinkintervall
;
; Interruptvektoren
.cseg
rjmp main ; Programmstart
reti ; externer Interrupt für Flankensteuerung
rjmp taste ; Pin change handler
rjmp timer ; Timer0 overflow handler
reti ; Analog Comparator handler
;
;************ Interrupt-Routinen *********************************
taste:
in Save,SREG ; Stack sichern
in merker_t,key_port ; Taste sichern, falls eine gedrückt wurde ;R1
andi merker_t, t_maske ; nur Tasten maskieren
ldi mp,0
out GIMSK,mp ; externe Interrupts abschalten; Neuwahl einer
; Spannung ist nur nach Neueinschalten möglich
out SREG,Save ; Stack wieder zurückschreiben
reti
;
timer:
in Save,SREG ; Stack sichern
tst merker_t ; wurde eine Taste gedrückt?
breq weiter ; nein, Entprellung überspringen
;
in mp, key_port ; Taste sichern, falls eine gedrückt wurde ;R1
andi mp, t_maske ; nur die Tasten maskieren
com mp ; low active
eor mp, key_state
and key_ct0, mp ; reset counter
and key_ct1, mp
com key_ct0 ; count
eor key_ct1, key_ct0
and mp, key_ct0 ; input AND last counterstate
and mp, key_ct1
eor key_state, mp ; toggle state
and mp, key_state ; 0-1-transition
or key_press, mp ; store key press detect
tst key_press ; Taste schon festgemacht?
breq weiter ; nein, noch eine Runde
com key_press
zeitende:
out SREG,Save
set ; T-Flag setzen und tschüß
rjmp ende
;
weiter:
dec Blinker ; Blinkzeit runterzählen
brne weiter_ ; wenn runtergezählt ist,
ldi Blinker,zeit_toggle ; dann neuladen und LED umschalten
sbis schalt_port,LED_default ; überspringe,wenn LED aus ist
rjmp led_aus
;
cbi schalt_port,LED_default ; LED einschalten
rjmp weiter_
;
led_aus:
sbi schalt_port,LED_default ; LED ausschalten
;
weiter_:
dec zeit_L ; Zeit runterzählen
brne raus ; wenn Nulldurchlauf,
dec zeit_H ; H-Teil runterzählen
breq zeitende ; Zeit abgelaufen
raus:
out SREG,Save ; Stack wieder zurückschreiben
ende:
ldi mp,1<<PCIF ; Flag für PinChange-Interrupt löschen,
out GIFR,mp ; da es auch auf die Schaltausgänge reagiert
reti
;
;************** Unterprogramme **************************************
;hier wird die gedrückte Taste ermittelt und die entsprechende Spannung
;eingeschaltet. Interrupts werden abgeschaltet
auswerten:
cli ; Interrupt löschen
ldi mp,0 ; Timer abschalten, wird nicht mehr benötigt
out TIMSK,mp
clt ; T-Flag löschen
clc ; zuerst C-Flag löschen
ror key_press ; Merker zwecks Prüfung 1.Taste 2x rollen
ror key_press
brcc u6v ; Bit1 nicht gesetzt? dann auf 6V testen
cbi schalt_port,a_43v ; 4,3V einschalten; L, da PNP-Transistor
sbi schalt_port,a_3v ; 3V-LED abschalten
rjmp ok ; ... und raus
;
u6v:
ror key_press ; Merker zwecks Prüfung 2.Taste eins weiter
brcc default ; Bit2 nicht gesetzt? dann 3V einschalten
cbi schalt_port,a_6v ; 6V einschalten; L, da PNP-Transistor
sbi schalt_port,a_3v ; 3V-LED abschalten
rjmp ok
default:
cbi schalt_port,a_3v ; 3V-LED einschalten; sonst nichts
ok:
rjmp loop ; ... und fertig
;
;************** Hauptprogramm ************************************
main:
; es ist kein Softwarestack vorhanden, daher keine Call-Befehle!!!
; Hardware initialisieren
sbi schalt_port,a_3v ; alle Ausgänge ausschalten
sbi schalt_port,a_43v ; H, da alle Transistoren PNP sind!!!
sbi schalt_port,a_6v
sbi DDRB,a_3v ; Pin2,3 und 5 als Ausgang
sbi DDRB,a_43v
sbi DDRB,a_6v
cbi DDRB,t_43v ; PB1 und PB2 als Tastereingänge setzen
cbi DDRB,t_6v
ldi mp,(1<<CS00)|(1<<CS02) ;Teiler=1024 (entspr.etwa 1kHz=1ms)
out TCCR0,mp
ldi mp,timerwert ;Timer vorladen
out TCNT0,mp
ldi mp,1<<TOIE0 ;Timerinterrupt einschalten
out TIMSK,mp
ldi mp,ext_int
out GIMSK,mp ; externe Interrupts ermöglichen
ldi mp,schlafen ; Schlafmodus und Interrupt
out MCUCR,mp ; und ins Controlregister schreiben
clr key_state ;sämtliche Merker der
clr key_press ;Entprellung löschen
clr key_ct0
dec key_ct0
mov key_ct1, key_ct0
ldi zeit_H,zeitlimit ; Gesamtzeit bis Aktivierung festlegen
cbi schalt_port,0 ; Blink-LED einschalten
ldi Blinker,zeit_toggle ; Togglezeit für LED-Blinken
ldi mp,1<<PCIF ; Flag für PinChange-Interrupt löschen,
out GIFR,mp ; da es auch auf die Schaltausgänge reagiert
sei ; Interrupt global freigeben
;
loop:
sleep ; CPU schlafen legen
brts auswerten ; eine Taste gedrückt; wenn ja,auswerten
rjmp loop ; ... und wieder schlafen ...
;
.exit ; Programmende
edit:
Habe noch den Schaltplan des Netzteils beigepackt.
Irgendwie bin ich jetzt ziemlich ratlos und weiß nicht mehr weiter.
Habe mir ein Netzteil für meine Kameras gebaut, wo ich die unterschiedlichen Spannungen mittels Tiny11 wähle.
Normalerweise würde eine simple Widerstandsumschaltung mit Drehschalter o.ä. völlig ausreichen, aber mein Spieltrieb hat mir diesen Floh ins Ohr gesetzt. Hintergrund ist auch, daß ich nicht aus Versehen die Spannung umschalte, während eine Kamera dran hängt. Deswegen habe ich auch den Tasteninterrupt nach Ablauf der Zeit oder nach erkanntem Tastendruck abgeschaltet, so daß Fehlbedienungen ausgeschlossen sind. Eine andere Spannung kann erst nach Neueinschalten gewählt werden.
Das Programm dürfte wegen der üppigen Kommentare gut durchschaubar sein. Die Belegung der Pins sieht man im Kopf.
Nun zu meinem Problem:
Im Simulator macht es, was es soll, aber in der Schaltung schaltet die 3V-LED, die ich als Default-Spannung gewählt habe, nur einmal ein und dann wird gleich auf die 4,3V (PB2) umgeschaltet, ohne einen Taster gedrückt zu haben.
Zuerst dachte ich an einen Schaltungsfehler. Darum habe ich den Tiny mit Tastern und LED's auf ein Steckbrett gesetzt und da passiert genau dasselbe. Jetzt bin ich so ziemlich ausgelaugt und habe keine Ideen mehr und hoffe, daß jemand einen Tip für mich hat.
Danke schon mal im Voraus
Roger
;************************************************* *******************
; Netzteil für Kameras, 3V, 4,3V und 6V
;
; MCU: ATtiny11; interner Takt=1MHz
; Version: 1.2
; Entprellroutine im Timer-Interrupt
;
; - Taster-4,3V an PB2 (Pin7)
; - Taster-6V an PB1 (Pin6)
; - Schaltausgang 3V über PB0 (Pin5)
; - Schaltausgang 4,3V über PB3 (Pin2)
; - Schaltausgang 6V über PB4 (Pin3)
;
; - T-Bit fungiert als Merker für Taste entprellt und Zeitablauf
;************************************************* *******************
;
.nolist
.include "C:\Programme\AVR Tools\AvrAssembler2\Appnotes\tn11def.inc"
.list
;
; Konstanten
.equ key_port = PINB ; Eingabe
.equ t_43v = PB2 ; Taster-4,3V
.equ t_6v = PB1 ; Taster-6V
.equ t_maske = 0b00000110 ; für Tastenmaskierung
.equ schalt_port = PORTB ; Ausgabe
.equ a_3v = PB0 ; Schaltausgang für 3V
.equ LED_default = PB0 ; zugehörige LED
.equ a_43v = PB3 ; Schaltausgang für 4,3V
.equ a_6v = PB4 ; Schaltausgang für 6V
.equ ext_int = 0b00100000 ; Maskierung für PinChange Interrupt
.equ schlafen = 0b00100000 ; Sleep-Modus erlauben
.equ timerwert = 255-15 ; etwa 15ms
.equ zeitlimit = 3 ; 255 x15ms x3 ca.11sek, Zeit für Spannungswahl
.equ zeit_toggle = 3 ; 3x 15ms=45ms, Blinkintervall der 3V-LED
; leuchtet dauernd, wenn Zeit abgelaufen ist
; Register
.def Save = R2 ; wegen fehlendem Stack
.def key_ct0 = R3
.def key_ct1 = R4
.def key_state = R5
.def key_press = R6
.def mp = R16 ; Arbeitsregister
.def merker_t = R17 ; merken,ob Taste gedrückt wurde
.def zeit_L = R18 ; Gesamtzeit
.def zeit_H = R19
.def Blinker = R20 ; Zähler für Blinkintervall
;
; Interruptvektoren
.cseg
rjmp main ; Programmstart
reti ; externer Interrupt für Flankensteuerung
rjmp taste ; Pin change handler
rjmp timer ; Timer0 overflow handler
reti ; Analog Comparator handler
;
;************ Interrupt-Routinen *********************************
taste:
in Save,SREG ; Stack sichern
in merker_t,key_port ; Taste sichern, falls eine gedrückt wurde ;R1
andi merker_t, t_maske ; nur Tasten maskieren
ldi mp,0
out GIMSK,mp ; externe Interrupts abschalten; Neuwahl einer
; Spannung ist nur nach Neueinschalten möglich
out SREG,Save ; Stack wieder zurückschreiben
reti
;
timer:
in Save,SREG ; Stack sichern
tst merker_t ; wurde eine Taste gedrückt?
breq weiter ; nein, Entprellung überspringen
;
in mp, key_port ; Taste sichern, falls eine gedrückt wurde ;R1
andi mp, t_maske ; nur die Tasten maskieren
com mp ; low active
eor mp, key_state
and key_ct0, mp ; reset counter
and key_ct1, mp
com key_ct0 ; count
eor key_ct1, key_ct0
and mp, key_ct0 ; input AND last counterstate
and mp, key_ct1
eor key_state, mp ; toggle state
and mp, key_state ; 0-1-transition
or key_press, mp ; store key press detect
tst key_press ; Taste schon festgemacht?
breq weiter ; nein, noch eine Runde
com key_press
zeitende:
out SREG,Save
set ; T-Flag setzen und tschüß
rjmp ende
;
weiter:
dec Blinker ; Blinkzeit runterzählen
brne weiter_ ; wenn runtergezählt ist,
ldi Blinker,zeit_toggle ; dann neuladen und LED umschalten
sbis schalt_port,LED_default ; überspringe,wenn LED aus ist
rjmp led_aus
;
cbi schalt_port,LED_default ; LED einschalten
rjmp weiter_
;
led_aus:
sbi schalt_port,LED_default ; LED ausschalten
;
weiter_:
dec zeit_L ; Zeit runterzählen
brne raus ; wenn Nulldurchlauf,
dec zeit_H ; H-Teil runterzählen
breq zeitende ; Zeit abgelaufen
raus:
out SREG,Save ; Stack wieder zurückschreiben
ende:
ldi mp,1<<PCIF ; Flag für PinChange-Interrupt löschen,
out GIFR,mp ; da es auch auf die Schaltausgänge reagiert
reti
;
;************** Unterprogramme **************************************
;hier wird die gedrückte Taste ermittelt und die entsprechende Spannung
;eingeschaltet. Interrupts werden abgeschaltet
auswerten:
cli ; Interrupt löschen
ldi mp,0 ; Timer abschalten, wird nicht mehr benötigt
out TIMSK,mp
clt ; T-Flag löschen
clc ; zuerst C-Flag löschen
ror key_press ; Merker zwecks Prüfung 1.Taste 2x rollen
ror key_press
brcc u6v ; Bit1 nicht gesetzt? dann auf 6V testen
cbi schalt_port,a_43v ; 4,3V einschalten; L, da PNP-Transistor
sbi schalt_port,a_3v ; 3V-LED abschalten
rjmp ok ; ... und raus
;
u6v:
ror key_press ; Merker zwecks Prüfung 2.Taste eins weiter
brcc default ; Bit2 nicht gesetzt? dann 3V einschalten
cbi schalt_port,a_6v ; 6V einschalten; L, da PNP-Transistor
sbi schalt_port,a_3v ; 3V-LED abschalten
rjmp ok
default:
cbi schalt_port,a_3v ; 3V-LED einschalten; sonst nichts
ok:
rjmp loop ; ... und fertig
;
;************** Hauptprogramm ************************************
main:
; es ist kein Softwarestack vorhanden, daher keine Call-Befehle!!!
; Hardware initialisieren
sbi schalt_port,a_3v ; alle Ausgänge ausschalten
sbi schalt_port,a_43v ; H, da alle Transistoren PNP sind!!!
sbi schalt_port,a_6v
sbi DDRB,a_3v ; Pin2,3 und 5 als Ausgang
sbi DDRB,a_43v
sbi DDRB,a_6v
cbi DDRB,t_43v ; PB1 und PB2 als Tastereingänge setzen
cbi DDRB,t_6v
ldi mp,(1<<CS00)|(1<<CS02) ;Teiler=1024 (entspr.etwa 1kHz=1ms)
out TCCR0,mp
ldi mp,timerwert ;Timer vorladen
out TCNT0,mp
ldi mp,1<<TOIE0 ;Timerinterrupt einschalten
out TIMSK,mp
ldi mp,ext_int
out GIMSK,mp ; externe Interrupts ermöglichen
ldi mp,schlafen ; Schlafmodus und Interrupt
out MCUCR,mp ; und ins Controlregister schreiben
clr key_state ;sämtliche Merker der
clr key_press ;Entprellung löschen
clr key_ct0
dec key_ct0
mov key_ct1, key_ct0
ldi zeit_H,zeitlimit ; Gesamtzeit bis Aktivierung festlegen
cbi schalt_port,0 ; Blink-LED einschalten
ldi Blinker,zeit_toggle ; Togglezeit für LED-Blinken
ldi mp,1<<PCIF ; Flag für PinChange-Interrupt löschen,
out GIFR,mp ; da es auch auf die Schaltausgänge reagiert
sei ; Interrupt global freigeben
;
loop:
sleep ; CPU schlafen legen
brts auswerten ; eine Taste gedrückt; wenn ja,auswerten
rjmp loop ; ... und wieder schlafen ...
;
.exit ; Programmende
edit:
Habe noch den Schaltplan des Netzteils beigepackt.