Warum funktioniert mein AVR Assembler Code nicht?

Gast #5891660
Lesenswert?

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)
4
  out DDRB, r16
5

6
loop:
7

8
  ldi r16, PINC ; PINC read
9

10
  cpi r16, 0b0000000 ; if(PINC == 0)
11
  breq number0
12

13
  cpi r16, 0b0000001 ; if(PINC == 1)
14
  breq number1
15

16
  cpi r16, 0b0000010 ; if(PINC == 2)
17
  breq number2
18

19
  cpi r16, 0b0000011 ; if(PINC == 3)
20
  breq number3
21

22
  cpi r16, 0b0000100 ; if(PINC == 4)
23
  breq number4
24

25
  cpi r16, 0b0000101 ; if(PINC == 5)
26
  breq number5
27

28
  cpi r16, 0b0000110 ; if(PINC == 6)
29
  breq number6
30

31
  cpi r16, 0b0000111 ; if(PINC == 7)
32
  breq number7
33

34
  cpi r16, 0b0001000 ; if(PINC == 8)
35
  breq number8
36

37
  cpi r16, 0b0001001 ; if(PINC == 9)
38
  breq number9
39

40
  out PORTB, r17 ; turn on leds
41

42
  rjmp loop
43

44
number0:
45
  ldi r17, 0b01111110 ; a, b, c, d, e, f
46
  
47
number1:
48
  ldi r17, 0b00110000 ; b, c
49

50
number2:
51
  ldi r17, 0b01101101 ; a, b, d, e, g
52

53
number3:
54
  ldi r17, 0b01111001 ; a, b, c, d, g
55

56
number4:
57
  ldi r17, 0b00110011 ; b, c, f, g
58

59
number5:
60
  ldi r17, 0b01011011 ; a, c, d, f, g
61

62
number6:
63
  ldi r17, 0b01011111 ; a, c, d, e, f, g
64

65
number7:
66
  ldi r17, 0b01110000 ; a, b, c
67

68
number8:
69
  ldi r17, 0b01111111 ; a, b, c, d, e, f, g
70

71
number9:
72
  ldi r17, 0b01111011 ; a, b, c, d, f, g
Persönliche Seite #5891714
Lesenswert?

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
Gast #5891770
Lesenswert?

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...
(Firma: matzetronics) #5891796
Lesenswert?

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.
#5892060
Lesenswert?

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.
Gast #5892084
Lesenswert?

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. ;-)
#5892114
Lesenswert?

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

:-))
#5892133
Lesenswert?

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
#5892232
Lesenswert?

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.
Moderator (Firma: Titel) Persönliche Seite #5892278
Lesenswert?

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 Übung
Danach 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ß...
Angehängte Dateien:
#5892392
Lesenswert?

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
Gast #5892438
Lesenswert?

Lothar M. schrieb:
> Und im Anhang noch ein Denkanstoß...

...
loop:

  ldi r16, PINC       ;  Eing„nge 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.
Moderator (Firma: Titel) Persönliche Seite #5892479
Lesenswert?

michael_ schrieb:
1
 ldi r16, PINC       ;  Eingnge einelesen   ...
> Das kann ja niemals gehen. Ersetzen durch:
1
  in r16,PORTC    ; Port-C einlesen
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:
1
.include "m328pdef.inc"
2

3
  ldi r16, 0b01111111 ; PB6..0 = Ausgang
4
  out DDRB, r16       ; 7-SegDisp Bit 6..0 = abcdefg
5
  
6
loop:                 ; jetzt gehts los
7
  in   r16,PINC       ; alle Pins vom PC einlesen
8
  out  PORTD,r16      ; und geradeaus auf den PD ausgeben
9
  jmp  loop           ; wieder von vorn beginnen
Gast #5892595
Lesenswert?

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
Gast #5892634
Lesenswert?

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
#5892719
Lesenswert?

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
(Firma: matzetronics) #5892734
Lesenswert?

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.
Moderator (Firma: Titel) Persönliche Seite #5892776
Lesenswert?

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.
Gast #5892819
Lesenswert?

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.
(Firma: Vescomp) #5892822
Lesenswert?

Matthias S. schrieb:
> Ein sinnvoller Weg wäre z.B.

 Genau.
 Und hier ein Beispiel:
1
.include "m328pdef.inc"
2

3
   ldi  r16, 0b01111111 ; PB0-6 as outputs (7 segment display)
4
   out  DDRB, r16       ;
5
   clr  r10
6
  
7
loop:
8
   ldi  zl, low(Tab7seg)
9
   ldi  zh, high(Tab7Seg)
10
WertIn:
11
   in   r16, PINC       ; Eingaenge einlesen   
12
   cpi  r16, 10         ; Falschen Wert eingelesen?
13
   brlo GetWert         ; Nein, Wert aus der Tabelle lesen
14
   ldi  r16, 10         ; Ja, Minus Zeichen anzeigen
15
GetWert:
16
   add  zl, r16
17
   adc  zh, r10
18
   ld   r16, Z
19
ausgabe:
20
  out PORTB, r16      ; Segmente updaten
21
  rjmp loop           ;
22

23
Tab7seg:  .db  0b01111110, 0b00110000, 0b01101101, 0b01111001, 0b00110011
24
          .db  0b01011011, 0b01011111, 0b01110000, 0b01111111, 0b01111011
25
          .db  0b00000001  ; Fehler, Minus Zeichen (Seg_g) anzeigen
 Anstatt Tagelang über Fehler, Fähigkeiten, Kenntnisse etc. zu
 diskutieren...
(Firma: matzetronics) #5892838
Lesenswert?

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.
Gast #5893186
Lesenswert?

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.
#5893255
Lesenswert?

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
#5893260
Lesenswert?

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
Gast #5893330
Lesenswert?

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
Moderator (Firma: Titel) Persönliche Seite #5893409
Lesenswert?

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... 
;-)
Gast #5895686
Lesenswert?

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.
Gast #5895704
Lesenswert?

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
(Firma: matzetronics) #5896085
Lesenswert?

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.
Gast #5896104
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren