Forum: Mikrocontroller und Digitale Elektronik Probleme bei Programm (Assembler)


von Dominik F. (dominik1202)


Lesenswert?

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

von Ronny (Gast)


Lesenswert?

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.

von Dominik F. (dominik1202)


Lesenswert?

Hallo!

Probleme hab ich schonb mit dem Struktorgramm..

ich verstehe das nicht.. bzw kann es nicht lesen..


von Ronny (Gast)


Lesenswert?

> 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?

von Dominik F. (dominik1202)


Lesenswert?

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!


von Ronny (Gast)


Lesenswert?

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

von Dominik (Gast)


Lesenswert?

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

von Karl heinz B. (kbucheg)


Lesenswert?

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.

von Karl heinz B. (kbucheg)


Lesenswert?

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

von Dominik (Gast)


Lesenswert?

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.

von Dominik (Gast)


Lesenswert?

Programmvorgabe ist S1 und S2 betätigt, dann LED 6

von Karl heinz B. (kbucheg)


Lesenswert?

Frage an das Forum:
Hat das STK500 eigentlich an den Tastern Pull Up Widerstände
oder müssen die AVR internen benutzt werden?

von Dominik (Gast)


Lesenswert?

kann nur sagen, dass das STK500 eine 1 an den Tastern hat, wenn diese 
nicht gedrückt sind.

von johnny.m (Gast)


Lesenswert?

@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.

von Thomas (kosmos)


Lesenswert?

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

von johnny.m (Gast)


Lesenswert?

@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.

von Dominik (Gast)


Lesenswert?

Hallo Johnny...

was meinst du damit?

@Dominik:
> sbi 0b01000000
Der sbi-Befehl hat zwei Operanden. Das macht so keinen Sinn.



Gruß
Dominik

von Karl heinz B. (kbucheg)


Lesenswert?

> 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.




von Hansi L. (fabian87)


Lesenswert?

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.

von johnny.m (Gast)


Lesenswert?

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).

von Dominik (Gast)


Lesenswert?

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

von Hansi L. (fabian87)


Lesenswert?

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!

von Dominik (Gast)


Lesenswert?

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.

von Karl heinz B. (kbucheg)


Lesenswert?

> 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.

von Karl heinz B. (kbucheg)


Lesenswert?

> 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

von Dominik (Gast)


Lesenswert?

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!

von Dominik (Gast)


Lesenswert?

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

von Hansi L. (fabian87)


Lesenswert?

na klasse

von Dominik (Gast)


Lesenswert?

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?

von johnny.m (Gast)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.