Kann mir bitte einer sagen warum dieses Programm sich nicht Assemblieren
lässt?
Es erscheint immer der Fehler "Operand 2 Out Of Range". Kann diesen
Fehler jemand beheben?
mfg.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;
.include "m8def.inc"
ldi r16, 0xff
out DDRB, r16
ldi r16, 0x00
out PortB, r16
out DDRC, r16
out PortC, r16
ldi r16, LOW(RAMEND)
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16
;
;:::::::::::::Timerwahl::::::::::::
;
loop:
sbis PortC, 0b00000001
rjmp Timer1
sbis PortC, 0b00000010
rjmp Timer2
sbis PortC, 0b00000100
rjmp Timer3
sbis PortC, 0b00001000
rjmp Timer4
sbis PortC, 0b00010000
rjmp Timer5
rjmp loop
;
;::::::::::::::Timer:::::::::::::
;
Timer1:
sbis PortC, 0b00100000
rjmp Timer1A
rjmp Timer1
Timer2:
sbis PortC, 0b00100000
rjmp Timer2A
rjmp Timer2
Timer3:
sbis PortC, 0b00100000
rjmp Timer3A
rjmp Timer3
Timer4:
sbis PortC, 0b00100000
rjmp Timer4A
rjmp Timer4
Timer5:
sbis PortC, 0b00100000
rjmp Timer5A
rjmp Timer5
;
;:::::::Ausführen:::::::::::::::
;
Timer1A:
ldi r16, PortC
push r16
ldi r16, 0b00000001
out PortB, r16
;::::::::Zeitschleife einfügen:::::::
ldi R17, $BF
WGLOOP01:
ldi R18, $A7
WGLOOP11:
ldi R19, $D0
WGLOOP21:
dec R19
brne WGLOOP21
dec R18
brne WGLOOP11
dec R17
brne WGLOOP01
ldi R17, $02
WGLOOP31:
dec R17
brne WGLOOP31
nop
nop
;::::::::::::::::::::::::::::::::::::::::
pop r16
out PortC, r16
rjmp Timer1
Timer2A:
ldi r16, PortC
push r16
ldi r16, 0b00000001
out PortB, r16
;::::::::Zeitschleife einfügen:::::::
ldi R17, $BF
WGLOOP02:
ldi R18, $A7
WGLOOP12:
ldi R19, $D0
WGLOOP22:
dec R19
brne WGLOOP22
dec R18
brne WGLOOP12
dec R17
brne WGLOOP02
ldi R17, $02
WGLOOP32:
dec R17
brne WGLOOP32
nop
nop
;::::::::::::::::::::::::::::::::::::::::
pop r16
out PortC, r16
rjmp Timer2
Timer3A:
ldi r16, PortC
push r16
ldi r16, 0b00000001
out PortB, r16
;::::::::Zeitschleife einfügen:::::::
ldi R17, $BF
WGLOOP03:
ldi R18, $A7
WGLOOP13:
ldi R19, $D0
WGLOOP23:
dec R19
brne WGLOOP23
dec R18
brne WGLOOP13
dec R17
brne WGLOOP03
ldi R17, $02
WGLOOP33:
dec R17
brne WGLOOP33
nop
nop
;::::::::::::::::::::::::::::::::::::::::
pop r16
out PortC, r16
rjmp Timer3
Timer4A:
ldi r16, PortC
push r16
ldi r16, 0b00000001
out PortB, r16
;::::::::Zeitschleife einfügen:::::::
ldi R17, $BF
WGLOOP04:
ldi R18, $A7
WGLOOP14:
ldi R19, $D0
WGLOOP24:
dec R19
brne WGLOOP24
dec R18
brne WGLOOP14
dec R17
brne WGLOOP04
ldi R17, $02
WGLOOP34:
dec R17
brne WGLOOP34
nop
nop
;::::::::::::::::::::::::::::::::::::::::
pop r16
out PortC, r16
rjmp Timer4
Timer5A:
ldi r16, PortC
push r16
ldi r16, 0b00000001
out PortB, r16
;::::::::Zeitschleife einfügen:::::::
ldi R17, $BF
WGLOOP05:
ldi R18, $A7
WGLOOP15:
ldi R19, $D0
WGLOOP25:
dec R19
brne WGLOOP25
dec R18
brne WGLOOP15
dec R17
brne WGLOOP05
ldi R17, $02
WGLOOP35:
dec R17
brne WGLOOP35
nop
nop
;::::::::::::::::::::::::::::::::::::::::
pop r16
out PortC, r16
rjmp Timer5
> Es erscheint immer der Fehler "Operand 2 Out Of Range". > Kann diesen Fehler jemand beheben? Wie wärs mit dir selber? Bei einer Fehlermeldung steht immer die Zeilennummer dabei. Dann suchst du im Quelltext besagt Zeile und siehst nach bei welcher Operation das ist. Wenn du die Operation hast, schaust du in der Doku (entweder online-Doku oder heruntergeladene Papierdoku) nach, welche Einschränkungen für den Operanden 2 in besagtem Befehl gelten. Und dann vergleichst du das mit dem was du hast.
Ich kenne Deine Programmierumgebung nicht, aber: Die Meldung müsste eigentlich eine Zeilennummer enthalten. Dort muss der 2. Operand überprüft werden Ich vermute mal, Du hast einen 16-Bit Operanden genommen, wo nur 8 Bit gehen. Viel Spaß beim Suchen. Wird nicht so schlimm sein!
Nebenbei: ldi r16, PortC push r16 ... pop r16 out PortC, r16 ist nicht ganz das, was dir dabei vorschwebt.
Du solltest Dir in der Befehlssatzdokumentation mal ansehen, was für Operanden der Befehl sbis erwartet. Kleiner Tip: Der zweite Operand muss im Bereich 0...7 liegen! 0b00100000 ist aber deutlich außerhalb davon...
So hab das Programm neu geschrieben!
Nun funktioniert es!
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.include "m8def.inc"
ldi r16, 0xff
out ddrb, r16
ldi r16, 0x00
out ddrc, r16
out portc, r16
ldi r16, LOW(RAMEND)
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16
;
;:::::::::::::::::::Timerwahl::::::::::::
;
PortEinlesen:
in r16, pinc
Timer1:
cpi r16,0b00000010
brne Timer2
rjmp Timer1W
Timer2:
cpi r16,0b00000100
brne Timer3
rjmp Timer2W
Timer3:
cpi r16,0b00001000
brne Timer4
rjmp Timer3W
Timer4:
cpi r16,0b00010000
brne Timer5
rjmp Timer4W
Timer5:
cpi r16,0b00100000
brne PortEinlesen
rjmp Timer5W
;
;::::::Auf Befehl warten:::::::::::::
;
Timer1W:
sbic pinc, 0b00000001
rjmp Timer1A
rjmp Timer1W
Timer2W:
sbic pinc, 0b00000001
rjmp Timer2A
rjmp Timer2W
Timer3W:
sbic pinc, 0b00000001
rjmp Timer3A
rjmp Timer3W
Timer4W:
sbic pinc, 0b00000001
rjmp Timer4A
rjmp Timer4W
Timer5W:
sbic pinc, 0b00000001
rjmp Timer5A
rjmp Timer5W
;
;::::::::::::::Ausführen:::::::::::::
;
Timer1A:
in r16, pinc
push r16
ldi r16, 0b00000001
out portb, r16
;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::
pop r16
out portc, r16
rjmp Timer1W
Timer2A:
in r16, pinc
push r16
ldi r16, 0b00000001
out portb, r16
;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::
pop r16
out portc, r16
rjmp Timer2W
Timer3A:
in r16, pinc
push r16
ldi r16, 0b00000001
out portb, r16
;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::
pop r16
out portc, r16
rjmp Timer3W
Timer4A:
in r16, pinc
push r16
ldi r16, 0b00000001
out portb, r16
;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::
pop r16
out portc, r16
rjmp Timer4W
Timer5A:
in r16, pinc
push r16
ldi r16, 0b00000001
out portb, r16
;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::
pop r16
out portc, r16
rjmp Timer5W
> sbic pinc, 0b00000001
Immer noch nicht kapiert? sbis und sbic erwarten als zweiten
Operanden keine Bitmaske, sondern die Bitnummer! Und eine Nummer
schreibt man nicht im Binärformat! Du verwechselst das mit sbrs und
sbrc, bei denen braucht's ne Bitmaske.
Außerdem steht in den Forenregeln klipp und klar, dass längerer Code als
Anhang gepostet werden soll und nicht im Thread! Und es gibt hier auch
die Möglichkeit, Code so zu formatieren, dass er besser als solcher
erkennbar und auch besser lesbar ist! Und die Möglichkeit sollte man
auch nutzen...
Im Prinzip ja. Was soll das Programm eigentlich machen? Dein Programm sieht etwas seltsam aus. zb. sind alle TimerxA identisch (oder hab ich da was übersehen)
1 | Timer5A: |
2 | in r16, pinc |
3 | push r16 |
4 | ldi r16, 0b00000001 |
5 | out portb, r16 |
6 | |
7 | ;::::::::::Zeitschleife hier einfügen:::::::: |
8 | nop |
9 | ;:::::::::::::::::::::::::::::::::::::::::::: |
10 | |
11 | pop r16 |
12 | andi r16, 0b11111110 |
13 | out portc, r16 |
14 | rjmp Timer5W |
Die Sequenz von PINC einzulesen und dann das Gelesene (ausser Bit0) auf dem PORTC auszulesen, sieht mehr überhaupt nicht koscher aus. Letztendlich bedeutet das doch, dass du alle Pins (ausser Pin 0) sowohl als Eingang als auch als Ausgang ansiehst (bzw. dort die Pullups von Eingangspins umschaltest). Das ganze ist mehr als undurchsichtig (oder ich bin einfach schon müde). Ich denke mal, das kann man auch wesentlich einfacher machen.
> Ich denke mal, das kann man auch wesentlich einfacher machen.
Richtig. Aber dazu müsste der "Autor" sein Programm verstehen. Dies
scheint hier nicht der Fall zu sein, ich vermute, dass hier
unverstandener fremder Code zusammenkopiert, dupliziert und
verschlimmbessert wurde.
...
Nope Das is eigenentwicklung! Die Timer sind gleich weil man einen Timer seiner Wahl reinmachen kann. Habe nur ein nop drinne weil es sich so besser simulieren ließ! Also wenns interressiert .... bei Conrad gibt es ein Bausatz mit dem man über einen LDR ein Relais bestimmte zeit lang anschalten und dann wieder aus schalten kann. Ich will diesen selbst bauen und ein paar extras noch! Aber abwarten wenn ich heute aufm stk getestet hab stell ich schaltplan noch rein und dann seht ihrs! Also geht mal an alle hier .. nicht immer mit ngativen kommentaren kommen wenn anfänger hier mal ein Code posten!!!! Auch wenn sie oft fehler beinhalten!!!!
Gut, dann ist es Eigenbau, den Begriff "Entwicklung" lasse ich mal außen vor, denn bis zu diesem Stadium fließt noch allerhand Wasser den Rhein hinunter... Ich habe mich nicht intensiv mit Deinem Code auseinandergesetzt, weil ich ihn beim groben Ansehen als sehr uneffizient eingestuft habe, was wohl in den vielen Wiederholungen gleicher Sequenzen, dem Fehlen einer Tastenentprellung und dem Vermeiden von Interrupt oder zumindest Unterprogramm-Aufruf begründet ist. Gut, es ist ein Anfängerprogramm, aber in einer Anfängerphase, wo es noch um das Lernen geht und noch nicht um das Realisieren von Projekten. Der nächste Lernschritt wäre dann das Verwenden eines Unterprogramms für die Warteschleife, die Du fälschlicherweise "Timer" nennst. Und dann sollte die Erkenntnis kommen, dass Du beim Mega8 drei Hardware-Timer mitbezahlt hast, von denen einer reicht, Dir im Hintergrund (also durch Hardware) einen "langsamen" Zeittakt zu generieren, der Dein gesamtes Programm synchronisiert und Warteschleifen unnötig macht. Wenn dann noch die Notwendigkeit einer soliden Tastenentprellung mit Flankenerkennung erkannt und realisiert wurde, dann kann man langsam über die Realisierung von Projekten nachdenken. Nein, ich will es Dir nicht mies reden, Du bist schon auf dem richtigen Weg, aber eben noch ganz am Anfang. Der Weg ist weiter als Du jetzt vermutest. Noch kämpfst Du mit dem Alphabet (Befehlssatz, erlaubte Register und Bereiche), also mit Selbstverständlichkeiten der AVR-Architektur, später wirst Du Dich dann damit beschäftigen, welche Algorithmen die Richtigen sind und wie man sie halbwegs effizient in Assembler formuliert. Vielleicht solltest Du nebenher auch mal schaun, wie es Andere machen. Dazu bieten sich diverse Tutorials an, z.B. das auf dieser Seite oder das AVR-ASM-Tutorial: http://www.mikrocontroller.net/articles/AVR-Tutorial http://www.avr-asm-tutorial.net/ Weiterhin bieten sich die Projekte Anderer in der Codesammlung an: http://www.mikrocontroller.net/forum/codesammlung Durch Analyse einzelner Codesequenzen und Vergleich mit eigenem Code für ähnliche Aufgaben kommt so manche Erkenntnis ganz von alleine, ohne dass man mehrere "persönliche Berater" beschäftigen muss. Noch'n Tip: Drucke Dir aus dem Datenblatt die Tabelle mit dem Befehlssatz aus. Mit dieser Übersicht und der Hilfe zum AVR-Studio geht das Erlernen des Befehlssatzes bedeutend besser und schneller. Gleiches gilt auch für die Tabelle mit der Beschreibung der I/O-Register. Diese ist sehr hilfreich beim Nachschlagen der Namen der I/O-Register und ihrer Bits, und dient dank der Angabe der Seiten-Nummern auch noch als Inhaltsverzeichnis zum Datenblatt-PDF. Dies spart (gerade in der Lernphase) allerhand Zeit und Frust. ...
Gast wrote: > Also geht mal an alle hier .. nicht immer mit ngativen kommentaren > kommen wenn anfänger hier mal ein Code posten!!!! Darum gehts nicht. Aber so wie das Programm aussieht, wärs vielleicht mal ganz gut, wenn dir jemand mit mehr Erfahrung zeigt, wie man das einfacher machen kann. Du willst ja auch was dabei lernen.
Danke Hannes Lux! Ich werde mich daran machen das von dir beschriebene mir anzueigenen! DIESER THREAD KANN GECLOSED WERDEN!!! Es steht nichts nütliches darin...
> DIESER THREAD KANN GECLOSED WERDEN!!!
Glücklicherweise bestimmst Du das nicht.
Dieser Thread kann nämlich immer noch als Beispiel für den nächsten
Anfänger dienen, der da meint, statt eigener Recherche ein halbes
Dutzend Helfer beschäftigen zu müssen.
...
Johannes M. wrote: >> sbic pinc, 0b00000001 > Immer noch nicht kapiert? sbis und sbic erwarten als zweiten > Operanden keine Bitmaske, sondern die Bitnummer! Und eine Nummer > schreibt man nicht im Binärformat! Du verwechselst das mit sbrs und > sbrc, bei denen braucht's ne Bitmaske. Nö, auch sbrc und sbrs wollen eine Bit-NUMMER. Den Unterschied, den du vermutlich meinst, betrifft cbi/sbi und cbr/sbr. /cbi und sbi erwarten eine Bitnummer, wohingegen sbr ein Alias für ori ist und genauso wie sbr eine Maske sehen will.
Sven P. wrote: > Nö, auch sbrc und sbrs wollen eine Bit-NUMMER. > Den Unterschied, den du vermutlich meinst, betrifft cbi/sbi und cbr/sbr. > /cbi und sbi erwarten eine Bitnummer, wohingegen sbr ein Alias für > ori ist und genauso wie sbr eine Maske sehen will. Jou, da haste wahr. Ich wollte noch zur Sicherheit eben nachschauen, hab das dann aber irgendwie nicht mehr gemacht...
Was auch noch auf den ersten Blick auffaellt, ist das Fehlen jeglicher Kommentare. Gast3
> Was auch noch auf den ersten Blick auffaellt, ist das Fehlen jeglicher > Kommentare. Ja, schon, aber diesen Satz habe ich mir verkniffen, da der Quelltext viele Trennzeilen aus Doppelpunkten enthält, die man evtl. als Kommentare bezeichnen kann. Und über den Sinn oder Unsinn dieser Kommentarzeilen möchte ich nicht diskutieren, da es schwer ist, die richtige Menge zu finden. Bei zuwenig geht die Formatierung verloren, bei zuviel ist auf dem Bildschirm zuwenig Platz für den eigentlichen Quelltext. Aber irgendwie habe ich noch nicht gerafft, was das Programm eigentlich mal tun soll. Die Aufgaben (Conrad-LDR-Relais) sind mir irgendwie nicht konkret genug formuliert. Daher kann ich auch nicht helfen, das Programm zu optimieren. Der wichtigste und aufwändigste Schritt bei der Entwicklung eines Programmes ist nunmal die eindeutige unmissverständliche Beschreibung der zu lösenden Aufgabe (mit normalen Worten, also ohne Einsatz einer Programmiersprache). Solange dies nicht klar definiert ist, lohnt es sich nicht, über die Programmierung in einer Programmiersprache nachzudenken. ...
Hallo Gast, meine Vorredner haben ja schon gesagt, das es in deinem Programm noch sehr viele Fehler gibt und vorallem UNGEREIMTHEITEN! Ich habe mich mal bei Conrad umgeschaut und ich glaube ich habe gefunden was du suchst .... Conrad Artikel-Nr.: 190951 - 62 Oder nicht? Dieser Bausatz sieht sehr interessant aus aber ist schwer realisierbar. Also für einen Anfänger! Wenn du möchtest könnte ich dir unter die Arme greifen :) Denn ich finde dieses Modul äuserst interessant ;) mfg. -crack-
So dein Programm ist nicht klar strukturiert aber ich denke wenn man es kommentiert wird es klarer, deshalb werde ich den ansatz so belassen und nur schnell ein paar Änderungen vornehmen! Schau doch einfach mal im AVR Tutorial unter Tasten nach ... da ist ein Beispiel von Peter Dannegger. Dieses werde ich aus Zeitgründen 1:1 übernehmen. Aber dafür sind Beispiele ja da ;) Das mit dem Timer musst du selbst programmieren, da ich wirklich wenig Zeit habe und dies nun nebenbei mache .... Bis heute abend sollte es fertig sein .... Ihr anderen haut mich nicht weil ich seine unübersichtliche Struktur lasse ;)
Sodale das Programm ist fertig ... Ich hab die Idee mit diesen Kommentar "Überschriften" beibehalten :) ist irgendwie witzig ;) Hoff das ist das was du versucht hast zu programmieren .... Du musst jetzt nurnoch die Timer einfügen, da wo das Programm dann einfach irgendwelche Werte an PortB ausgibt ... also bei Timer1A-Timer5A! Hab die ausgaben nur zum testen azfm stk reingemacht .... Wenn dir Timer zu schwer sind, dann nimm delay-loops. Aber das sollte nur eine Notlösung sein, denn elegant ist das nicht!!! mfg. -crack-
Danke für das Programm -crack-! Funktioniert einwandfrei! Aber nehme Delay schleifen da ich keine Timer programmieren kann.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.