Mit einem Timer problemlos möglich
Vielleicht kannst Du Dir dort ein paar Anregungen holen
http://www.mikrocontroller.net/forum/read-4-159103.html
Hallo zusammen,
ich habe vor kurzem angefangen im Assember AVM-Mikroprozessadoren zu programmieren. Jetzt bin ich vor ein für mich unlösbares Problem gestoßen.
Wie ist es möglich während einem laufenden Programm das einen Ausgang aktiviert, diesen in einem Gewissen Takt ein und auszuschalten. Das ganze soll ca. die Geschwindigkeit eines Andreaskreuzes am Bahnübergang haben.
Ich habe folgenden funktionierenden Code geschrieben:
;************************************************* *************
.include "tn2313def.inc" ; Definitionen für Attiny2313 *
;************************************************* *************
; Schrankensteuerung Modelleisenbahn
; Interner RC-Oszi, 1MHz, Tiny 45
; Stand: 03.03.2006
;
; Software um eine Bahnschranke bei durchfahren der Lichtschranke durch
; den Modellzug zu schließen und nach vollständigem Austritt des Zuges
; incl. dessen Anhänger aus dem Schrankenbereich wieder zu öffnen
;
; PORTB
; PB0: IN P Lichtschranke 1
; PB1: IN P Lichtschranke 2
; PB2: OUT - Schranke oeffnen (High aktiv)
; PB3: OUT - Schranke schließen (High aktiv)
; PB4: OUT - Andreaskreuz
; PB5: OUT - Andreaskreuz
; merker1 Durchfahrene Lichtschranke 1
; merker2 Durvhfahrene Lichtschranke 2
; Register Definition
; General Purpose
.def a = r16 ;Register 16 als a definieren
.def b = r17 ;Register 17 als b definieren
; Interrupt
; .def i_a = r19 ;Wird nicht benötigt
; .def sSREG = r1
.DEF merker1 = r21 ;Register 21 wird als merker1 definiert
.DEF merker2 = r22 ;Register 22 wird als merker2 definiert
RESET: ldi a, low(RAMEND) ;Lade in a low(RAMEND)
out SPL, a ;Gebe a im SPL aus
;IO-Init
ldi a, 0b11111111 ;Lade in a die Hex-Zahl
out PORTB, a ;Gebe a an PORTB aus / initialisierung des Ports
ldi a, 0b00111100 ;Lade in a Hex-Zahl
out DDRB, a ;Gebe a an DDRB aus / 0==Eingang; 1==Ausgang
cbi PORTB,2 ;Setze Ausgang PB,2 auf Low
cbi PORTB,3 ;Setze Ausgang PB,3 auf Low
cbi PORTB,4 ;Setze Ausgang PB,4 auf Low
cbi PORTB,5 ;Setze Ausgang PB,5 auf Low
rjmp oeffnen ;Springe zu oeffnen
start: CLR merker1 ;Lade die Zahl 0 in merker1
CLR merker2 ;Lade die Zahl 0 in merker2
ls1: sbic PINB, 0
rjmp ls2 ;Wenn PB0!=0 springe zu ls2
CPI merker1,1
BREQ ls11 ;Wenn merker1==1 springe zu ls11
CPI merker2,1
BREQ ls11 ;Wenn merker2==1 springe zu ls11
ldi merker1 ,1 ;Setze merker1 auf High (1)
ldi a, 20 ;Pause von 20*10ms
rcall WAIT_M ;um beim Steckerziehen eine schließung zu vermeiden
sbi PORTB,3 ;Setze Ausgang PB3 auf High /
;Anfang Schranke schließen
sbi PORTB,4 ;Andreaskreuz aktvieren
sbi PORTB,5
ldi a, 50
rcall WAIT_M ;Pause von 50*10ms
cbi portb,3 ;Setze Ausgang PB3 auf Low /
;Ende Schranke schließen
ls11: CPI merker2,1
BREQ warten ;Wenn merker2==1 springe zu warten
ls2: sbic PINB, 1
rjmp ls1 ;Wenn PB1!=0 springe zu ls1
CPI merker2,1
BREQ ls22 ;Wenn merker2==1 springe zu ls22
CPI merker1,1
BREQ ls22 ;Wenn merker1==1 springe zu ls22
ldi merker2, 1 ;Setze merker2 auf High (1)
ldi a, 20 ;Pause von 20*10ms
rcall WAIT_M ;um beim Steckerziehen eine schließung zu vermeiden
sbi PORTB,3 ;Setze Ausgang PB3 auf High /
;Anfang Schranke schließen
sbi PORTB,4 ;Andreaskreuz aktvieren
sbi PORTB,5
ldi a, 50
rcall WAIT_M ;Pause von 50*10ms
cbi portb,3 ;Setze Ausgang PB3 auf Low /
;Ende Schranke schließen
ls22: CPI merker1,0
BREQ ls1 ;Wenn merker1==0 springe zu ls1
;Die folgende warten-Schleife wird mehrmals durchlaufen
;um die Abstände zwischen den Anhängern zu überbrücken
warten: ldi R25, 0b01111111 ;Lade in das Register25 die Hex Zahl (dez:127) /
;Ein Takt benötigt 1ys
warten0: sbis PINB, 0
rjmp warten ;Wenn PB0==1 springe zu warten
sbis PINB, 1
rjmp warten ;Wenn PB1==1 springe zu warten
ldi a, 1
rcall WAIT_M ;Pause von 1*10ms
DEC R25 ;Decrementierung des Wertes im Register 25 um 1
BRNE warten0 ;Wenn die Zahl im R25!=0 ist springe zu warten0
oeffnen: sbi portb,2 ;Setze Ausgang PB2 auf High / Anfang Schranke öffnen
cbi PORTB,4 ;Andreaskreuz deaktvieren
cbi PORTB,5
ldi a, 50
rcall WAIT_M ;Pause von 50*10ms
cbi portb,2 ;Setze Ausgang PB2 auf Low / Ende Schranke öffnen
rjmp start ;Springe zu start
;Zeitschleife
;Übergabe: a - Länge= 10ms * a (a:1..255)
WAIT_M:
WM_0: ldi b, 0xFF
WM_1: lpm
lpm
lpm
lpm
lpm
lpm
lpm
lpm
lpm
lpm
lpm
lpm
lpm
lpm
wdr
wdr
dec b
brne WM_1
dec a
brne WM_0
ret
Kann mir jemand helfen wie ich den PB4 und PB5 nach der aktivierung zum blinken bringe und nach der deaktivierung durch das Programm wieder zum ausschalten??
Viele liebe Gruesse
Sebastian Frei
Mit einem Timer problemlos möglich
Vielleicht kannst Du Dir dort ein paar Anregungen holen
http://www.mikrocontroller.net/forum/read-4-159103.html
Vielen Dank für deine Antwort.
So wie dieser verlinkte Timer funktioniert konnte ich im AVM-Studio simulieren. Das wäre auch genau das was ich bräuchte, nur leider funktioniert das Programm so nicht für den Attiny2313.
Dort bringt er eine Fehlermeldung beim Stack. Da habe ich einfach den SPH rausgelöscht, da der bei dem controller nicht zur Verfügung steht. Aber der Timer läuft dann nur einmal durch und hängt dann.
An was liegt das? Wie kann ich das problem lösen. Ich bröuchte also nur einen Timer anlegen und dieser bei Überlauf (ca. alle 2 Sekunden) ins verlinkte programm springen. Wer kann mir weiterhelfen??
Gruss Sebastian
Sebastian
>Aber der Timer läuft dann nur einmal durch und hängt dann.
vielleicht hast Du nur den "reti" Befehl vergessen ?
Bei solchen Problemchen ist es immer besser, wenn Du uns den kompletten Programm-Code zur Verfügung stellst.
Sonst "orakeln" wir nur
Trotzdem, großes LOB an Dich, denn Du programmierst sehr übersichtlich und nachvollziehbar.
Bernhard
Hallo Bernhard,
vielen Dank für die schnelle Rückantwort. Ich habe das Hauptprogramm herausgelöscht um mich auf das wesentliche zu konzentrieren. Es geht also nur um den Timer. Der läuft auch einmal durch, aber dann glaube ich fast, dass ihm der Stack fehlt um wieder zurückzuspringen.
Ehrlich gesagt habe ich noch nicht viel Ahnung in sachen Mikrocontroller, aber ich bin fleißig dabei mir das ganze anzueignen. Ich bin dabei ein Buch durchzulesen, aber leider verstehe ich noch nicht alles. Na ja dieses Semester werde ich noch microcontroller bekommen.
Na ja egal. Kannst du mir bitte helfen, damit ich das ganze für den Attiny 2313 zum laufen bekomme. Wäre echt nett.
Bis dann und viele liebe Gruesse
Sebastian
Der Quellcode ist im Anhang ersichtlich
Schickst du auch mal 40€ vorbei für's WinRAR?
Disclaimer: none. Sue me.
Sorry,
im Anhang als Zip-Datei.
Gruesse
Sebastian
Das sieht doch ok aus, bis auf die Initialisierung des SP, denn SL hat nach dem Reset nen zufälligen Wert.
Disclaimer: none. Sue me.
@Sebastian
Der Fehler lag bei den Interrupt-Vektoren,
ich habe sie aus dem Datenblatt herauskopiert
und bei Dir eingefügt.
Der µC sprang auf die falsche Adresse und bekam sofort ein reti
Immer aufpassen, wenn Du für einen anderen µC die Software anpasst,
nicht nur die include "2313def.inc" ändern, Die Vektoren sin leider meistens unterschiedlich.
Ein paar Vereinfachungen habe ich auch gleich mit vorgenommen,
denn mit Resourcen muss man sehr geizen
Die Interrupt-Routine habe ich Dir auch gleich vernünftig vorbereitet,
denn alle Register müssen gesichert werden die beim Interrupt benötigt werden, sonst gibt es unangenehme Fehlfunktionen des Programmes und man(n) sucht stundenlang.
Viel Spaß
Bernhard
kleine Änderung in der Timer-Routine
; Timerwert neu einstellen
ldi temp,timerwert
mov tsw,temp
out tcnt0,tsw
bitte ändern in:
; Timerwert neu einstellen
out tcnt0,tsw
Lesezeichen