Hallo, ich bin Umsteiger von MicroChip PICxxxx zu Atmel.
ich habe folgendes Problem:
ATMega8 mit 16 MHz Takt (Quarz)
ich möchte eine Routine (ASM) benutzen, die softwaremäßig mit einem
Taster einen Schalter, Taster simuliert.
Sourcecode siehe Anhang.
Das Programm soll beim 1. Tastendruck eine LED einschalten und beim
2. Tastendruck wieder ausschalten.
Das Programm funktioniert jedoch nicht so wie ich es will.
1. Tastendruck: LED ein, solange Taste gedrückt bleibt.
loslassen: LED aus (sollte "ein" sein bis zum 2. Tastendruck)
Schau Dir mal in dem uralten Beispiel im Anhang an, wie der Laser ein-
und aus geschaltet wird. Die Routine ist direkt hinter der
Tastenentprellung. Ich habe das ganze Programm angehängt, damit Du noch
diesen oder jenen AVR-spezifischen Tip finden kannst. ;-)
Nicht falsch verstehen, ich will Dich nicht belehren, ich kann dafür
nicht mit PICs umgehen... ;-)
...
Hallo Hannes,
erstmal schönen Dank für die prompte Beantwortung.
Ich habe deinen Source Code erstmal grob überflogen, genaue Analyse muß
ich noch nachvollziehen.
Bezüglich Belehrung: ich lasse mich gerne belehren (man kann nicht alles
wissen, manchmal steckt auch ein Denkfehler hinter den eigenen
Vorstellungen, denen man auch nach xfacher Überprüfung nicht findet)
Mein Problem ist aber warum nach dem 1. Drücken der Taste, das 2.
Drücken nicht erkannt wird:
;----------------
;--- Test keypress
; ---||||____________||||----------------||||_________||||-----
; PD1 ein PD1 aus
; Prellen Prellen
; Taste gedrückt Taste losgelassen
loop3:
ldi r16, 0x00 ; PORTB Eingang
out DDRB, r16
ldi r16, 0xFF ; PORTD Ausgang
out DDRD, r16
ldi r16, 0xFF ; PORTD alle LEDs On
out PORTD, r16
cbi PORTD,1
loop31: ; 1. mal gedrückt
sbic PINB,0
rjmp loop31
sbi PORTD,1
rcall delay ; Taste gedrückt
loop311:
sbis PINB,0
rjmp loop311
rcall delay ; Taste losgelassen
loop312: ; 2. mal gedrückt
sbic PINB,0
rjmp loop312
rcall delay ; Taste gedrückt
loop313:
sbis PINB,0
rjmp loop313
rcall delay ; Taste losgelassen
cbi PORTD,1
rjmp loop31
Dein Konzept gefällt mir nicht. Du hast keine Entprellung der Tasten
und Du vertrödelst Rechenzeit in Warteschleifen. Dieser Programmierstil
führt in eine Sackgasse.
Um Tasten sauber einzulesen und zu entprellen, nutzt man einen
Timer-Interrupt und ruft die Entprellroutine im Abstand von 4 bus 25 ms
zyklisch auf. Die Routine entprellt gleichzeitig bis zu 8 Taster oder
Schalter (8 Bit Breite der Register) und stellt für jeden
Taster/Schalter ein Zustandsbit (tas, bzw. Key_state) und ein Flag für
erneuten Tastendruck (tfl, bzw. Key_press) bereit. Und das alles mit nur
12 Takten alle 20 Millisekunden für 8 Tasten gleichzeitig... Wer dies
nicht nutzt, dem ist nicht zu helfen...
Schau Dir das Beispielprogramm noch mal genauer an. Es ist so klein und
überschaubar, dass ich sogar auf Mainloop-Jobs verzichtet habe und die
ganze Funktionalität in die Timer-ISR gelegt habe, die vom Timer alle 10
Millisekunden aufgerufen wird (für die Kritiker: Ja, es geht noch
besser, heute nutze ich die Timer auch eleganter und effizienter).
...
@Hannes
Es ist mir völlig klar, das das Programm nicht optimal ist (ist bei
einem Neueinsteiger, der sich erstmal mit der Materie beschäftigt auch
normal!)
Diese Routine soll auch nur dazu dienen, per Software-Breakpoint das
Programm an bestimmten, nicht kritischen Punkten, anzuhalten um
Portzustände auszulesen und dann per Tastendruck weiterlaufen zu lassen.
Da spielt verbratene Rechenzeit keine Rolle.
Meine Hauptfrage war auch, warum der 2. Tastendruck (ab loop312) nicht
erkannt wird! Es scheint so, als ob dieser Programmteil einfach
übersprungen wird.
>Ich habe das Problem gelöst.>Ich hatte den Stack-Pointer nicht initialisiert!
Wer hat das nicht schonmal vergessen ;-)
Ach ja, wenn Du mal auf das RAM zugreifen willst, dann
bitte nicht ab Adresse 0x00 sondern erst ab 0x0060 oder 0x0100
(bzw. siehe Datenblatt des jeweiligen Controllers).
Warum siehts Du dann im Datenblatt :-)
>(war bei PICxxxx auch nicht notwendig!)
Dafür hat man beim PIC seine Freude mit anderen Kleinigkeiten
(z.B. PCLATH vor einem "goto" manuell setzen, etc.)