Ich programmiere erst seit kurzem mit Assembler und brauch Hilfe. Mein
Programm soll eine binäre Zahl am PORTC einlesen und diese Zahl dann auf
ein 7 Segment Display anzeigen. Wenn aber ein Signal an PORTC anliegt
passiert nichts. Ich habe alle Verbindungen geprüft also kann es nicht
daran liegen.
1
.include "m328pdef.inc"
2
3
ldi r16, 0b01111111 ; PB0-6 as outputs (7 segment display)
Sebastian schrieb:> ldi r16, PINC ; PINC read
Das tut nicht das, was du planst. Du lädst hier nur die Adresse des PINC
Register als direkten Wert in R16. Du möchtest vermutlich
an Karl M.:
- es ist gar kein Interrupt aktiviert
- der Stack wird gar nicht benutzt
- beim ATmega328P ist der 'Initial Value' des Stackpointers ohnehin
=RAMEND
ohne Stack-benutzung (call/push/pop/ret) gehts auch ohne SPL/SPH.
Interrupt-Tabelle ist ohne Interrupte auch nicht notwendig.
Für simplen Code ohne Call/Ret reichts doch :)
Matthias hat ja das Hauptproblem schon beschrieben.
IN R16, PINC
Sebastian denk mal über eine Tabelle mit den Daten nach:
Z-Register mit Anfang laden.
Offset durch Zahl dargestellt aufaddieren.
LPM mit Z-Register
Karl M. schrieb:> Die Interrupt-Vektor-Tabelle fehlt und die Initialisierung des Stacks,> insbesondere des Stack-Pointers SP[H:L].
So ein Bullshit.
Eine (vollständige) Interruptvektortabelle braucht man sowieso praktisch
nie.
Allenfalls braucht man einzelne Interruptvektoren. Eben genau die, die
man tatsächlich benutzt. Er benutzt exakt keinen, also braucht er auch
keinen. Alles, was er benutzt, ist der Reset-Vektor. Und es spricht
absolut nichts dagegen, in dem Fall, das man keine Interrupts braucht,
genau dort mit dem main-code anzufangen. Alles andere wäre sinnlos
verschwendeter Flash...
Dasselbe Drama gilt für den Stack. Den braucht man genau dann, wenn man
Interrupts benutzen möchte oder Unterprogramme aufrufen möchte oder
irgendwas pushen oder poppen möchte. Macht er aber alles nicht. also ist
die Initialiserung des Stacks überflüssig. Verschwendet nur Rechenzeit
(wenn auch in einem sehr überschaubaren Ausmass). Bei einem P328 wäre es
sogar doppelt sinnlose Verschwendung, der initialisiert nämlich seinen
Stack schon per Hardware auf RAMTOP, wie alle "neueren" AVRs es seit
ewigen Zeiten tun...
Thomas O. schrieb:> ldi r16, 0x00ff> out ddrc, r16
Was soll das Laden eines 16-bit Wertes in ein 8-Bit Register denn
bewirken? Es sei angemerkt, das die Ports eines AVR nach Reset auf Input
stehen. Nur eventuelle Pullups sollten konfiguriert werden:
1
ldi r16,0xff
2
out portc,r16
Sebastian schrieb:> cpi r16, 0b0000000 ; if(PINC == 0)> breq number0
Hier genau die Stellen zählen. Es sind bei dir nur 7, der Port (und R16)
haben aber 8.
Asche auf mein Haupt, hatte erst die Ports verwechselt der eine war ja
schon als Ausgang und als ich das FF in 00 korrigieren wollte war ich
wohl zu schnell.
Sebastian schrieb:> number9:> ldi r17, 0b01111011 ; a, b, c, d, f, g
Ab hier läuft das Programm durch den ganzen Flash, bis es wieder bei
0x0000 ankommt.
Das Programm enthält aber noch viel mehr Mumpitz. Assembler scheint
nicht so Dein Ding zu sein.
Hallo,
Peter D. schrieb:> Assembler scheint nicht so Dein Ding zu sein.
Wie er schon im Eröffnungsbeitrag schrieb:
> Ich programmiere erst seit kurzem mit Assembler und brauch Hilfe.
rhf
Matthias S. schrieb:> Sebastian schrieb:>> cpi r16, 0b0000000 ; if(PINC == 0)>> breq number0>> Hier genau die Stellen zählen. Es sind bei dir nur 7, der Port (und R16)> haben aber 8.
Das ist dem Compiler so etwas von egal. Auch aus "0b0" würde er ein 0x00
generieren.
Roland F. schrieb:> Wie er schon im Eröffnungsbeitrag schrieb:>> Ich programmiere erst seit kurzem mit Assembler und brauch Hilfe.
Auch als Anfänger darf man Tutorials lesen, das Instruction Set mal
aufschlagen und das Gehirn einschalten.
Was z.B. erwartet man, was nach 10 "ldi r17,x" Befehlen wohl in R17
steht?
Auch sollte die letzte Zeile eines Programms immer ein jmp oder ret
sein.
Die Kommentare in C-Syntax lassen die Frage offen, warum er nicht gleich
C nimmt.
Sebastian schrieb:> breq number9>> out PORTB, r17 ; turn on leds
Ein C-Complier würde Dir hier ein
"warning: 'r17' is used uninitialized in this function"
vor den Latz knallen.
Versuch erstmal, ein Programm mit nur einer Bedingung zum Laufen zu
bringen.
Wolfgang schrieb:> Das ist dem Compiler so etwas von egal.
Es gibt keinen Compiler bei Assembler. Und es ist nicht egal, wenn man
z.B. die letzte Stelle wirklich abfragen möchte. Notiert man binär, ist
es wirklich sinnvoll, auch die 8 Bit zu beachten.
Kleine strukturelle Änderung hilft:
In jedem der "numberx:"-Blöcke als zweite Zeile ein "rjmp ausgabe"
hinzufügen, vor dem out nach portb ein label "ausgabe:" einbauen, und es
sollte schon besser laufen. Elegant ist es trotzdem nicht. ;-)
Hallo,
Peter D. schrieb:> Roland F. schrieb:>> Wie er schon im Eröffnungsbeitrag schrieb:>>> Ich programmiere erst seit kurzem mit Assembler und brauch Hilfe.>> Auch als Anfänger darf man Tutorials lesen, das Instruction Set mal> aufschlagen und das Gehirn einschalten.
Oder in einen (Fach-)Forum nachfragen! Denn genau dafür ist so eine
Diskussionsplattform ja eigentlich gedacht.
Warum fühlen sich hier so oft Diskussionsteilnehmer (in diesem Fall du)
extrem genervt von scheinbar trivialen Frage? Bleiben wir doch mal beim
aktuellen Fall:
- Sebastian hat sich eine Aufgabe gestellt.
-> das zeigt Interesse
- er angefangen eine Lösung zu suchen und dazu ein Programm geschrieben
-> Eigeninitiative, wird hier immer gefordert.
- Das Programm funktioniert nicht, er weiß auf mangelnder Kenntnis und
Erfahrung nicht mehr weiter und bittet um Hilfe.
Ich würde sagen, er hat alles richtig gemacht. Als Reaktion erhält er
z.B von dir die Zurechtweisung, er solle sich doch mal Tutorials
durchlesen und du unterstellst ihm gedankenloses Handeln.
Was soll das? Das ist destruktiv und demotivierend(1) gegenüber einer
Person, die augenscheinlich etwas lernen will. Wenn dich solche Beiträge
so sehr nerven, halte doch einfach mal die Hände von deiner Tastatur weg
und antworte gar nicht. Das spart dir dann Zeit und vor allem Nerven.
rhf
P.S.:
(1) Übrigens, sollte Demotivation Ziel deines Beitrag gewesen sein, hier
mal ein kleines "Tutorial" zur Weiterbildung von dem Fachmann für
solche Fragen:
https://www.youtube.com/watch?v=1x6R6z1_vMk
:-))
Hi
Also, viele unsinnige Antworten, wenige, die das Problem angehen. Ganz
toll finde du den Hinweis, doch C zu erlernen. Zum Prinzip, Assembler
ist eine Programmiersprache der einfachsten Art. Die Befehle sind
simpel. Höhere Programmiersprachen sind mit komplexen Befehlen bestückt.
Aber, Kern des Problems, man muss programeren können. Nicht jeder, der
einen Pinsel halten kann, ist ein Picasso oder Rembrandt. Um dahin zu
kommen, bedarf es Übung und Talent. Nun zum Thema.
En Controller holt sich aus seinem Speicher einen Befehl nach dem
anderen. Dazu hat er ein Register, den Prrogrammcounter,. Zuerst holt er
den Befehl LDI und eine dazugehörige Konstante. Den Wert dieser
Konstante schreibt er dann mit dem Befehl OUT in das Portsteuerregister.
(DDRx). Nun kommt die Marke Loop. Den Controller interessiert diese
Marke nicht, aber der Compiler, der aus den Assembler Anweisungen einen
Maschinencode generiert, merkt sch den Wert des Prrogrammcounter, also
die Adresse des aktuellen Befehles. Auch die Adressen der Marken Numbers
hat sich der Compiler durch eine entsprechende Berechnung der dortigen
Befehlsadresse gemerkt und ersetzt nun bei den nächsten Befehlen den
Markennamen mit der Adresse. Also ein BREQ number3 schreibt den
berechnete Adresse in den Prrogrammcounter. Somit wird der nächste
Befehl an der Marke Number3 geladen und der Programmcounter auf die
nächste Adresse gesetzt. Das dies Adresse vom Befehl LDI Konstante 4
ist, ist dem Controller egal und so arbeitet er weiter mit erhöhen des
Programmcounter s und dem Laden und bearbeiten der unter der
Speicheradresse enthaltenen Befehle. Findet er keine mehr, weil die
Speicherzelle noch nicht geschrieben ist macht er nichts, außer der
Erhöhung des Programmcounter s. Irgendwann läuft der Programmcounter auf
der höchste 16 Bit Adresse FFFFh und der nächste Wert wäre 10000h. Doch
die 1 im Überlauf ist mit 16 Bit nicht mehr abzubilden und es bleibt
nur die 0000h übrig. Und damit beginnt dein Programm von vorn. Das wäre
Mal der Programmierfehler und das hat nichts mit Assembler zu tun.
Die Lösung ist ein BRNE auf den nächsten Vergleich. Dazu mußt du
natürlich auch dort entsprechend Marken setzen. Z.B. check_2, check_3
usw.Hinter den BRNE setzt du ein CALL Numbers und der Befehlsfolge an
den Marken Numbers beendest du mit RET. Falls du noch Probleme hast,
melde die ruhig mit einer PN.
Gruß oldmax
Roland F. schrieb:> und du unterstellst ihm gedankenloses Handeln.
Ich setze auch bei einem Anfänger voraus, daß er weiß, daß Code in genau
der Reihenfolge abgearbeitet wird, wie er hingeschrieben wurde. Sprünge
führen nur die Sprungbefehle (BRANCH INSTRUCTIONS) aus.
Assembler ist da gnadenlos. Wenn man Unsinn hinschreibt, führt er auch
Unsinn aus.
Ich helfe auch Anfängern gerne, aber ein roter Faden sollte schon zu
erkennen sein.
Martin V. schrieb:> viele unsinnige Antworten, wenige, die das Problem angehen.
Ich würde empfehlen, zuerst mal eine einzige LED blinken zu lassen. Und
das zuallererst im Simulator!
> Um dahin zu kommen, bedarf es ÜbungDanach würde ich ein Lauflicht empfehlen (erst simpel von links nach
rechts, dann hin&her, dann mit beliebigem Muster, dann mit per Taster
verstellbarer Geschwindigkeit).
Wenn diese "Übungen" umgesetzt wurden, löst sich das Problem, um das es
hier im Thread geht, ganz von alleine, weil es gar nicht mehr
auftritt.
Roland F. schrieb:> Ich würde sagen, er hat alles richtig gemacht.
... aber er hat kein Durchhaltevermögen (obwohl er kurz vor dem Ziel
steht) und gibt sich keine Mühe. Mag hart klingen, ist aber so.
Denn dieses Problem kann man tatsächlich mit kostenloser Software und
frei zugänglichen Informationen selber lösen.
Ich hatte noch mehr geschrieben, das aber wieder gelöscht, weil es
offtopic ist. Und auch deine Auslassungen helfen dem TO im Grunde nicht
weiter, ausser dass er jetzt weiß, dass er "alles richtig gemacht" hat
(was irgendwie auch wieder ein wenig demotivierend ist, weil es ja
trotzdem nicht funktioniert)...
Zurück zur Sache:
was erscheint auf der Anzeige mit so einem Programmschnipsel:
1
ldi r17, 0b00110000;
2
out portc,r17;
Zeigt sie eine "1" oder ein "E"?
Und im Anhang noch ein Denkanstoß...
Lothar M. schrieb:> was erscheint auf der Anzeige mit so einem Programmschnipsel:ldi r17,> 0b00110000;> out Port portc,r17;
Nix.
Auf deinem Monitor allerdings:
error: PORTC: Unknown instruction or macro
Hi
@Lothar Warum zitierst du mich? Deiner Antwort auf das erste Zitat kann
ich nicht so richtig folgen. Im Übrigen tut er ja genau das, was du
vorschlägst, er will eine LED anschalten, auch wenn es eine
7Segmentanzeige ist. Fakt ist, das Programm führt den Out-Befehl gar
nicht aus, weil er nach dem Laden des Bitmusters nicht in die
Programmschleife zurückfindet. Und das habe ich ausführlich beschrieben
und wenn Stefan des Lesens mächtig ist, dann wird er verstehen, welchen
Fehler er gemacht hat. Die Arbeit mit Controller und Assembler setzt
schon ein wenig Kenntnisse der Hardware vorraus. Hochsprachen sind da
nicht ganz so anspruchsvoll, aber auch da gibt es ganz gemeine Fallen,
in die man tappen kann, wenn man die zeitliche Reihenfolge nicht
beachtet. Und diese Fehler sind in Hochsprachen nicht so offensichtlich
wie hier in Assembler. Mir ist es auch schon passiert, das ein
mathematisches Ergebnis von 0 von Pascal anders geliefert wurde wie von
Basic. Bei einer Kalenderberechnung lieferte Basic keine Null, sondern
ein kltzekleines 0,00000000irgendwas während die gleiche Formel n Pascal
das richtige Ergebnis lieferte. Da man ja weiß, das der Fehler
grundsätzlich vor dem Monitor sitzt, hat es mich schon einiges an Zeit
gekostet, bis der Fehler erkannt und mit einem kleinen Offset behoben
werden konnte.ok, ich schweife ab.
Grundsätzlich, wer Assembler anwendet, lernt seinen Controller
zwangsläufg so richtig kennen. Das Datenblatt ist Pflichtlektüre.
Assembler hat also nicht nur Nach- sondern auch Vorteile. Alles eine
Frage der Perspektive.
Gruß oldmax
Lothar M. schrieb:> Und im Anhang noch ein Denkanstoß...
...
loop:
ldi r16, PINC ; Eingnge einelesen
...
Das kann ja niemals gehen.
Ersetzen durch:
in r16,PORTC ; Port-C einlesen
Einen Pin kann man evtl. mit SBIC/SBIS testen.
Anfänger sollten sich erst mal an fertigen einfachen Programmen
versuchen.
Und für jeden Prozessor eine Standard Initialisierung.
Egal, ob man alle Funktionen braucht oder nicht.
Ich habe mich damals durch die Appl. AVR-242 durchgebissen.
Danach war Tasten und 7-Segment kein Problem mehr.
Vor allem den Code für die 7-Segment würde ich wie dort in Tabelle
ablegen.
Nicht wie hier über Sprünge.
Wehe, wenn die phys. Anschlüsse nicht mit dem PORT übereinstimmen.
Sollten da trotzdem nicht eher die PINs eingelesen werden?
Es ist aber auch echt heiß... ;-)
michael_ schrieb:> erst mal an fertigen einfachen Programmen versuchen.
Und wenn schon nicht fertig, dann wenigstens einfach. Das meinte ich mit
der blinkenden LED. In diesem Fall wäre das simpelste
LED-Einlesen-und-Ausgeben-Programm etwa so:
Lothar M. schrieb:> Uuups, korrigiert... ;-)
Jetzt sollte eine '1' auf der Anzeige erscheinen.
Andernfalls wäre das ein 'E', aber mit Dezimalpunkt :-)
Und man macht das normalerweise mit Tabellen, aber andersrum,
d.h. Seg_a = bit0 ... DP = bit7.
Lothar M. schrieb:> in r16,PORTC ; Port-C einlesen> Sollten da trotzdem nicht eher die PINs eingelesen werden?> Es ist aber auch echt heiß... ;-)
Neieiein!
Es geht nicht. Wie willst du ein Bit in einem Register ablegen?
Also das Port einlesen, was der TO sowieso möchte, und dann evtl. die
Pin einzeln behandeln.
Lothar M. schrieb:> in r16,PINC ; alle Pins vom PC einlesen
Neieiein! Ändern.
Hier mal die Applikation AVR-242.
http://ww1.microchip.com/downloads/en/AppNotes/doc1231.pdf
Hi
>Lothar M. schrieb:>> in r16,PINC ; alle Pins vom PC einlesen>Neieiein! Ändern.
Witzbold. Selbstverständlich werden die Ports über das PIN-Register
eingelesen:
PINC – The Port C Input Pins Address
MfG Spess
Hallo Lothar,
> ... aber er hat kein Durchhaltevermögen (obwohl er kurz vor dem Ziel> steht) ...
Schon mal auf die Idee gekommen, das er seinen Fehler "einfach nicht*
sieht?
> Denn dieses Problem kann man tatsächlich mit kostenloser Software und> frei zugänglichen Informationen selber lösen.
Naja, das gilt so ziemlich für jedes Problem das in diesem Forum
behandelt wird.
> ... ausser dass er jetzt weiß, dass er "alles richtig gemacht" hat> (was irgendwie auch wieder ein wenig demotivierend ist, weil es ja> trotzdem nicht funktioniert)...
Lesen hilft: mit richtig meinte ich, das er sich gemäß der hier immer
wieder geforderten Vorgehensweise bei Fragen richtig verhalten hat.
rhf
Hallo Peter,
> Ich setze auch bei einem Anfänger voraus, daß er weiß, daß Code in genau> der Reihenfolge abgearbeitet wird, wie er hingeschrieben wurde.
Vielleicht ist das das Grundproblem hier, das einfach zu viel
vorausgesetzt wird.
rhf
Roland F. schrieb:> Vielleicht ist das das Grundproblem hier, das einfach zu viel> vorausgesetzt wird.
Das glaube ich auch. Und wenn dann noch Leute wie 'michael_' kommen, die
nur zur Verwirrung beitragen, ist das noch weniger hilfreich.
Ein sinnvoller Weg wäre z.B.
1. Lese den Wert von PORTC ein und maskiere ihn auf sinnvolle Werte, um
Überschreitungen von Werten zu vermeiden.
2. Benutze diesen Wert als Zeiger in eine Tabelle, um das passende
Bitmuster für die 7-Segment Anzeige zu erhalten.
3. Schreibe den erhaltenen Tabellenwert auf den Port der Anzeige.
4. Springe zu 1.
michael_ schrieb:> Es geht nicht. Wie willst du ein Bit in einem Register ablegen?
Ich lege gleich alle 8 Bits des Pin-Registers parallel im R16 ab. So wie
das hier gemacht werden muss, weil ja anschließend dieses R16 mit einem
8-bit Wert verglichen wird.
Marc V. schrieb:> aber mit Dezimalpunkt
Du hast noch eine Chance. Als Tipp: das Bit 7 ist ein Eingang... ?
...wenn man statt dem DDRB das richtige Portregister konfiguriert.
Lothar M. schrieb:> michael_ schrieb:>> Es geht nicht. Wie willst du ein Bit in einem Register ablegen?> Ich lege gleich alle 8 Bits des Pin-Registers parallel im R16 ab. So wie> das hier gemacht werden muss, weil ja anschließend dieses R16 mit einem> 8-bit Wert verglichen wird.
Ist ja auch richtig. Man liest das gesamte Port (PORTC)ein.
spess53 schrieb:> Witzbold. Selbstverständlich werden die Ports über das PIN-Register> eingelesen:>> PINC – The Port C Input Pins Address
Dann zeig mal den gesamten Ausdruck.
Durch Komma getrennt muß dahinter noch das konkrete Pin kommen.
PINC,PC3 ; das 3. Beinchen am Port-C
Geht aber nicht mit dem IN-Befehl.
Lothar M. schrieb:> michael_ schrieb:>> erst mal an fertigen einfachen Programmen versuchen.> Und wenn schon nicht fertig, dann wenigstens einfach. Das meinte ich mit> der blinkenden LED. In diesem Fall wäre das simpelste> LED-Einlesen-und-Ausgeben-Programm etwa so:.include "m328pdef.inc">> ldi r16, 0b01111111 ; PB6..0 = Ausgang> out DDRB, r16 ; 7-SegDisp Bit 6..0 = abcdefg>> loop: ; jetzt gehts los> in r16,PINC ; alle Pins vom PC einlesen> out PORTD,r16 ; und geradeaus auf den PD ausgeben> jmp loop ; wieder von vorn beginnen
So richtig fertig ist das aber noch nicht?
Mindestens fehlt eine Zeitschleife ...
Aber "Hallo Welt" wäre erst mal eine blinkende LED.
michael_ schrieb:> Geht aber nicht mit dem IN-Befehl.
Nein, nur mit bestimmten In Registern. Und man liest damit aber kein Bit
ein, sondern man fragt es mit einem bedingten Sprungbefehl als SBIS oder
SBIC ab.
Marc V. schrieb:> Und hier ein Beispiel:
Da sieht doch cool aus. Ich hätte vermutlich, angeregt durch den
'Hexzahl auf 7-Segment' Thread einfach auf 0x0F maskiert und die 16
Zustände in die Tabelle geschrieben. Aber das ist nur ein Nerd-Spässchen
:-P
michael_ schrieb:> Mindestens fehlt eine Zeitschleife ...
Da fehlt überhaupt keine Zeitschleife. Der MC liest das ein und gibt es
aus. Da muss nichts gebremst werden - ist ja keine blinkende LED.
> Ist ja auch richtig. Man liest das gesamte Port (PORTC)ein.
Immer noch nicht. Man liest PINC, denn nur da finden sich die Zustände
der Inputports.
michael_ schrieb:> Dann zeig mal den gesamten Ausdruck.> Durch Komma getrennt muß dahinter noch das konkrete Pin kommen.> PINC,PC3 ; das 3. Beinchen am Port-C>> Geht aber nicht mit dem IN-Befehl.
Siehe bitte endlich ein, das du die Aufgabenstellung nicht verstanden
hast. Bitweises einlesen ist hier kontraproduktiv.
Lothar M. schrieb:> Marc V. schrieb:>> aber mit Dezimalpunkt> Du hast noch eine Chance. Als Tipp: das Bit 7 ist ein Eingang... ?
Ja, aber nur beim TO, normalerweise ergeben 7 Segmente und DP genau
8 bit und so wird es auch verbunden, angefangen bei bit0 und Segment a.
Matthias S. schrieb:> Es gibt keinen Compiler bei Assembler.
Irgendwer wird aus dem ASCII-Text schon die passenden Befehle für den µC
generieren. Von mir aus nenne das Ding Cross-Assembler.
Matthias S. schrieb:> 1. Lese den Wert von PORTC ein und maskiere ihn auf sinnvolle Werte, um> Überschreitungen von Werten zu vermeiden.
Mit maskieren alleine wird das wohl nichts, wenn man hinterher für die
Ausgabe nur den Zahlenraum von 0 bis 9 zur Verfügung hat.
Lothar M. schrieb:> michael_ schrieb:>> Geht aber nicht mit dem IN-Befehl.> Nein, nur mit bestimmten In Registern. Und man liest damit aber kein Bit> ein, sondern man fragt es mit einem bedingten Sprungbefehl als SBIS oder> SBIC ab.
Uff, fast hast du es richtig geschnallt.
Mit dem IN-Befehl kann man nur auf das Daten-Register zugreifen.
Dann gibt es noch das Direction-Register.
Und dann gibt es das PIN-Register.
Da geht dann das SBIC/SPIS und weitere.
Das sind drei verschiedene Sachen.
Matthias S. schrieb:> Marc V. schrieb:>> Und hier ein Beispiel:>> Da sieht doch cool aus. Ich hätte vermutlich, angeregt durch den> 'Hexzahl auf 7-Segment' Thread einfach auf 0x0F maskiert und die 16> Zustände in die Tabelle geschrieben. Aber das ist nur ein Nerd-Spässchen> :-P
Nur solange, wie nur ein 7-Segment.
Matthias S. schrieb:> michael_ schrieb:>> Mindestens fehlt eine Zeitschleife ...>> Da fehlt überhaupt keine Zeitschleife. Der MC liest das ein und gibt es> aus. Da muss nichts gebremst werden - ist ja keine blinkende LED.
Naja, es ging um "Hello Welt".
Matthias S. schrieb:> michael_ schrieb:>> Dann zeig mal den gesamten Ausdruck.>> Durch Komma getrennt muß dahinter noch das konkrete Pin kommen.>> PINC,PC3 ; das 3. Beinchen am Port-C>>>> Geht aber nicht mit dem IN-Befehl.>> Siehe bitte endlich ein, das du die Aufgabenstellung nicht verstanden> hast. Bitweises einlesen ist hier kontraproduktiv.
Uff!
Darum geht es ja hier, bitweises einlesen geht nicht!
Matthias S. schrieb:>> Ist ja auch richtig. Man liest das gesamte Port (PORTC)ein.>> Immer noch nicht. Man liest PINC, denn nur da finden sich die Zustände> der Inputports.
Vielleicht geht das in irgend einer Hochsprache, aber in Assembler geht
das nicht.
Da geht nur PORTC.
Hoffentlich ist das Elend bald zu Ende.
Hi Stefan
Wenn du diesen Thread noch folgst, vergißdas, was dir die
Pseudo-Experten sagen wollen. Kurz, warum du keine Ausgabe bei denen
Programm bekommst, legt daran, das du diesen Befehl nicht erreichst.
Warum habe du bereits geschrieben. Das Lesen der Eingänge wäre dann dein
zweiter Fehler gewesen, auch das ist bereits schon erwähnt worden,
allerdings vielleicht ein wenig verkompliziert. Also,einen Port einlesen
erfolgt nicht mit einem Ladebefehl LDI oder LDS sondern mit IN
(Register),PINx. Auch was die Beschaltung des Controllers betrifft, bin
ich mir nicht sicher, ob dir Pullup und pulldown Widerstände bekannt
sind. Deswegen, wenn du wirklich lernen willst, nimm Kontakt über eine
PN auf. Das was du hier liest, wird dich nur verwirren, weil selbst die
fachlichen Antworten schon abgehoben und in Selbstdarstellung gehen. (
Wie kann man eben Anfänger schon indirekte Adressierung vorschlagen, wo
noch nicht einmal eine ganz einfache Aufgabe gelöst werden kann????)
Also, ihr Superhelfer, schaltet Mal eine Stufe runter, wenn ihr das noch
könnt und lässt eure kleinen Spezialitäten erst Mal ruhen. Irgendwann
einmal ist das kleine Einmaleins verstanden und der Weg über
Multiplikation und Division zur höheren Mathematik frei.
Gruß oldmax
michael_ schrieb:> Uff, fast hast du es richtig geschnallt.> Mit dem IN-Befehl kann man nur auf das Daten-Register zugreifen.> Dann gibt es noch das Direction-Register.> Und dann gibt es das PIN-Register.> Da geht dann das SBIC/SPIS und weitere.
Du solltest wirklich mal in die Datenblätter schauen, auch doc856 von
Atmel ist sehr zu emnpfehlen. Bis dahin halts lieber mit Dieter Nuhr. Du
weisst schon, "..., Fresse halten".
Oliver
Hi
>Also,einen Port einlesen>erfolgt nicht mit einem Ladebefehl LDI oder LDS sondern mit IN>(Register),PINx.
Selbstverständlich kann man LDS zum Einlesen eines Port verwenden.
Allerdings nicht mit der IO-Adresse sondern mit der um 0x20 größeren
RAM-Adresse. Also
lds r16, PINC+0x20 bewirkt das gleiche wie in r16, PinC
MfG Spess
spess53 schrieb:> lds r16, PINC+0x20 bewirkt das gleiche wie in r16, PinC
Je nach AVR-Typ sind nicht mehr alle Ports und viele Hardwareregister
nicht per IN/OUT erreichbar, d.h. es geht nur LDS/STS.
In C hat man es daher sehr einfach, da kümmert sich der Compiler
automatisch drum.
@Marc V
Wenn ich mir den Ausgangscode von Sebastian so ansehe, kann ich mir
nicht vorstellen, dass er mit Deinem Programm sehr viel anfangen kann.
Könnte gehen, auch wenn mir die Zuordnung zu den einzelnen Segmenten
unklar ist.
Hi
>Hier gehts aber nicht um irgendeinen Typ, sondern um einen ATmega328P.
Auch der ATMega328 hat IO-Register die mit LDS/STS und nicht mit IN/OUT
angesprochen werden müssen.
MfG Spess
michael_ schrieb:> Uff, fast hast du es richtig geschnallt.
Sei dir vollkommen sicher: mir musst du dahingehend nichts mehr
beibringen. Ich kenne die AVR-Controller vom ersten Baustein an. Dessen
Assembler war kommend vom 8049, 8051 und einem unsäglichen Ausflug zu
den ersten PIC-Controllern ein leuchtender Stern am Himmel.
> Mit dem IN-Befehl kann man nur auf das Daten-Register zugreifen.
Mit dem IN Befehl kann man genauso wie mit dem OUT Befehl auf die
unteren 64 IO Register zugreifen.
> Dann gibt es noch das Direction-Register.
Auch darauf kann man mit IN und OUT zugreifen.
> Und dann gibt es das PIN-Register.
Auch darauf kann man mit IN und sogar überraschenderweise(!) mit OUT
zugreifen. Denn wenn eine 1 auf ein Bit eines PIN Registers geschrieben
wird (z.B. auch mit SBI), dann toggelt per unerwarteter Fernwirkung das
entsprechende PORT Register Bit und damit der Pegel des Ausgangs (oder
der Pullup, wenn der Pin mit dem DDR auf Eingang geschaltet ist).
> Da geht dann das SBIC/SPIS und weitere.
Und diese bedingten Sprungbefehle SBIS bzw. SBIC können nur auf
bestimmte Register (IO Register 0..31) zugreifen. Genauso wie SBI und
CBI.
Mehr dazu im Datenblatt unter "Register Summary" und der "Data Memory
Map".
EDIT: hoppla, da hatte ich wohl vergessen, auf "Senden" zu drücken...
;-)
Oliver S. schrieb:> die Portregister liegen bei dem im durch in/out- addressierbaren Bereich.
Und noch besser: sie liegen sogar im bitadressierbaren Bereich, auf
den mit SBI, CBI, SBIS und SBIC zugegriffen werden kann.
Lothar M. schrieb:> michael_ schrieb:>> Uff, fast hast du es richtig geschnallt.> Sei dir vollkommen sicher: mir musst du dahingehend nichts mehr> beibringen. Ich kenne die AVR-Controller vom ersten Baustein an. Dessen> Assembler war kommend vom 8049, 8051 und einem unsäglichen Ausflug zu> den ersten PIC-Controllern ein leuchtender Stern am Himmel.
Hier sind wir uns doch einig.
Zuerst der 90S1200 und dann mit dem 90S2313 konnte ich meine
PWM-Probleme lösen können.
Froh, dass ich mich gegen die unmöglichen PIC entschieden habe.
Sollen doch alle mit dem PINC glücklich werden.
Die Erkenntnis, dass es damit nicht geht, hat mich damals vor 20 Jahren
Stunden gekostet.
Um 8 Bit von einem I/O Register einzulesen.
spess53 schrieb:> Selbstverständlich kann man LDS zum Einlesen eines Port verwenden.> Allerdings nicht mit der IO-Adresse sondern mit der um 0x20 größeren> RAM-Adresse. Also>> lds r16, PINC+0x20 bewirkt das gleiche wie in r16, PinC>> MfG Spess
Vielleicht.
Aber warum? Braucht die 3-fache Zeit.
Bei 8MHz 125ns zu 375ns.
Hi
Aber warum? Braucht die 3-fache Zeit. Braucht die 3-fache Zeit.
Fast gibt es nicht. Es ist genau die doppelte Zeit. Solltest du
eigentlich wissen. wenn du das Instruction Set gelesen hast
MFG Spess
michael_ schrieb:> Sollen doch alle mit dem PINC glücklich werden.> Die Erkenntnis, dass es damit nicht geht, hat mich damals vor 20 Jahren> Stunden gekostet.> Um 8 Bit von einem I/O Register einzulesen.
Ich zitiere jetzt nochmal aus dem Datenblatt des ATMega 48/88/168/328:
" Reading the pin value
Independent of the setting of Data Direction bit DDxn, the port pin can
be read through the PINxn Register bit."
Das sollte jetzt klar sein. PINC ist die richtige Adresse, um den Wert
der Port C Pins einzulesen. Ist der Pin als Eingang deklariert, liest
man damit einen extern angelegten Logiklevel ein.
Hi
Ich weiß nicht so recht, ob es vielleicht besser wäre, ihr würdet mal
die Telefonnummern tauschen. Der TO ist schon lange raus und ihr längst
nicht mehr beim Thema und, sorry, das ich mecker, es ist niemandem eine
Hilfe, wenn ihr euch hier einen Kleinkrieg leistet, wer in der kürzesten
Zeit auf welchem Weg eine Peripherie anspricht und was das Datenblatt
aussagt. Erstellt doch diesbezüglich einen eigenen Thread, anstatt
Anfänger mit eurem (beachtenswertem) Wissen zu frustrieren, denn die
verstehen nur noch Bahnhof. Das ist nicht wirklich nett, wenn man bei
jedem Post mit sicherlich gut gemeinter aber für hier die Antwort völlig
überzogener tiefgründiger Fachkenntnis reagiert.
Gruß oldmax