Hallo! Folgendes Programm will einfach nicht funktionieren und ich finde den Fehler nicht! .include "8515def.inc" ldi r16, 0x01 out DDRC, r16 loop: in r16, PINC andi r16, 0b00100011 cpi r16, 0b00100001 breq L2 sbi portc,0 rjmp loop L2: cbi Portc, 0 rjmp loop Struktogramm dazu: R16=PINC R16=R16 und 0x23 R1===x021 JA NEIN PC6=0 PC6=1 Hoffe könnt mir weiter helfen! Gruß Dominik
andi r16, 0b00100011 cpi r16, 0b00100001 breq L2 Seh ich das richtig,das du lediglich einen Taster an PortC.5 angeschlossen hast und damit eine LED an PortC.0 steuern möchtest?Wieso maskierst du dann auch die Bits 0 und 1?Oder möchtest du noch einen Schalter an PortC.1 mit einbeziehen? Schau dir vielleicht auch mal die Befehle BRTS/BRTC (branch T set/clear) und BST/BLD (bit load/store),damit kann man einfach testen,ob bestimmte Bits in einem Register gesetzt sind und dann entsprechen springen.
Hallo! Probleme hab ich schonb mit dem Struktorgramm.. ich verstehe das nicht.. bzw kann es nicht lesen..
> Folgendes Programm will einfach nicht funktionieren und ich finde den > Fehler nicht! Also noch einmal... Was genau soll das Programm denn tun?Hast du konkrete Hardware auf der es laufen soll oder simulierst du den Mega8515 im z.B AVR-Studio?Lass dir doch mal nicht alles aus der Nase ziehen.Ich könnte jetzt raten,was das Programm beabsichtigt (Hausaufgaben sind doch immer recht das selbe ;) ),aber damit ist dir nicht geholfen. Übrigens,in deinem Struktogramm soll doch bestimmt R16 == 0x21 stehen,oder?
Hallo! Ist keine Hausaufgabe.. ich lerne für ne Klausur und das ist ne beispielaufgabe wie sie wahrscheinlich kommt... Leider drängt die Zeit sehr..eigentlich versuche ich mir sowas selber beizubringen, aber bis Dienstag wird es eng. Also ich will das ganze auf nem STK500 laufen lassen. Problem hier ist ja, dass die Taster low-aktiv sind, was die Sache nicht gerade leichter macht. Bin sowas von verwirrt, dass ich überhaupt nichts mehr auf die Reihe bringe... Wir, also die ganze Klasse, stehen vor nem risen Rätsel. Unser Lehrer kann uns den scheiss einfach nicht beibrinmgen!
Lies dir bitte mal in Ruhe das Tutorial hier auf der Seite durch,da stehen die Grundlagen eigentlich recht verständlich beschrieben drin.Dein LED-Problem z.B hier http://www.mikrocontroller.net/articles/AVR-Tutorial:_IO-Grundlagen Versuch zu verstehen,was die einzelnen Assemblerbefehle bewirken.Dann gehst du Schritt für Schritt durch das Programm,schreib dir dabei ruhig heraus,was in den einzelnen Registern nach jedem Befehl steht.Die Befehle sind ganz hinten im Datenblatt des Mikrocontrollers (unter www.atmel.com -> products -> mikrocontroller -> avr-risc 8bit zu bekommen) kurz beschrieben. Zu deinem Timer-Problem gibt´s auf dieser Seite hier auch ein Tutorial.Das benutzt zwar C als Programmiersprache,die Funktionsweise des Timers (Prescaler,Bitbreite,Interrupts) ist allerdings immer die selbe.Es werden stets in einigen Register(n) einzelne Bits gesetzt,die dann festlegen,wie der Timer funktioniert. http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Die_Timer.2FCounter_des_AVR
Hallo! Habe das Programm nochmal neu geschrieben, aber immer noch keine Funktion... Set r16 Out DDRC, r16 L1: IN r16, pinc andi r16 0b00100011 CPI r16, 0b00100001 breq L2 L2: sbi 0b01000000 rjmp L1 Ich hab mir zwar das Tutorial schon agesehen, aber bis morgen werd ich das niemals schaffen. Muss ja vormittags auch arbeiten. Hoffe auf Antwort! Danke im Vorraus! Dominik
Ich kann dir eigentlich nur raten, dass du das Programm mit dem AVR-Studio Simulator Schritt für Schritt duchgehst. Du kannst dir alle Registerinhalt ansehen und siehst auch welcher Befehl was bewirkt, bzw. welche Auswirkungen er hat. Das geht immer noch am schnellsten, vor allem deshalb weil du dann auch verstehst warum verschiedene Dinge so gemacht sind.
Und übrigens. Unter "will einfach nicht funktionieren" kann sich niemand was vorstellen. Was sollte den passieren? Was passiert statt dessen? Sollte passieren: Das ist wohl so, dass das Pgm beim Drücken des Tasters an C1 eine Aktion auslöst. Und zwar nur dann wenn C1 gedrückt ist und die Taster an C0 und C5 nicht gedrückt sind. Alle anderen Taster sind egal. Was soll passieren? Die LED an C6 soll angehen. Mit andi r16, 0b00100011 maskierst du dir besagte 3 Tastereingänge heraus, dort wo die 1-en stehen. Alle anderen (durch die 0-en in der UND-Maske) sind uninteressant und werden im Ergebnis auf jeden Fall 0. Vom eingelesenen Pin-Zustand sind also alle Bits mit Ausnahme der Bits 0, 1 und 5 auf jeden Fall 0. Der Inhalt der Bits 0, 1 und 5 hängt davon ab, wie die Taster stehen. Wenn ein Taster nicht gedrückt ist, bleibt da eine 1 übrig. Wenn ein Taster gedrückt ist, wird das Bit 0. cpi r16, 0b00100001 Das wird jetzt gestestet. Und zwar fordert der Test, dass Bit5 1 sein muss (und damit der Taster nicht gedrückt ist). Weiter muss auch Bit0 eine 1 aufweisen, der Taster aber auch nicht gedrückt sein. Nur Bit1 muss eine 0 haben, der Taster muss also gedrückt sein. Nur: Damit das so funktioniert, müssen am Port aber auch die Pins 0, 1 und 5 auf Eingang geschaltet sein! Ansonsten kann das natürlich nie funktionieren. Nur das passiert nicht. ldi r16, 0x01 out DDRC, r16 0x01, das ist 0b00000001 Das heist: Du schaltest Bit0 auf Ausgang! Wenn der aber auf Ausgang steht, dann kannst du den nicht als Eingang vom Taster benutzen! Vielleicht sagt aber deine Vorgabe aber auch, dass du nur einen Taster abfragen sollst. Dann frag ich mich aber wie du auf die UND-Maske und den Vergleichswert gekommen bist. Vielleicht solltest du auch das hier mal studieren http://www.mikrocontroller.net/articles/AVR-Tutorial:_IO-Grundlagen
ahhhhh... jetzt langsam dämmert es mir.... Super... heisst also, dass ldi r16, 0b01000000 out DDRC, r16 richtig wäre oder? Jetzt habe ich noch eine Frage auf die ich noch keine Antowrt gefunden habe.. In manchen Programmen die wir von unserem Lehrer bekommen haben heisst es PORTC, PCO oder PORTC, 0 wo ist denn da der unterschied oder gibt es da gar keinen? Wofür steht denn dann das PC vor der 0? Fragen über Fragen, aber den "Bock" in dem Programm finde ich jetzt bestimmt. Aufjedenfall hat das hier gerade mal mehr gebracht als die letzten 2 Monate in der Schule... Bedanke mich schonmal für die Engelsgeduld.
Frage an das Forum: Hat das STK500 eigentlich an den Tastern Pull Up Widerstände oder müssen die AVR internen benutzt werden?
kann nur sagen, dass das STK500 eine 1 an den Tastern hat, wenn diese nicht gedrückt sind.
@Karl Heinz:
Das STK500 hat an jedem Taster einen zusätzlichen Pull-Up. Die
µC-internen müssen nicht aktiviert werden.
@Dominik:
> sbi 0b01000000
Der sbi-Befehl hat zwei Operanden. Das macht so keinen Sinn.
Noch ein kleiner Tip: Assembler ist zwar nicht case-sensitiv, aber
gewöhne Dir trotzdem an, die Befehle in Assembler entweder immer in
Großbuchstaben oder immer in Kleinbuchstaben zu schreiben, aber nicht
beides auf einmal in einem Quelltext. Das erschwert das Lesen ungemein.
Ich persönlich finde die Kleinbuchstaben-Variante besser, v.a. dann,
wenn man zusätzlich (oder in Zukunft) in einer Hochsprache (C)
programmieren will. Da gewöhnt man sich dann gar nicht erst an,
Anweisungen GROSS zu schreiben. Sinnvolle Sache: Schlüsselwörter (in
Assembler mnemonics (also Befehle) und Assembler-Direktiven, in C
Anweisungen, Typen, Variablen, Funktionsbezeichner...) generell in
Kleinbuchstaben und nur Makros (also selbstdefinierter Kram) in
GROSSBUCHSTABEN. Da weiß man dann auf den ersten Blick, was man da vor
sich hat.
PORTC, 0 ist aber kein AVR-Assembler denke das ist eher 8051 oder was anderes. Woher kommen die 5V an den Pin durch externen oder internen Pullup? Einen einzelnen Pin z.b. PortD Pin7 frägt man am leichtesten so ab sbic pind, 7 oder sbis pind,7 je nach dem ob der Pin low oder high ist wird dann der nächste Befehl übersprungen. Wenn allerdings einen bestimmt Tatenkombination gefragt ist mache ich das auch mit einer und Verknüpfung und vergleiche es danach. Hier nochmal ein vollständiges Beispiel. Abfrage_pind7: sbic pind, 7 ;Überspringe nächsten Befehl wenn pind7 low(clear) rjmp pind7_high ;wenn pind7 high springe zur folgenden Routine pind7_low: rjmp Abfrage_pind7 ;Polling, gehe wieder zur Tastenabfrage pind7_high: sbr status, 0b00000001 ;Angenommen PortC hat lauter Status Leds angeschlossen und du willst nur die eine setzen oder löschen ohne die anderen zu beeinflussen out portc, status
@Thomas O.: "PORTC, 0" ist überhaupt kein Assembler, sondern es sollte vermutlich nur als Beispiel dienen. @Dominik: Wenn da irgendwas mit "sbi PORTC, PC0" o.ä. steht, dann heißt das, dass da eine Definition aus der Headerdatei oder eine selbstgemachte Definition benutzt wird. Entweder in der "irgendeinAVRdef.inc" oder im eigenen Programm steht eine .equ-Direktive der Art .equ PC0 = 0 An jeder Stelle, an der "PC0" von da an im Programm auftaucht, wird es vom Assembler durch "0" ersetzt. Das dient lediglich der besseren Lesbarkeit des Programms.
Hallo Johnny...
was meinst du damit?
@Dominik:
> sbi 0b01000000
Der sbi-Befehl hat zwei Operanden. Das macht so keinen Sinn.
Gruß
Dominik
> was meinst du damit? > > @Dominik: > > sbi 0b01000000 > Der sbi-Befehl hat zwei Operanden. Das macht so keinen Sinn. Schau bitte ins Datenblatt. Im AVR Studio geht das besonders einfach. Setze den Cursor in deinem Code Fenster auf das sbi und drücke F1 sbi will 2 Argumente haben. sbi - Set Bit in I/O Register welches I/O Register ? welches Bit ? daher kann sbi 0b01000000 nicht stimmen. Mindestens eine Angabe (entweder der Port oder die Bitnummer) fehlt.
Also, der sbi Befehl bedeutet soviel wie set bit! Ich empfehle dir, die langformen der Befehle anzuschauen, meistens sind die so logisch, dass der Befehl nachher selbsterklärend ist, man musses nur vorher mal gehört haben. Du hast jetzt also gesagt set bit 0b010000000 ... damit hast du ja aber kein ziel gesagt, in welchem register das bit eigentlich gesetzt werden soll. Außerdem ist 0b01000000 eine Byteangabe, nämlich bit 6, das du jetzt setzen willst! also nimmst du z.b. das register 16 als zwischenspeicher. Die Register r0 - r31 beinhalten jeweils 8 bit, also 1 byte. Du benutzt sie um Werte für kurze Zeit Zwischenzuspeichern und um eine Verbindung zwischen den verschiedenen "Einheiten" und der ALU, also der Recheneinheit herzustellen. Das heisst, wenn du ein anliegendes HIGH oder LOW an einem Portpin erkennen willst, musst du dies über ein Register einlesen, bevor du dann mit dem jeweiligen Wert im Register weiter rechnen kannst! Gleichzeitig musst du, wenn du ein Portpin setzten willst, dies zuerst in ein Register laden und dieses Register dann an den jeweiligen Port ausgeben! wenn du nun also bit 6 setzten willst, dann schreibst du zum Beispiel: clr r16 ; r16 auf 0 setzen sbi r16,6 ; setze bit 6 in r16 also 0b01000000 ich weiss jetzt nicht was du mit diesem wert machen willst, du könntest ihn nun aber z.b. auf einen Port legen: out PORTC,r16 Also nochmals: die 31 register stellen verbindungen zu allem her und eigentlich können alle rechnungen mur mit ihnen ausgeführt werden. Wenn du genug Register frei hast, dann arbeite nur mit r16 - r31 für den Anfang. r0 - r15 haben einschränkungen, dass würde dich jetzt aber verwirren wenn ich dir das erklären würde. Also folgendes geht NICHT!!! : out PORTC,0b01000000 oder sbi 0b01000000 (würde ja auch keinen sinn geben, woher soll irgendjmd., geschweige denn der assemblierer wissen, wo er das bitmuster hinsetzen soll?) Also das ist jetzt alles bewusst sehr primitiv erklärt, damit du es besser verstehen kannst.
Naja, 0b01000000 ist für beide Operanden zu viel. Syntax: sbi I/O-Register, Bit wobei "I/O-Register" von 0..31 geht (untere 32 Register), wobei hier natürlich sinnigerweise der in der Headerdatei definierte Registername angegeben werden sollte, und "Bit" eine Zahl von 0..7 sein muss (also die laufende Nummer des zu setzenden Bits im Register).
Hallo zusammen, also die LED6 ist nun am leuchten, aber die soll ja nur leuchten wenn die Taster SW0 und SW1 gedrückt werden. Aus bekomme ich die LED auch nicht durch drücken .include "8515def.inc" ldi r16, 0b01000000 out DDRC, r16 loop: in r16, PINC andi r16,0b11111100 cpi r16, 0b11111100 breq L2 clr r16 sbi portc,6 rjmp loop L2: cbi Portc,6 rjmp loop Ihr seid sicher völlig am verzweifeln an mir! Gruß Dominik
wie wärs wenn du uns endlcih mal einen kleinen schaltplan servierst? Vorher kann man wohl nicht sagen, ob dein code das macht was er soll!
Habe ja keinen Schaltplan! Simuliere das alles auf dem STK500 Laut Aufgabenstellung soll bei Drücken der Taster SW0 und SW1 die LED6 leuchten. mehr steht selber nicht auf dem Arbeitsblatt.
> andi r16,0b11111100
Du hast noch nicht kapiert, was es mit diesen UND
und ODER Sachen auf sich hat.
Die Wahrheitstabelle für UND lautet
A B Ergebnis
0 0 0
0 1 0
1 0 0
1 1 1
Das Ergebnis ist also nur dann wahr (1), wenn sowohl
A als auch B wahr sind.
Wenn du jetzt 2 8stellige Binärzahlen hast,
die eine hast du zb von einem PIN eingelesen
und lautet
0b10010110
und die zweite ist die Zahl die du direkt beim andi
angibst
0b11111100
dann werden die miteinander verundet, indem Bitposition
für Bitposition durchgegeangen wird
0b10010110
0b11111100
und jeweils die korrespondierenden Stellen miteinander
UND Verknüpft werden: (Das Ergebnis ist nur dann 1 wenn
sowohl A als auch B 1 sind.)
0b10010110 <- Das ist der Wert vom PIN
0b11111100 <- Das ist die Maske vom andi
----------
UND 0b10010100
Wenn du jetzt mal das Ergebnis mit der Zahl die
du vom PIN her hast vergleichst, dann fällt auf,
dass im Ergebnis der gleiche Wert wie in PIN auftaucht
genau dort, wo in der Maske eine 1 war. An den Stellen
an denen in der Maske eine 0 war, ist im Ergebnis
auf jeden Fall eine 0. Das ist auch logisch weil
bei einer UND Verknüpfung das Ergebnis sofort 0 ist,
wenn einer der beiden Partner, A oder B, 0 sind.
d.h. aber auch, mit
andi r16,0b11111100
hast du alles wegmaskiert, was dich eigentlich interessiert.
Du möchtest wissen, wie der Zustand der untersten beiden
Bits ist. Alle anderen interessieren dich nicht. Nur:
Mit dem andi, so wie du die Maske geschrieben hast, maskierst
du dir gerade die beiden dich interessierenden Bits weg (setzt
sie auf jeden Fall auf 0) und lässt alle anderen Bits
unangetastet.
Ich hoffe das ist jetzt etwas klarer, wie die Geschichte
mit Maskierung mittels UND eigentlich funktioniert.
> cpi r16, 0b11111100
Der ist dann auch falsch.
Wenn die Maskierung richtig ist, dann bleibt in
R16 klarerweise eine komplette 0 übrig.
Die Bits 2 bis 7 werden durch den UND auf 0
gesetzt, und wenn dann noch die Taster SW0 und SW1
gedrückt sind, dann sind alle Bits 0
Wie ein UND funktioniert ist mir klar... so ein paar Grundlagen habe ich schon ;-) auch wenns nicht so aussieht, aber irgendwie hab ich hier ne totale Denkblockade bei ANDI setze ich alle Bits (Taster) auf 1, die ich später benutzen will in dem Falle jetzt 0b00000011 (Taster SW0 und Taster SW1), richtig? Aber wie ich auf den Wert beim CPI komme ist mir immer noch nicht klar! da kommt doch nicht auch 0b00000011 ein oder? langsam wirds mir schon peinlich weiter zu fragen! Gruß Dominik Grossen Dank erstmal an alle die sich so eine Mühe mit mir geben!
Ich habs.... jetzt weiss ich auch endlich wo der Bock lag... da ich die Taster und die LEDs mit Flachbandkabel verbunden habe und die Taster auf PortA liegen und die LEDs auf PortC, konnte ich lange versuchen den Wertder Taster auf PortC zu lesen. Das programm läuft jetzt auf meinem Board include "8515def.inc" ldi r16, 0b01000000 out DDRC, r16 loop: in r16, PINA andi r16,0b00000011 cpi r16, 0b00000000 breq L2 sbi portc,6 rjmp loop L2: cbi Portc,6 rjmp loop
Ja.. ich müsste mich selber steinigen! ;-) Eine Finale Frage habe ich noch.. das STK500 ist ja nun high-aktiv... sollten die Taster nun low-aktiv sein.. müsste ich ja nur bei dem CPI die letzten beiden Bits auf 1 setzen richtig?
> das STK500 ist ja nun high-aktiv...
Wenn Du die Taster meinst: Nein, die sind Low-aktiv! Gedrückter Taster
-> Low-Pegel am Pin...
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.