Hi, ich arbeite in der Schule mit Intel Processoren. Ich will aber privat mit Atmel arbeiten und zwar unteranderem mit dem AT90S4433. Dummerweise sind da andere Befehle drin. Gibt es vielleicht irgendwo sone Tabbelle wo man die ersazt befehle drin sind ? soweit es halt möglich ist. z.b. JZ JNZ JMP = RJMP :-D und so weiter. IM ANhang wollte ich mal ein Prog schreiben der zwischen 2 LED hin und herspringt. aber ich kriege das mit dem JNZ nicht hin. Er bleibt in der warte schleife hängen vermute ich. Ich habe die 3 Register mit 100 dez geladen. Und decrementiere diese also minus und will das er sprint wenn der wert auf null ist. Was muss ich da ändern. Für euchist das Pipifax ich konnte abe rim netz nix finden :-( Danke
für JZ nimm BREQ für JNZ nimm BRNE Steht aber wirklich alles im Datenblatt in der Befehlstabelle bestens erklärt. Gruß Jan
naja unter bestens erklärt stell ich mir was anderes vor. Aber geal und warum funktioniert mein prog nicht habe den brne verwendet gehabt :-/
Das Unterprogramm 'warte' musst du natürlich mit einem call oder rcall aufrufen, sonst führt der ret ins nirwana. In 'warte' nusst du brne statt breq schreiben, denn du willst ja springen , wenn der dec kein Null ergibt. Ausserdem hast du wohl w1 und w2 vertauscht. Damit der Unterprogrammrücksprung geht muss der Stackpointer initialisiert werden. Uwe
Atmel hat auch (Intel-) kompatible im Programm ( i8051 ). Der Befehlsvorrat wird Dir sehr bekannt vorkommen . Ist auch ein CISC . Siehe : http://www.atmel.com/products/8051/ ( Nein , ich will nicht bekehren ... ;-)
> naja unter bestens erklärt stell ich mir was anderes vor. Dann solltest du dir mal folgendes runterladen: http://www.atmel.com/dyn/resources/prod_documents/doc0856.pdf
Naja, so eine Tabelle kann es gar nicht geben. Zwar sind die Mnemonics bei ähnlichen Prozessorarchitekturen ähnlich, aber bei weitem nicht gleich.
Hi, habe das soweit gemacht jetzt leuchten mir 2 LED's vielleicht blinken die auch abwechselnd aber so schnelle das ich das nicht mirkriege. HAbe das aber mi dme Stack nicht gemacht. Da ich es für Intel auch nicht machen musste. Könnt ihr mir sagen was bzw. wie ich das machen soll ? Danke MFG Killer
Du musst den Stackpointer auf Ramend setzen. Schau dir doch einfach mal die Beispielcodes in den Datenblättern an und die hier im Forum geposteten Codebeispiele. z.B.: http://www.mikrocontroller.net/forum/read-1-261184.html#261258 http://www.mikrocontroller.net/forum/read-1-259571.html#259582 Weitere Beispiele gibt es in der Codesammlung. Auch in der Artikelsammlung gibt es interessante Hinweise: http://www.mikrocontroller.net/articles/AVR_Checkliste ...
.include "4433def.inc" ;Definitionsdatei einbinden, ggf. durch ;2333def.inc ersetzen start: ldi r16, 0xFF ;0xFF ins Arbeitsregister r16 laden out DDRB, r16 ;Inhalt von r16 ins IO-Register DDRB ausgeben ldi r16, 0b11111110 ;0b11000000 in r16 laden out PORTB, r16 ;r16 ins IO-Register PORTB ausgeben rjmp warte ldi r16, 0b11111101 ;0b11000000 in r16 laden out PORTB, r16 ;r16 ins IO-Register PORTB ausgeben rjmp warte ende: rjmp start warte:ldi r17, 0x64 w1:ldi r18, 0x64 w2:ldi r19, 0x64 s1: dec r17 BREQ s1 dec r18 BREQ w1 dec r19 BREQ w2 ret
sorry für den Müll-Post gerade ... warte: ldi r17, 0x64 w1: ldi r18, 0x64 w2: ldi r19, 0x64 s1: dec r17 BREQ s1 dec r18 BREQ w1 dec r19 BREQ w2 ret Ersetze BREQ durch brne. brne heisst: springe, wenn (das letzte Ergebnis) nicht NULL war. Mit BREQ werden die Schleigen nie ausgeführt. Und natürlcih Stack setzen, wie oben beschrieben. Bei Microcontrollern musst Du eben Einiges selber machen, was Dir auf dem PC das Betriebssystem abnimmt (Stack-Initialisierung z.B.). Dafür passt der AVR aber auch auf eine Briefmarke ... Gruß, Stefan
Ich krieg das nicht hin. Habe jetz den Steckpointer initialisiert. Und alle änderungen vorgenommen die ihr mir gesagt habt aber es leuchten immer noch beides LEDs. Was muss man da sonst noch machen ? Ist der wert in der schleife zu klein. Oder was anders ? Wäre super wenn jemand die datei so modifiziert das es geht. Ich hoffe mal das ich dann daraus mein fehler erkenne. Danke
"HAbe das aber mi dme Stack nicht gemacht. Da ich es für Intel auch nicht machen musste." Der Witz ist gut, selten so gelacht. Aber dann mußt Du schon konsequent bleiben und darfst die DDRx-Register auch nicht setzen. Es ist völlig egal, was Du woanders gemacht oder nicht gemacht hast. Wenn Du etwas notwendiges nicht machst, bestraft Dich der Mikrocontroller mit nicht funktionieren, so einfach ist das. Und nun überleg nochmal, was Du nicht machst. Peter P.S.: Ich verstehe auch nicht, warum die AVR-Entwickler den Stack beim Reset nicht auf einen gültigen Wert setzen können. Sie habens eben nicht gemacht und deshalb must Du es machen.
Mein Gott, also wirklich einige sind ja wirklich nett. Aber andere denken da die es schon in und auswendig können. Das jeder anderer der damit anfängt ein Looser ist. Wenn man die Turorial und beschreibungen nicht richtig versteht, heißt es nicht automatisch das man ein Looser ist sondern das man es anders eklärt bekommen muss. Das Mit dem Stack wusst ich nicht. Wie soll man etwas machen was man nicht weis. Nun habe ich ihn inistialiesiert. Und es geht immer noch nicht wie du in der Datei vielleicht erkennen kannst. Anstelle mir Prädigen zu geben, zeigen wieviel besser du bist, könntest du mir lieber Helfen. Und Sagen was an meinem Prog nicht stimmt.
Hast du dir die Beispiele in den von mir angegebenen Links überhaupt angesehen? Wenn ja, dann sollten deine Fragen geklärt sein. Wenn es dazu weitere (konkrete) Fragen gibt, die du mittels Beispiel, Datenblatt und Hilfe zum AVR-Studio nicht lösen kannst, so frag nach. ...
Hi, natürlich habe ich mri diese angeschaut. Darauf basieren habe ich die initialiesierung vorgenommen. Doch leiter Leuchten diese immer noch und blinken nicht. Also eine kroete frage kann ich nicht stellen. Da ich der ansicht bin das mein Programm so laufen müsste.
Nunja, ich weiß zwar nicht, welchen Assembler du benutzt, dass du keine Fehlermeldungen erhältst. Du nimmst den AT90S4433. - Dort heißt der Stackpointer nicht SPL sondern SP (sagt mir zumindest das Datenblatt). - Du nutzt den Befehl CALL. Den kann der 4433 garnicht, den gibt es erst bei größeren AVRs. Du müsstest daher RCALL nehmen. - Lade mal deine Zeitschleifenregister mit 0 und springe mit BRNE (branch if not eaquel, Sprung wenn nicht gleich 0) zurück. Im (vollständigen) Datenblatt zu jedem AVR gibt es (recht weit hinten) die Tabellen "Register Summary" und "Instruction Set Summary". Diese sollte man sich (gerade als AVR-Anfänger) unbedingt ausdrucken. Später kommt dann noch die Int-Vektor-Tabelle dazu und evtl. die Registerbeschreibungen der Timer. Ohne diese Informationen bist du erschossen, wir übrigens auch! Ein MC-Programm soll die Hardware des MC manipulieren (die bei jedem Typ etwas anders ist!), da muss man die Hardware schon kennen, sonst wird das nix. ...
Hi, geh mal systematisch vor: * Testen, ob der mc überhaupt was tut: Erstmal nur Low- und Hi-Pegel auf einige Ports geben und dann nachmessen, ob die ankommen. * Pins toggeln: Schleife (ohne Warte-Routine), in der die LED-Pins klow- und high geschaltet werden. Die LEDs müssen im Vergleich zu Schritt1 dunkler werden. Wenn Du ein Messgerät hast: beim Messen der Ports muss sich ungefähr VCC/2 ergeben. * Wartezeiten einfügen: Jetzt setzt Du zwischen das Hi- und Low-Schalten der LEDs Wartezeiten ein. Erstmal ohne Unterprogramm-Aufruf, kopiere Deine Warteschleife 2* (mit brne-Befehlen). Die Labels und Sprungziele in den Warteschleifen entsprechend anpassen. Danach müsstest Du ein Blinken sehen können. * Wartezeiten statt direkt im Programmcode als Unterfunktion umbauen: Jetzt muss der Stack richtig initialisiert sein, sonst landet ein Rücksprung aus dem Unterprogramm im Nirvana. Welchen Assembler benutzt Du und welche Messmöglichkeiten (Messgerät, Oszi?) hast Du zur Verfügung? Viel Spass noch, Stefan
DAnke erstmal für deine Antwort. Ich habe das eigentlich so systematisch. ( Relativ ) gemach gehabt.Hab das jetz aber genau so gemacht. DEr µC arbeitet. Da ich jedes mal was anderes einprogrammieren kann z.b. 2,3 oder 4 LEDs zu leuchten zu bringen und so weiter. Toggeln funktioniert auch. Im ersten Modus ca 2V. Im 2ten Modus ca 1V. Unterprogramm entfernt Warte schlleife direkt eingefügt. Leider leuchten die immer noch und Blinken nicht. Warteschleife:= warte: ldi r17, 0x64 w1: ldi r18, 0x64 w2: ldi r19, 0x64 w3: dec r17 BREQ w3 dec r18 BREQ w1 dec r19 BREQ w2 PS: Ich verwende AVR Studio 4. WAVEAVR HAtte ich auch da hat er auch nicht gemekert. Call habe ich trozdekm durch rCall ersetzt genauso wie SPL durch SP. Immer noch gleicher Fehler.
Ließt Du eigentlich die Posts? BREQ = Branch if equal = Springe wenn Null BRNE = Branch if not equal = Springe wenn ungleich Null fällt Dir was auf?
JA tue ich. Tutmir Leid das ich ein Mensch bin. In dem ich BRNE verwende leuchtet nur eine LED was mir logisch erscheint da er daruch in der schleife hängen bleibt. Ich muss schon sagen in diesem Forum Fachleute = Ja Gute Menschen = Sehr wenig Und da ich wohl zu "Blöd" für dieses Forum bin und nicht von jedem gleic angepist werden möchte. Kann man von mir aus das Theard schließen. Ich werde wohl ode rüber anders Versuchen rauszufinden wie man Sowas machen kann. PS: Wenn es einen Netten gibt der mir ( Einen Anfänger ) gerne helfen würde und der mich nicht nur anpissen will. Wäre es Nett mich mal zu kontacktieren. PTNB@gmx.de
Na dann bist Du doch fast durch. bei dec Rx ziehst Du 1 vom Register ab, das Ergebnis ist entweder Null oder eben nicht. NULL entspricht bei der Atmel-Logik EQUAL. Du willst so lange decrementieren, bis Rx NULL ist, also springst Du mit brne (-> springe wenn NICHT NULL) zurück in die Schleifenwiederholung. Vergiss nicht: wenn Du den Code der Warteschleife mehrmals im Programm hast, dann musst Du alle Labels und Sprungziele umbenennen, also: Pin schalten ;Warteschleife 1: warte: ldi r17, 0x64 w1a: ldi r18, 0x64 w2a: ldi r19, 0x64 w3a: dec r17 BREQ w3a dec r18 BREQ w2a ;w1 war hier falsch! dec r19 BREQ w1a ;w2 war hier falsch! Pin zurückschalten ; Warteschleife 2: warte2: ldi r17, 0x64 w1b: ldi r18, 0x64 w2b: ldi r19, 0x64 w3b: dec r17 BREQ w3b dec r18 BREQ w2b ;w1 war hier falsch! dec r19 BREQ w1b ;w2 war hier falsch! In Deinem gerade geposteten Code war übrigens w1 und w2 verdreht. Gruß, Stefan
Dass er mit brne in der Schleife hängenbleibt liegt am Vertauschen von den Sprungzielen w1 und w2, s.o. Stefan
Ich geb mal nen Schubser: DEC r17 ist ein simpler DEC-Befehl, wie ihn die Intels auch kennen. Und wie bei den Intels auch, wird das Ergebnis der Operation in den Flags "bekanntgegeben". Ergo: Ist r17 nach dem DEC = 0, dann ist das Zero-Flag = 1. So. Die Intels kennen nun ein "JZ" (Jump if Zero=1) und ein "JNZ" (Jump if not Zero=1). Bei den AVR's heißt das ganze "BREQ" (Branch if Equal) bzw. BRNE (Branch if not Equal). Woher das "Equal" kommt ? Vom CMP-Befehl. Ein (Intel-Style) "cmp ax,bx" führt Prozessorintern eine Subtraktion von ax und bx aus ("sub ax,bx"). Das Ergebnis wird wieder in den Flags reflektiert. Ergo: Sind beide Werte gleich ("Equal"), ergibt das interne "sub ax,bx" genau Null - worauf das Zero-Flag gesetzt wird. Got the point ? I hope so.
Hey, mal sachte! Man hat Dich schon am Anfang des Thread darauf hingewiesen, nicht BREQ sondern BRNE (Gegenstück von JNZ) zu verwenden, ebenso wie RCALL statt RJMP zum Aufruf der Warterei und auch SP statt SPL (SPL und SPH nur für AVRs mit mehr als 128 Byte SRAM). Wer sich die Beiträge vollständig in Ruhe durch liest, ist klar im Vorteil. Anpissen Will Dich bestimmt niemand sondern nur X mal darauf hinweisen. Vielleicht ist ja Deine Schleife viiiiel zu lang, sind ja immerhin 3 Verschachtelungen. Setze mal die äußere Schleife auf 1. MfG Andi
Danke für die Erklärung des DEC Befehls und der BRNE und BREQ. Das weis ich und habs auch verstanden. Doch wenns nicht geht versuche ich erst das eine und dann das andere. Und habe jetzt auch extra für dich ANDI mal in die Schleife eine 1 eingesetzt, so sieht meine Schleife aus: warteA: ldi r17, 0x01 w1a: ldi r18, 0x64 w2a: ldi r19, 0x64 w3a: dec r17 BRNE w3a dec r18 BRNE w2a dec r19 BRNE w1a Ich glaube aber mittlerweile nicht das es an der Schleife leigt. Da wir das ausführlich besprochen haben und da ich auch schon den Schleifengenerator eingesetzt habe, da aich angefangen habe an mir zu zweifeln. Dieser ist im ANhang, vielleicht kennt ih den ja. Und könnt mir direkt mal sagen ob der was taugt.
Huch, heute ist wohl der Eingeschnappt-Tag. Wenn sich doch mal die werten Herren Einschnapper erstmal selber durchlesen würden, was sie da so schreiben. Und mal kurz nachdenken, wie das auf jemanden wirken könnte, der nicht in ihren Kopf schauen kann. Anpissen will hier keiner jemanden, aber Gedanken lesen kann hier niemand (nehme ich mal an). Auf der Gegenseite sind auch nur Menschen und keine Alles-aus-der-Nase-ziehen-und-antworten-Roboter. Peter
Sorry, exe-Dateien laufen auf meinem Rechner nicht - die Löschtaste ist immer schneller ;-) Deien Schleife ist wirklich viel zu lang - das Setzen der Register ist an der falschen Stelle. So wird sie ca. 16 millionen mal ausgeführt. Dreh mal R17 und R19: warteA: ldi r19, 0x01 w1a: ldi r18, 0x64 w2a: ldi r17, 0x64 w3a: dec r17 BRNE w3a dec r18 BRNE w2a dec r19 BRNE w1a Du machst das übrigens nicht extra für Andi - sondern Andi macht das extra für Dich ... Gruß, Stefan
Ich denke übringens meine letzte shcleife war sowieso falsch die sollte so ausehen. warteA: ldi r19, 0x01 w1a: ldi r18, 0x64 w2a: ldi r17, 0x64 w3a: dec r17 BRNE w3a dec r18 BRNE w2a dec r19 BRNE w1a Peter ich kann keine gedanken auf ie Entfernung lesen :-) Ich weis das auf der Anderen Seite Menschen sind. Finde es auch nicht schlim wenn die was sagen oder mich auf etwas hinweisen. Aber ich kenne es aus anderen Forum eigentlich so das der Ton noch auf einem richtigem Nivo bleibt. Oder sind µC-Programmierer da anders ? Noch mal mein aktueller ASM als anhang. WEnn jemand noch was sieht wäre es "NETT" Mich zu informieren oder drauf hinzuweisen was ich vielleicht "wieder" Falsch gemacht habe.
Nett gemeinter Hinweis: Das AVRStudio hat einen Simulator, mit dem man das Programm schrittweise ausführen und so nachvollziehen kann. Gruß, Andreas
@NAS4Killer: Mir fällt auf, das Du, von dem was man Dir erzählt, nichts gescheites draus machst oder ignorierst. Wieso? Wieso machst Du in der Funktion 2 identische Warteschleifen in Dein "Hauptprogramm" rein und rufts nicht eine "Warte-Routine" einfach 2 mal mit RCALL (oben schon erwähnt) auf? Man kann der Warterei auch r19 als Parameter übergeben wie lange gewartet werden soll, somit auch variabel. MfG Andi
Ach ne. Ich kann leider nicht alle wünsche ausführen. Da man mir gesagt hat das ich kein rcall verwenden soll sondern die schleife direkt einbinden soll. Mach ich das halt auch. Man hat nicht gesagt ich soll keine idenntische machen habe ich auch nicht die sind von der Zeit gleich. Ich denk mal das es nicht shclim ist. Es ging wohl darum das ich eine Schleife A und eine Schleife B habe und dies ist auch der Fall. Der NETTE TIP :-D Mit dem Simulator ist gut. Ich werde mit ihm jetzt etwas rumspielen, und ich sehe das die schleife so doch festhängt.
@Andreas: weil ich ihm geraten habe, erstmal den Funktionsaufruf wegzulassen, um möglichst wenig Fehlerquellen zu haben, s.o. Stefan
Danke :-D Der hängt doch nicht in der shcleife da sah erst nur so aus. Wenn die Simulation Zeitecht ist dann war die shcleife auf jedenfall zu lang. HAbs jetz geändert. Trozdem leuchten beide. Ich versteh das nicht. Laut simulato muss es so gehen. ER macht wennd ei befehle stimmt erst die eine LED an dann kommt die schleife und dann macht er die andere LED und die letze wieder aus an dann kommt wieder schleife und so weiter. Doch leuchten tun die beide :-/
Spiel ein bischen mit der Schleifenverzögerung rum. Wahrscheinlich bist Du wieder zu schnell (64.000 Durchläufe bei 16 Mhz(?)). Schau genau hin! Sind die LEDs etwas dunkler als beim "Nur-Einschalten"? Welche Spannung misst Du jetzt an den Portpins? Alle Werte ausser VCC und GND deuten darauf hin, dass der Pin doch toggelt - nur zu schnell zum Hinschauen. Stefan
Danke es geht, wenn ich jetzt auf ff alles stelle dann gehts. Zwar langsam aber "ES GEHT" :-DDDDDD Endlich habe ich es geschaft 2 LED zum wechseln zu bringen. Natürlich mit eurer Hilfe. Jetzt erstmal sicherhitskopier und mal schauen was ich draus machen kann. DANKE an alle hier. Die irgendwie mir weitergeholfen habe :-DDDDD
Noch ein Hinweis: Guck mal (beim simulieren) links oben im Fenster "I/O View" -> Processor. Dort ist der "Cycle Counter", der die Takte mitzählt (kann man durch Doppelklick auch setzen). "Stop Watch" berechnet die zugehörige Zeit in (s) bezogen auf die eingestellte Frequenz. Im Menü "Debug"->"AVR Simulator Options" kannst Du Deine Frequenz vorgeben. Bei dieser Deiner Schleife, --------------------------------- warteA: ldi r19, 0x01 w1a: ldi r18, 0x64 w2a: ldi r17, 0x64 w3a: dec r17 BRNE w3a dec r18 BRNE w2a dec r19 BRNE w1a --------------------------------- erhalte ich so eine Zeit von ca. 2,5 ms bei 12MHz Takt.
Wenn ich das so sehe, wie hier stundenlang Wartezeiten ausgetüftelt werden. Also der Asemmbler hat einen Präprozessor der sehr gerne für Dich Konstanten bis zu 32Bit berechnet (aber keine Kommazahlen !). Die Operanden byte1() ... byte4() dienen der besser lesbaren Schreibweise der einzelnen Bytes. Und dann sollte man sich noch SUBI und SBCI genauer angucken, die ideal für Rechnen >8Bit geeignet sind. Mit 3 Byte kann man dann bis zu 24 Bit Wartezeiten erzeugen:
1 | .equ XTAL = 16000000 ;Quarztakt (16MHz) |
2 | |
3 | .equ Warte1 = 10 ;10Hz (100ms) |
4 | |
5 | warten1: |
6 | ldi r16, byte1(XTAL / Warte1 / 5) |
7 | ldi r17, byte2(XTAL / Warte1 / 5) |
8 | ldi r18, byte3(XTAL / Warte1 / 5) |
9 | _warte11: |
10 | subi r16, byte1(1) ; 1 Zyklus |
11 | sbci r17, byte2(1) ; 1 Zyklus |
12 | sbci r18, byte3(1) ; 1 Zyklus |
13 | brne _warte11 ; 2 Zyklen |
14 | ; = 5 Zyklen |
15 | ret |
Du brauchst nur bei Warte1 einen anderen Wert eintragen und der Assembler rechnet dann die richtigen Ladewerte für Dich vollautomatisch aus. Peter
@Peter Da Du grad so schön aus dem Nähkästchen plauderst: gibt es einen Weg, die Taktzyklen bei WinAVR/GCC für ein "konstantes, lineares Programmstück" irgendwie automatisch vom Compiler/Präprozessor berechnen zu lassen und dies dann im Programm zu verwenden?
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.