Hallo zusammen,
ich versuche mich gerade, in das Thema "Timer" einzuarbeiten. Dazu nutze
ich das das AVR Tutorial. Als Controller nutze ich einen Tiny2313 und
habe das Programm in Assembler geschrieben. Ich habe soweit alles
versucht, an den Tiny2313 anzupassen. Aber leider ohne Erfolg...
So wie ich es jetzt habe, leuchten bei mir die LEDs dauerhaft. Kleine
Info zur Hardware: Ich nutze das STK 500. Die Frequenz habe ich wie im
Programmbeispiel im Tutorial auf 4 MHz eingestellt.
Vielleicht kann mal jemand einen Blick darüber werfer, warum das nicht
funktioniert. Bin für jede Hilfe dankbar ! :)
Möchte dann gerne mit dem Programm ein bißchen das Thema Timer kennen
lernen und evtl. mal die Signale eines RC Empfänger auswerten. Daher der
Name PPM-Test.
Viele Grüße
Sven
So, das "Problem" hat sich gelöst... und ich habe wieder einen Teil
verstanden. Ich hatte den Vorverteiler auf 1 stehen. Also viel zu
schnell. Da kommt das Auge nicht mit. Aus diesem Fehler habe ich auf
jeden Fall was gelernt. ;)
Irgendwas muß mit den Vorbereitungen zum 2313 nicht stimmen.
3 LED am Port (B0 bis B2) leuchten dauerhaft.
Was mache ich nur verkehrt!
Worin erkennt das Interrupt, daß es nach dem Timerdurchlauf
von 256 nach timer: springen soll.
Bei Bascom gab es
Config Timer0 = Timer,Prescale = 1024
On Timer0 timer
Enable Timer0
Grüße
Rolf
Hi
>Was mache ich nur verkehrt!> .DEF akku = r16 ; Arbeitsregister r16 in akku benannt>timer: ldi r16,100
Entweder du benennst r16 mit akku, dann hat r16 in deinem Programm
nichts zu suchen. Oder du bleibst bei r16.
>;Arbeitsbeginn> ldi akku,0b00000111 ; Bitmuster 0000 0111> out PORTB,akku ; Pb0 - Pb2 = High>timer: ldi r16,100>....
Rate mal was dein ATTiny nach dem 'out PortB,akku' macht.
Außerdem:
-Kein SREG im Interrupt gesichert
-Warten im Interrupt
MfG Spess
>> ldi akku,0b00000111 ; Bitmuster 0000 0111>> out PORTB,akku ; Pb0 - Pb2 = High>>>timer: ldi r16,100>>....>> Rate mal was dein ATTiny nach dem 'out PortB,akku' macht.
@Rolf
Ich denke der Hinweis war etwas zu subtil, vor allen Dingen wenn man ihn
im Zusammenhang mit dem vorhergehenden Hinweis (Akku/R16) sieht.
Daher etwas konkreter:
Wo ist deine Hauptschleife?
JEDES Programm braucht eine Hauptschleife, in der der Programmfluss
verbleibt, solange der µC unter Strom steht!
Es ist das, was in BASCOM das
...
do
... Programmlogik
loop
war.
Hallo Leute,
erst mal meinen Dank für Eure Infos!
Ich habe gelesen und nochmals gelesen über Timer0 vom 2313,
und anschließendes Interrupt.
Das Register TCCR0 hab ich voll im Griff..eingestellt auf
Prescale 1024.
Das Zählregister TCNT0 auch überschaubar..wird inkrementiert bei Hoch-
laufen, das macht es von alleine..also nicht wichtig.
Das Überlaufregister TIFR..Bit0=TOVO wird gesetzt bei Überlauf.
Das Register TIMSK muß Bit0 = TOIE0 gesetzt werden. Dieses hat
außer I=sei höchste Priorität.
Wie aus den Bild zu sehen, habe ich alles korrekt vorgegeben.
(hoffentlich gut erkennbar)
3 Leds habe ich zuvor an PORTB/Pin0 - 2 dunkel gesetzt.
Und es tut sich nichts, sie bleiben dunkel; über die ISR "timer"
müßten sie alle 3 zum leuchten kommen, oder?
An der Hardware kann es nicht liegen, denn sie lassen sich ohne
Timer problemlos steuern.
Jetzt sind die Experten gefragt!
Grüße
Rolf
Im Buch steht:
TOVO=1 (Überlauf)und TOIE0=1 und I=1 (sei)wird der Timer0 Interrupt
ausgelöst.
Bitte Programmtext immer als Text und nicht als Bild.
Unterschied: Aus einem Text kann ich mir mit Cut&Paste Teile
ausschneiden, auf die ich Antworten möchte. Bei einem Bild kann ich das
nicht.
Weiterer Unterschied: Bei einem Text hängst DU einfach dein Programmfile
als Attachment an, bei einem Bild hast du mehr Arbeit.
Du hast 8 LED am Port B hängen?
Dann ist es immer eine gute Idee, wenn du nicht alle 8 entweder auf 0
oder auf 1 stellst, sondern erst mal zb abwechselnd auf 0 und 1
ldi led,0b10101010
auf die Art brennen unabhängig davon, ob deine LED jetzt alle nach Masse
oder alle nach Vcc verschaltet sind, immer auf jeden Fall 4 LED
Hi
Nimm bitte deine ASM-Datei als Anhang.
>Und es tut sich nichts, sie bleiben dunkel; über die ISR "timer">müßten sie alle 3 zum leuchten kommen, oder?
Kommt darauf an, wie die Leds angeschlossen sind. Der erste Overflow
kommt nach etwa einer viertel Sekunde. Danach passiert nichts mehr.
>Das Register TIMSK muß Bit0 = TOIE0 gesetzt werden.
In meinem Datenblatt ist TOIE0 Bit1. Deshalb ist
ldi akku,0b00000001 auch Unsinn. Mit
ldi akku,1<<TOIE0 passiert das nicht.
MfG Spess
> Jetzt sind die Experten gefragt!
Solche Dinge lassen sich aber auch noch im Simulator wunderbar testen.
Dort kann man dann auch in der Registerübersicht wunderbar sehen, welche
Bits man wirklich gesetzt hat und wie der Timer hochzählt.
Hinweis: Für den Simulator den Prescaler auf 1 setzen, sonst tippt man
sich die Fingerkuppen wund.
> ldi akku,0b00000111 ; Bitmuster 0000 0111> out PORTB,akku ; Pb0 - Pb2 = High
Das macht er und dann macht er hier weiter (ldi r16,100) und schaltet
Sie wieder ein paar 100µS später wieder aus
>>timer: ldi r16,100>warte: dec r16> brne warte> ldi r16,0b00000001> out PORTB,r16> reti
mach mal ne Endlosschleife dazwischen damit er nicht in den Handler
reinläuft (loop: rjmp loop):
ldi akku,0b00000111 ; Bitmuster 0000 0111
out PORTB,akku ; Pb0 - Pb2 = High
loop: rjmp loop
timer: ldi r16,100
warte: dec r16
brne warte
ldi r16,0b00000001
out PORTB,r16
reti
Hallo Spess,
Erfolg....jetzt leuchten die 3 Leds an Pb0 bis PB2 nach Änderung
wie in Deinem Vorschlag.
;Timer0 und Interrupt voreinstellen
ldi akku, 0b00000101 ;Prescale = 1024
out TCCR0, akku ;akku in Steuerreg. TCCR0
ldi akku,(1<<TOIE0) ; Register TIMSK (Bit0=1)
out TIMSK, akku ; Interrupt frei gegeben
sei ; I=sei (Inter. frei)
evtl. muß ich bei Prescale auch eine Änderung durchführen,
denn das macht mich dann mit akku, xxxxxx auch stutzig!
Wie soll ich das mit 0101 vorgeben =1024
Die Leds hängen an Plus über NPN gesteuert, d.h. High=LED Pin=1
Allen Anderen antworte ich morgen!
grüße Rolf
noch was: muß die Anweisung 1<<TOIE0 in Klammern?
Hi
>evtl. muß ich bei Prescale auch eine Änderung durchführen,>denn das macht mich dann mit akku, xxxxxx auch stutzig!>Wie soll ich das mit 0101 vorgeben =1024
Das Bitmuster stimmt dort schon. Allerdings ist auch hier ein
ldi r16, 1<<CS2|1<<CS0
informativer.
>noch was: muß die Anweisung 1<<TOIE0 in Klammern?
Nicht unbedingt. Aber stören tut es auch auch nicht.
MfG Spess
Nur mal so als Anmerkung:
spess53 schrieb:> ldi r16, 1<<CS2|1<<CS0
Das was Spess hier schreibt (Bitmanipulation) steht hier
http://www.mikrocontroller.net/articles/Bitmanipulation
sehr gut beschrieben.
Welche Bits sich genau hinter CS2, CS0 oder auch TOIE0 verbergen findest
du in der "tn2313def.inc" beschrieben.
Gruß Steffen
Hi
>Nur mal so als Anmerkung:>....
Das Problem ist das die meisten ,die hier mit Assemblerproblemen
auftauchen, blutige Anfänger sind. Da liegt das Interesse erst mal
darin, ein meist recht begrenztes, Ziel irgendwie zu erreichen. Die Form
ist recht egal. An Lesbarkeit, Wartbarkeit oder gar Wiederverwendbarkeit
des Codes wird kein Gedanke verschwendet, zumal die Mittel dazu
(AVR-Assembler->Directives/Expressions oder AVR-Assembler->Preprocessor
und anderes) weitestgehend unbekannt sind.
MfG Spess
Hallo Spess und Seffen,
danke für Eure Antwort noch zu später Stunde.
Frage: was ist das für ein Längsstrich zwischen 1<<CS2 und 1<<CS0,
kann sowas auf dem Laptop nicht finden..einen / ja!
Zu Karl Heinz:
ok, Quelldatei als Text und nicht Bild.
3 Leds liegen gegen Plus über 3 NPN Trans. an PB0-PB2
Der erste Durchbruch ist geschafft, nun geht es ins Eingemachte.
Grüße
Rolf
Hi
>Frage: was ist das für ein Längsstrich zwischen 1<<CS2 und 1<<CS0,>kann sowas auf dem Laptop nicht finden..einen / ja!
Sollte auch auf deinem Laptop mit AltGR + <>-Taste (links neben Y)
erreichbar sein.
MfG Spess
Rolf Hegewald schrieb:> Frage: was ist das für ein Längsstrich zwischen 1<<CS2 und 1<<CS0,
Der befindet sich normalerweise (deutsche Tastatur) auf der Taste mit <
und >. Erreichbar über "Alt Gr" zusammen mit <. Wird in der Regel durch
einen unterbrochenen senkrechten Strich dargestellt.
Volkmar
|| ok, hat geklappt!
Nun steh ich vor einem Wahnsinns-Projekt, das ich in Hamburg
im Miniatur-Wunderland (Modelleisenbahn) gesehen habe und im Jahr
2011 umgesetzt. Es handelt sich um einen Contenerkran der Fa.
Brawa mit 2 Motoren.
1. Motor AUF/AB
2. Motor LINKS/RECHTS
Das alles läuft mit einem PIC in Pic-Assembler. Mein Wunsch war es,
mit Atmel, aber nicht mit Bascom umzusetzen, sondern wieder Assembler.
Die Motoren zu steuern, ist nicht das Problem, dagegen Pausenzeiten
in verschiedenen Zeitabständen schon.
Mit den Pic habe ich 3 Register geladen und inkrementiert, sehr auf-
wendig. Also habe ich mich mit den Timer0 angetan.
Das Blockschema sieht so aus:
1. Motor AUF=EIN
2. Pause1 ;ca. 5 Sec.
3. Motor AUF=AUS
4. Pause1
5. Motor LINKS=EIN
6. Pause2 ;ca. 20 Sec.
7. Motor LINKS=AUS
8. Pause1
9. Motor AB=EIN
10. Abfrage über Lichtschranke
usw. dann geht es wieder aufwärts, rechts und ab.
Es kommen also zwei Zeiten in Betracht. Eine mit 5 Sec.
die andere mit 20 Sec.
Nun habe ich schon in der ISR herumgefummelt...aber!
;Timer0 und Interrupt voreinstellen
ldi akku, 0b00000101 ;Prescale = 1024
out TCCR0, akku ;akku in Steuerreg. TCCR0
ldi akku,(1<<TOIE0) ; Register TIMSK (Bit0=1)
out TIMSK, akku ; Interrupt frei gegeben
sei ; I=sei (Inter. frei)
;Arbeitsbeginn
loop: rjmp loop
timer: ldi leds,0b00000001
out PORTB,leds ;Register r17
ldi akku,0b00000111
dec akku
brne gehe ;Sprung, wenn akku nicht Null
ldi leds,0b00000100
out PORTB,leds
ldi akku,0b00000111
dec akku
brne gehe
gehe: reti
Was meint Ihr, soll ich bei der alten Register-Methode bleiben,
oder mich durchkämpfen.
Grüße
Rolf
Rolf Hegewald schrieb:> Was meint Ihr, soll ich bei der alten Register-Methode bleiben,> oder mich durchkämpfen.>
Auf jeden Fall: Timer
Timer sind deine Arbeitspferde. Ohne sie sind komplexere Programme nicht
sinnvoll machbar.
> Nun habe ich schon in der ISR herumgefummelt...aber!
Aber was?
>> ;Timer0 und Interrupt voreinstellen> ldi akku, 0b00000101 ;Prescale = 1024> out TCCR0, akku ;akku in Steuerreg. TCCR0> ldi akku,(1<<TOIE0) ; Register TIMSK (Bit0=1)> out TIMSK, akku ; Interrupt frei gegeben> sei ; I=sei (Inter. frei)>> ;Arbeitsbeginn>> loop: rjmp loop>>> timer: ldi leds,0b00000001> out PORTB,leds ;Register r17> ldi akku,0b00000111> dec akku
was machst du da?
Wenn du vorher 7 in den Akku lädst
(warum schreibst du dann nicht auch einfach
ldi akku, 7
ist doch viel einfacher zu lesen. Ob dezimal oder hexadezimal oder
binäre Schreibweise benutzt wird, hängt davon ab, wofür die Zahl steht.
Man wählt immer die Schreibweise, die in der gegebenen Situation die
natürlichste ist. Du willst etwas zählen, also wird dezimal die
natürliche Schreibweise sein, denn du denkst dezimal)
und diese 7 dann um 1 runterzählst, dann steht 6 im akku. Immer. Denn
bei jedem Aufruf der Timer-ISR lädst du ja wieder 7 in den Akku.
> brne gehe ;Sprung, wenn akku nicht Null
das kann daher nie 0 sein
> ldi leds,0b00000100> out PORTB,leds> ldi akku,0b00000111> dec akku> brne gehe> gehe: reti
Du hast das Prinzip noch nicht verstanden.
In der ISR realisierst du die Dinge, die nach einer gewissen
Zeiteinheit(!) getan werden müssen. Das AUfsetzen bzw. Einstellen der
Umgebung machst du ausserhalb. Die ISR ist wie das Ticken einer Uhr und
bei jedem Tick siehst du nach bzw. bestimmst du, was genau jetzt, zu
diesem Zeitpunkt, bei diesem Tick der Uhr, getan werden muss.
Du denkst noch in Warteschleifen! Und genau das ist der falsche Ansatz.
Du musst in zeitlichen Ereignissen denken.
Tick ... 1 Sekunde vergangen, was gibt es jetzt zu tun?
Tick ... wieder 1 Sekunde vergangen, ist jetzt etwas zu tun?
Tick ... die nächste Sekunde ist abgelaufen, ich könnte mal den
Motor einschalten
Tick ... 1 Sekunde aufs Konto gutschreiben, ansonsten gibt es nichts
Tick ... noch eine Sekunde. Heissa, ich wollte doch nach 2 Sekunden
den Motor wieder ausschalten! Vor 2 Ticks hab ich ihn ein-
geschaltet, also ist jetzt der Zeitpunkt, ihn auszuschalten
Tick ...
....
Grundsätzlich wirst du Ticks zählen müssen, weil du ja längere Zeiten
als 1 Sekunde brauchst. Nehmen wir mal an, dass der Tick jede Sekunde
kommt (du also genau alle 1 Sekunde einen Aufruf der ISR hast).
Was musst du tun?
du zählst 1 zu deiner Anzahl an Ticks dazu, weil du ja längere
Zeiteinheiten als 1 Sekunde haben willst. Wenn du 20 derartige
Ticks abzählst, dann sind 20 Sekunden vergangen, wenn du bei
20 angelangt bist (du kannst natürlich auch von 20 runterzählen
und wenn du bei 0 bist, sind 20 Sekunden vergangen. Kommt aufs
gleiche raus. Runterzählen ist meist einfacher)
Solange du deine Sekunden nicht erreicht hast, gibt es nichts
zu tun -> verlassen der ISR
Sind die Sekunden erreicht, dann musst du zb etwas schalten
zb LED ein oder LED aus. Dazu wirst du irgendeinen Mechanismus
brauchen, der dir sagt ob jetzt ein oder ausgeschaltet werden
soll. Du kannst zb das Portregister befragen ob zur Zeit
eingeschaltet ist und dann daraus deine Schlüsse ziehen.
Wie auch immer, auf jeden Fall muss dann deine Tickzählerei
wieder von vorne beginnen. D.h. du setzt den Tickzähler wieder
zurück (auf 0 wenn du ihn erhöhst, auf zb 20 wenn du mit der
Methode runterzählen arbeitest)
Und eines solltest du auf jeden Fall machen:
In der ISR wird auf jeden Fall das Status-Register SREG gesichert! Das
ist lebenswichtig, weil du nie vorhersehen kannst, welche andere
Anweisungssequenz in der Hauptschleife durch die ISR unterbrochen wird.
Zur Zeit ist deine Hauptschleife noch leer
loop: rjmp loop
aber das wird nicht immer so bleiben!
Rolf Hegewald schrieb:> Was meint Ihr, soll ich bei der alten Register-Methode bleiben,> oder mich durchkämpfen.
Es ist einfacher als Du jetzt denkst...
Lies Dich mal hier durch:
http://www.hanneslux.de/avr/index.html
Ist zwar alles schon etwas älter, hilft Dir aber sicherlich beim
Verstehen.
Ohne Timer komme ich eigentlich gar nicht zurecht...
...
Hallo,
meinen Dank besonders an Karl Heinz für seine vielen
aufklärenden Worte. Wenn ich das mit dem Tick richtig verstanden habe,
würde bei mir eine Zeit von: (ich gehe mal von 1MHz Systemtakt aus)
1 ys x 1024 = 1,024 ms x 256 = 262,144 ms etwa 0,26 Sec.
Auf die Genauigkeit kommt es jetzt nicht drauf an, nur vom Prinziep.
Würde ich ein Register in der ISR auf $0F setzen und zu Null runter
zählen, hätte ich ein Ergebnis von 0,26 x 15 = 3,9 Sec.
Was habe ich nun in der Zwischenzeit gemacht..also wieder gelesen!
Und dazu ist mir das von Hannes eine große Hilfe gewesen.
D.h. ich muß den Tick EIN und Ausschalten können, bzw. eine loop
Arbeitsschleife aufbauen.
Das Ganze sieht jetzt so aus:
.INCLUDE "tn2313def.inc" ; Deklarationen für Tiny2313
.EQU takt = 1000000 ; Systemtakt 1 MHz
.EQU laufein = 1<<CS02|1<<CS00
.EQU laufaus = 0<<CS02|0<<CS00
.DEF flashein = r7
.DEF flashaus = r8
.DEF akku = r16 ; Arbeitsregister r16 in akku benannt
.DEF warte4 = r17 ; für Pausenzeit ca. 4 Sec.
.DEF warte15 = r18 ;für Pausenzeit ca. 15 Sec.
.ORG 0x0000
rjmp start ;Sprung zu Vorbereitung
.ORG OVF0addr ;Timer0 Überlauf-Einsprung
rjmp timer ;Sprung zur ISR
start: hier werden nur PortB als Ausg. gesetzt.
Timer 0 voreinstellen
;Timer0 und Interrupt voreinstellen
ldi akku,(1<<TOIE0) ; Register TIMSK (Bit0=1)
out timsk,akku ; Interrupt frei gegeben
sei ; I=sei (Inter. frei)
;Timer0 EIN-AUSschalten:
ldi akku,laufein ;Bitm. 0101=1024
out flashein,akku ;in r7 Inhalt von akku
ldi akku,laufaus ;Bitm. 0000=Timer Stopp
out flashaus,akku ;in r8 Inhalt von akku
; out TCCR0,flashein = Timer EIN / out TCCR0,flashaus = Timer AUS
Jetzt beginnt der eigentliche Arbeitsbeginn:
loop: rcall pause4 ;Pause 4 Sec.
rcall ein ;Motor linksauf-EIN
rcall pause4 ;Pause 4 Sec.
rcall halt ;Motor linksauf-HALT
rjmp loop
hier die Unterpr.
pause4:
warte4 $0F ;Bitmuster 0b00001111 in r17
out TCCR0,flashein ;Timer = EIN
ende4: out TCCR0,flashaus ;Timer = HALT
ret
ein:
ldi akku,$02 ; r16 = 02
out PORTB,akku
ret
halt:
ldi akku,$00
out PORTB,akku
ret
und zum Schluß die ISR (und hier bin ich mir mit den brne noch
etwas unsicher)
timer:
dec warte4
brne laufe
laufe: rjmp ende4
reti
.EXIT
mit der Sreg muß ich mich noch antun.
Ganz schön komplex..das Ganze, aber da blickt Ihr doch durch, oder?
Aber ich komme aus einem Fehler nicht raus, der so aussieht.
D:\Tiny2313\krantest2.asm(64): error: syntax error, unexpected INTEGER,
expecting ':'
Also wie gesagt, es läuft noch nicht!
Grüße erst mal
Rolf
Hi
>Ganz schön komplex..das Ganze
Ich habe Assemblerprogramme, die sind 200x größer. Da fängt es langsam
an komplex zu werden.
>aber da blickt Ihr doch durch, oder?Du must durchblicken.
Fangen wir mal an:
-Kein Stack initialisiert
-Kein SREG gesichert
-Sprung aus der Interruptroutine
> dec warte4> brne laufe>laufe: rjmp ende4
Unsinn. Egal ob Null oder nicht kommt das Programm zu 'laufe'.
> warte4 $0F ;Bitmuster 0b00001111 in r17
Was soll das sein?
>out flashein,akku ;in r7 Inhalt von akku
heißt: out r7,r16 und das ist falsch. Richtig mov r7,r16
Das ist das, was ich auf die Schnelle gefunden habe. Aber da sind mit
Sicherheit noch andere Eier vesteckt.
MfG Spess
Rolf Hegewald schrieb:> D.h. ich muß den Tick EIN und Ausschalten können, bzw. eine loop> Arbeitsschleife aufbauen.
Damit wirst Du nicht viel weiter kommen. Schau Dir mal meine
Feuerwerks-Zünduhr an, da werden zu bestimmten Terminen bestimmte
Aktionen ausgeführt:
http://www.hanneslux.de/avr/zuenduhr/index.htmlhttp://www.hanneslux.de/avr/zuenduhr/ZndUhr01.asm
Nur mit Zeit gesteuert wird Dein Kran sich aber verhedern, da würde ich
auch noch mit Endschaltern (Lichtschranken) arbeiten, die signalisieren,
dass eine bestimmte Position erreicht ist.
Dann würde ich mir ein "Datensatzformat" ausdenken, z.B. 2 Bytes für die
Verzögerung bis zum nächsten Schritt, 1 Byte für das Bitmuster, was zu
tun ist, 1 Byte für das Bitmuster, welcher Endschalter die Sache
vorzeitig beendet. Diese Datensätze kommen dann ins EEPROM des AVRs und
können jederzeit nach Bedarf berändert werden, ohne das Programm (im
Flash) verändern zu müssen.
Mit einem (frei durchlaufenden ) Timer generiert man nun einen Basistakt
von z.B. 10ms. In diesem findet erstmal die Entprellung der
Endschaltereingänge statt, sowie auch das Herunterzählen der gerade
laufenden Zeitverzögerung. Wird die laufende Verzögerung 0, dann wird
ein Merker (Flag, Semaphore, Bitvariable,...) gesetzt, der dem
Hauptprogramm mitteilt, dass der laufende Arbeitsgang zu Ende ist.
Das Hauptprogramm prüft nun dieses "FertigMaisTeer-Flag" und macht
Folgendes, falls es gesetzt war:
FertigMaisTeer-Flag löschen (Jobauftrag entwerten, Job ist ja in Arbeit)
Nächsten Datensatz aus EEP holen,
Wartezeit-Zähler auf neuen Startwert setzen
Ausgangs-Bitmuster ausgeben (also Schalthandlung ausführen)
Eingangs-Bitmaske aktualisieren (welcher Eingang darf Abbruch auslösen)
Endschalter-Flags löschen (alte Auslösungen entwerten)
Weiterhin prüft die Hauptschleife die Endschalter-Flags und setzt bei
Betätigung einfach mal den FertigMaisTeer-Merker, um den Arbeitstakt
vorzeitig zu beenden.
Vereinbart man, dass 0xFFFF (leeres EEPROM) als Verzögerungszeit
ungültig ist und stattdessen als Rücksetzen des Arbeitstaktzählers auf
den Anfang interpretiert wird, so kann man das Bewegungsprogramm als
endlosen Ring ausführen.
Baut man noch Routinen zum Update des Bewegungsprogramms per RS232 ein,
dann kan das Bewegungsprogramm jederzeit von einem PC (auch über
USB-RS232-Wandler) ersetzt werden, mindestens hunderttausend mal.
Schreibt man sich für den PC noch ein Programm (GUI?) zum Editieren des
Bewegungsprogramms und Verwalten eines Archives mit Bewegungsprogrammen
sowie den Routinen zum Senden eines Bewegungsprogramms an den AVR der
Kransteuerung, dann kann man den Kran recht flexibel zappeln lassen.
Baut man in die Kommunikation zwischen PC und AVR neben den Kommandos
zum EEP-Update noch ein paar Kommandos zur Direktsteuerung ein, dann
kann man das Ding auch mal per Mausklick steuern. Ist mE kreativer, als
nur ein Detail vom MiWuLa kopieren zu wollen.
So, nun mach' was Du willst, aber mach' was (oder auch nicht...)
...
Hi
Noch etwas:
Der Timer0 besitzt TCCR0A und TCCR0B, aber kein TCCR0. Der Assembler
akzeptiert TCCR0 nur weil er diese Bezeichnung nach TCC0B umleitet. Nimm
bitte die richtigen Registerbezeichnungen.
MfG Spess
Ich seh das wie ihr.
Und ich bin mir ziemlich sicher, dass die Jungs im MiWuLa da Endschalter
(zb in Form von Gabellichtschranken) zur Fahrkontrolle eingebaut haben.
Die können es sich doch gar nicht leisten, dass sich der Kran jeden
2.ten Tag verheddert. Das Zeug muss laufen!
Ich bin eigentlich nur deswegen auf den Timer aufgesprungen, weil Timer
nun mal ein wichtiges Arbeitsmittel sind. So wie der 2.te Gang beim Auto
:-)
mh...nun steh ich da!
erst mal zu spess:
sicher habe ich den Stack initial.
Hab es hier weggelassen.
Das mit TCCR0B und mov r7,r16 zieh ich mir nochmal rein.
Ich denke, wenn ich zu Beginn r16 in akku benenne, soll ich dann
nicht später mit r16 weiter machen.
Am Anfang stehen die .DEFxxx Bezeichnungen.
Nochmals zu diesen Kran:
In AUF Rechts Linksbetrieb sind Endlagenschalter eingebaut, aber um
die brauch ich mich garnicht zu kümmern. Der Motor wird autom. ab-
geschaltet. Egal ob 4 oder 5 Sec. die Zeit muß nur so lang sein,
daß die Endlage auch erreicht wird.
Die Abwärtsfahrt zum Contener habe ich mit einem Readkontakt gelöst.
Aber soweit bin ich noch lange nicht.
Vergessen wir doch mal das Thema "Kran" und nehmen eine einzige
LED an PortB,1 gegen Plus über NPN
kleines Quellprogramm:
loop:
pause4 (ca. 4 Sec.)
PB1 = EIN
pause4
PB1 = AUS
rjmp loop
Ich muß doch den Timer0 EIN bzw. AUSschalten, oder sollte ich das mit
sei machen?
Nun lasst mich doch nicht so zappeln, es fehlt nur noch ein Tick
bei mir, dann kommt der Durchbruch.
Meine ISR
timer:
dec warte4
brne
rjmp ende4
reti
Darf ich den rjmp ende4 innerhalb der ISR machen oder nicht
Bin gespannt, ob ich es schaffe, die eine LED zum blinken zu bringen.
Grüße
Rolf
Rolf Hegewald schrieb:> Darf ich den rjmp ende4 innerhalb der ISR machen oder nicht
Nein, darfst Du nicht.
> ende4: out TCCR0,flashaus> ret
Das ret würde zwar auch aus der ISR zurückkehren, aber nur reti setzt
das I-Flag in SREG wieder und erlaubt wieder Interrupts.
Besorg' Dir erst mal das Instruction Set Pdf von Atmel.
Rolf Hegewald schrieb:> Nun lasst mich doch nicht so zappeln, es fehlt nur noch ein Tick> bei mir, dann kommt der Durchbruch.
Sagte der Blinddarm :D
Rolf Hegewald schrieb:> In AUF Rechts Linksbetrieb sind Endlagenschalter eingebaut, aber um> die brauch ich mich garnicht zu kümmern. Der Motor wird autom. ab-> geschaltet. Egal ob 4 oder 5 Sec. die Zeit muß nur so lang sein,> daß die Endlage auch erreicht wird.
Ist zwar jetzt egal, aber für die Zukunft: Für sowas nimmt man der
Einfachheit halber gleich die Endlagenschalter her. Ist doch viel
einfacher.
> Ich muß doch den Timer0 EIN bzw. AUSschalten, oder sollte ich das mit> sei machen?
Der Timer läuft STÄNDIG
Den stellst du am ANfang ein, dann kommt irgendwann der sei (wodurch die
Timer ISR ab sofort dann regelmässig aufgerufen wird) und dann gehts im
Hauptprogramm in die Hauptschleife hinein.
> Meine ISR> timer:> dec warte4
Lies es mir von den Lippen ab:
In einer ISR wird nicht gewartet!
Der Programmaufbau ist so
1
rjmp start
2
3
Interrupt Vektoren
4
5
start:
6
Stack Initialisieren
7
8
Timer initialisieren
9
10
Zustand des Krans sei gleich "fahre nach links"
11
Wartezeit für diesen Zustand sei 4 Sekunden
12
13
sei
14
15
loop: rjmp loop
16
17
18
Timer ISR:
19
SREG sichern
20
21
Wartezeit um 1 runtzählen
22
ist die Wartezeit 0?
23
Nein -> zum Ende der ISR
24
25
; die Zeit für die Bewegung ist abgelaufen, wie gehts weiter
26
erst mal Motor aus
27
28
welches ist der 'Zustand' des Kranes?
29
30
"fahre nach links"
31
Neuer Zustand ist "fahre nach unten links"
32
Wartezeit sei 10 Sekunden
33
entsprechenden Motor ein
34
-> zum Ende der ISR
35
36
"fahre nach unten links"
37
Neuer Zustand ist "fahre nach oben links"
38
Wartezeit sei 10 Sekunden
39
entsprechender Motor ein
40
-> zum Ende der ISR
41
42
"fahre nach oben links"
43
Neuer Zustand ist "fahre nach rechts"
44
Wartezeit sei 4 Sekunden
45
entsprechender Motor ein
46
-> zum Ende der ISR
47
48
"fahre nach rechts"
49
Neuer Zustand ist "fahre nach rechts unten"
50
Wartezeit sei 10 Sekunden
51
entsprechender Motor ein
52
-> zum Ende der ISR
53
54
"fahre nach rechts unten"
55
Neuer Zustand ist "fahre nach rechts oben"
56
Wartezeit sei 10 Sekunden
57
entsprechender Motor ein
58
-> zum Ende der ISR
59
60
"fahre nach rechts oben"
61
Neuer Zustand ist "fahre nach links"
62
Wartezeit sei 4 Sekunden
63
entsprechender Motor ein
64
-> zum Ende der ISR
65
66
Ende der ISR:
67
SREG wieder herstellen
68
reti
> Bin gespannt, ob ich es schaffe, die eine LED zum blinken zu bringen.
Einfach ein Register in der ISR um 1 runterzählen.
Wenn es danach nicht 0 ist, wird die ISR wieder verlassen.
Ist es 0, dann schaltest du die LED um und belegst das Register wieder
mit einem Zählwert vor, von dem aus runtergezählt wird.
Wie gross dieser Zählwert ist, hängt davon ab wie schnell die LED
blinken soll und wie oft die ISR aufgerufen wird. Das wiederrum hängt
davon ab, wie schnell der Timer zählt und das wiederrum hängt von der
Taktfrequenz und dem Vorteiler ab.
Hi
>Ich denke, wenn ich zu Beginn r16 in akku benenne, soll ich dann>nicht später mit r16 weiter machen.>Am Anfang stehen die .DEFxxx Bezeichnungen.
Richtig. Das sollte dir auch nur zeigen, was du machst. Wenn man einen
Port den Namen 'flashaus' verpasst ist 'out flashaus,akku' richtig. Bei
einem Register aber nicht.
Persönlich bin ich Gegner von diesem .def-Gedödel. Das mag bei solchen
Spielzeugprogrammen ganz nett sein. Bei größeren Programmen kann man
einem Register nicht nur eine Funktion zuweisen. Und wenn man Librarys
für Displays, Sensoren, Schnittstellen usw. schreibt müssen die mit
verschiedenen Programmen konfliktlos zusammenarbeiten. Und da ist nun
mal der Registername der kleinste gemeinsame Nenner.
MfG Spess
Hallo an Alle,
ich habe sofort alles von Karl Heinz ausgedruckt und das Pferd ganz
Neu aufgesattelt.
Ihr habt Recht, das Ding war suboptimal.
Habe also von Anfang Neu aufgebaut und viele Anregungen von
Euch zu Herzen genommen.
Z.B. den .defxxx Düttelkram weggelassen und stur mit r16 losgearbeitet.
Mich um das SREG Register gekümmert und die Sache läuft schon mal.
Das Thema "Kran" wird ersetzt durch 3 LEDs an PB0-PB2.
Hier also das Neue:
; PORTB: Ausgabe
; PortD: Eingänge
;Datum: 10.12.2011
;AVR: Tiny 2313
.INCLUDE "tn2313def.inc" ; Deklarationen für Tiny2313
.EQU takt = 1000000 ; Systemtakt 1 MHz
; r16=Arbeitsregister
rjmp start
.ORG OVF0addr ;Interrupt Vektoren
rjmp timer ;Sprung zur ISR
;Stack initialisieren, PortB=Outp., PortD=Inp.
start: ldi r16,LOW (RAMEND)
out SPL,r16
ldi r16,$ff ; Bitmuster 1111 1111
out DDRB,r16 ; Port B ist Output
ldi r16,$00 ; Bitmuster 0000 0000
out DDRD,r16 ; Port D ist Input
;Timer0 initialisieren
ldi r16,1<<CS02|1<<CS00 ;Prescale = 1024
out TCCR0B,r16 ;r16 in Steuerreg. TCCR0
ldi r16,1<<TOIE0 ;r16< 1 = Interrupt-Freigabe
out TIMSK,r16 ;TIMSK = Timer Interrupt
sei ; I-Bit im Statusregister SREG
; 0 = Interrupt gesperrt
; 1 = " " freigegeben
;Arbeitsbeginn
loop: ldi r16,2
out PORTB,r16
rjmp timer ;Sprung zur ISR
rjmp loop
;Interrupt - ISR
timer: push r16 ;Register retten
in r16,SREG ;Statusregister
ldi r16,1
out PORTB,r16
reti
Wie schon gesagt,das läuft.
Diese Versuche stecken nicht in den Quelltext wie oben!
Nun wollte ich die ersten Gehversuche mit einem Register z.B. r17
in der ISR machen und dieses runter zählen, und da komme ich mit brne
immer noch ins schleudern.
1.Schritt...im Arbeitsbereich loop: habe ich r17 mit 0F geladen.
2. " ....springe mit rjmp timer zur ISR
gehe dec,r17
brne gehe
reti
aber so ist das doch nicht ok, ich möchte doch nur nach jedem
Timer-Überlauf r17 = -1 zählen.
Ich weiß noch nicht, wie ich exakt rauskomme, na ja..Ihr
werdet darüber lächeln, aber ich nehms hin!
Grüße
Rolf
Hi
>;Interrupt - ISR>timer: push r16 ;Register retten> in r16,SREG ;Statusregister> ldi r16,1> out PORTB,r16> reti
Das Sichern von SREG macht nur Sinn wenn man es auch wieder
rekonstruiert. Push und Pop funktionieren nur wenn es genau so viele
Pushs wie Pops gibt.
Und warum erfindest du einen eigenen Namen für den Interrupt. Nimm den
aus dem Datenblatt. Da weiß jeder, was gemeint ist.
Hi
>Wie schon gesagt,das läuft.
Nicht wirklich.
>;Arbeitsbeginn>loop: ldi r16,2> out PORTB,r16> rjmp timer ;Sprung zur ISR> rjmp loop
Wenn du einen Motor eine bestimmte Zeit in eine Richtung fahren lassen
willst geht das einfach so:
Hallo spess,
aufatmen, Dein Vorschlag läuft!
Muß alles erst mal verarbeiten.
Z.B. test war der Befehl "tst"
nach ca. 2 Sec. schaltet ein PORT,x nach PORT,y
Ich komme der Sache immer näher, meinen Dank nochmals.
Übrigens: Studio gab mir eine Warnung mit "1<<CS2|1<<CS0
Habe ich abgeändert in "1<<CS02|1<<CS00" alles war ok!
Nochmals mein Dankeschön
Rolf
Hi
>Z.B. test war der Befehl "tst"
Ja, das war ein Tippfehler.
Noch was: Quelltext sollte keine Tabs enthalten. Sonst sieht es in jedem
Editor anders aus. Am besten du stellst in den Editor-Options vom
AVR-Studio Tabwith auf 1 und aktivierst 'Replace Tabs with Space'.
MfG Spess
Hi
Du willst bestimmt nicht für jede Motorfahrt einen eigenen Code
schreiben. Im Anhang mal eine Minimalvariante wie so etwas mit wenig
Code flexibel geht. Die Motoransteuerungen (pause, M1_right, M1_left
...) und die Zeiten sind meiner Phantasie entsprungen. Musst du also
anpassen. In der Tabelle 'ablauf' muss einfach nur eingetragen werden,
was wie lange gemacht werden soll.
MfG Spess
Hi
War die Debugversion:
ldi r16,1<<CS00 ; 1<<CS02|1<<CS00
;FOC0A,FOC0B,WGM02,CS02,CS01,CS00
in
ldi r16,1<<CS02|1<<CS00 ;FOC0A,FOC0B,WGM02,CS02,CS01,CS00
ändern.
MfG Spess
Hallo Spess und Karl Heinz,
alles super geworden mit dem Quelltext für den Contener.
2 Eingänge an PortD liegen über Readkontakte gegen GND.
Habe ich so gelöst:
loop: nop
read1: spic PIND,PD0
rjmp read1
Motor aufwärts EIN
Dann auf 2 Unterprogramme (5 bzw. 20 Secunden)
rcall zeit5
rcall zeit20
zeit5:
pause5: tst r17,17 ;gemessen ca. 5 Sec.
brne pause5
ret
zeit20:
pause20: tst r17,5C ;gemessen ca. 24 Sec.
brne pause20
ret
Nun muß ich noch die Hardware zusammen stricken und dann kommt der große
Momment.
Leider zeigt mein Buch nur den Timer1 für einen Mega8.
So wie ich lese, ist das Gebiet umfangreicher als der Timer0.
Für die übernächste Zeit werde ich sowas für einen
Tiny13 brauchen, und zwar als Ortungspieper für einen 3m Segler.
Aber ich glaube, der kleine Tiny hat nur Timer0.
Also meinen Dank nochmals für Eure Hilfe und geduldige
Ausdauer mit mir.
Grüße
Rolf
mh...was wäre das schön, wenn ich Eure Englischkenntnisse hätte!
Und mit über 70 Jahren fange ich nicht mehr damit an, zumal
mir das Volkshochschul-Englisch nicht viel nützen wird.
Hallo an ALLE,
habe heute nochmal den ganzen Thread durchgekaut, um viele
Sachlagen zur Erinnerung zu rufen.
Der Containerkran (jetzt will ich es aber mal richtig schreiben)
läuft und läuft.
Danke nochmals und Grüße
Rolf