Hallo Leute,
ich möchte eine Zeichenkette (3 Zeichen) die über die serielle
Schnittstelle kommt auswerten und hab mir auch ein kurze Routine
geschrieben.
Leider nimmt der MC die Zeichenkette nicht an. Die Schnittstelle selbst
funktioniert, weil die Initialisierungsroutine eine Zeichenkette an das
Terminal schickt.
Im ersten Teil hab ich sowas wie ein Blinkprogramm eingefügt, damit ich
sehen kann ob der MC irgendwo hängen leibt, was nicht der Fall ist.
Den Empfang hab ich freigeschalten: sbi UCSRB,RXEN
Kann mir vielleicht jemand sagen warum, das Programm nicht so wie ich
will?
Ich komm nicht von allein drauf
Wird denn die Datadirection des UART-Ports richtig initialisiert, ich
kann im Code keine Initialisierung finden. Standardmäßig ist nach dem
Einschalten jeder Pin ein Eingang, das musst du aber geändert haben,
sonst würde der AVR keine Zeichen senden können. Rxd muss als Eingang
konfiguriert sein, vielleicht ist da ein Fehler passiert.
Man kann als Konstanten auch character schreiben, das wäre besser
lesbar:
cpi r16,'t' ; prüfen ob t gedrückt wurde
Hast du mal eine einfache Loopback-Schleife getestet oder zumindest ein
Hardwareloopback ausprobiert?
Grüße,
Peter
Hallo Peter,
ich wüsste nicht, dass RX und TX extra als Eingang bzw. Ausgang
geschalten werden müssen, ich nutze die eingebaute serielle
Schnittstelle.
Hier meine Initalisierungsroutine:
1
UART_INIT:
2
.equ BAUD = 38400
3
.equ UBRRVAL = F_CPU/(BAUD*16)-1
4
; Baudrate einstellen
5
ldi r16, LOW(UBRRVAL)
6
out UBRRL, r16
7
ldi r16, HIGH(UBRRVAL)
8
out UBRRH, r16
9
; Frame-Format: 8 Bit
10
ldi r16, (1<<URSEL)|(3<<UCSZ0)
11
out UCSRC, r16
12
sbi UCSRB,TXEN ; TX aktivieren
13
sbi UCSRB,RXEN ; RX aktivieren
Das mit dem Charater ist ein guter Hinweis...
Was meinst du mit Hardwareloopback?
Ich habe auch schon versucht, gleich nach dem Auslesen des Zeichens es
wieder an die UART zurückzusenden, leider ohne Erfolg.
Das Senden an das Terminal funktioniert aber definitiv
Hardwareloopback bedeutet, dass man den Mikrocontroller aus der
Schaltung entfernt und am Sockel Rxd mit Txd verbindet. EIn
angeschlossenes Terminal muss dann genau die gesendeten Zeichen
empfangen. Damit hat man die Hardware bis zum Controller gestestet.
Grüße,
Peter
Du solltest außerdem besser warten bis ein Zeichen angekommen ist, bevor
du es ausließt, also etwa so:
getChar:
sbis UCSRA,RXC ; wait for incoming data (until RXC==1)
rjmp getChar
in R16,UDR ; store received data in R16
ret
Grüße,
Peter
Dann erweitere die Loop ein wenig:
sende das empfangene Byte wieder zurück (evtl. auch im Klartext, d.h.
für ein empfangenes A sendest Du 41 oder A41 zurück).
Ich kann mich wage daran erinnern, dass es beim ATMEGA wichtig ist, in
welcher Reihenfolge die Register geschrieben werden.
Ich denke, es muss hier UBRRH zuerst geschrieben werden:
ldi r16, LOW(UBRRVAL)
out UBRRL, r16
ldi r16, HIGH(UBRRVAL)
out UBRRH, r16
Um welchen Prozessor geht es denn eigentlich genau?
Peter
Hast du dir eigentlich genau überlegt, was diese Zeile macht?
ldi r16, (1<<URSEL)|(3<<UCSZ0)
Vor allem das mit der 3 in 3<<UCSZ0?
Ich habe das jetzt nicht nachgeprüft, aber die vordefinierten Bits (z.B.
UCSZ0) sind eine Zahl von 0 bis 7 und geben die Stelle des jeweiligen
Bits im Register an. Normalerweise verwendet man sie um den Code
lesbarer zu machen und shiftet um eben die damit definierte Konstante
eine 1 in das Register. Aber eine 3 setzt ja zwei Bits. Damit ist die
Lesbarkeit verloren gegangen und zudem größere Verwirrung erzeugt, denn
wer weiß dadurch intuitiv eindeutig, welches das zweite gesetzte Bit
ist?
Also sollte man es entweder so machen:
ldi r16, (1<<URSEL)|(1<<UCSZ0)|(1<< das andere, was gemeint war)
Oder gleich ohne lesbare Konstanten:
ldi r16, 0xirgendwas
Grüße,
Peter
Hallo Peter,
ich muss natürlich gestehen, dass viele Codeteile nicht von mir sind.
Ich hatte ursprünglich begonnen einen Temperatursensor (DS1632) per TWI
auszulesen.
Da ohne Vorkenntnisse habe ich mir den Code von Metaller geschnappt,
siehe Blutrausch I2C. Nach einigen Wochen rumgefrickel und
Datenblätterlesen hab ich es doch noch hinbekommen den Code entsprechend
anzupassen.
Da die Ausgabe über den UART immer funktioniert hat, habe ich mir keine
Gedanken drum gemacht. Erst als ich versucht habe den Code dahingehend
zu erweitern, dass ich auch Befehle an den Temperatursensor schicken
kann.
Wie wieder mal unschwer zu erkennen, spart man mit copy and paste
mitnichten Zeit :-(
Um zurückzukommen zum Thema, das mit 3<<UCSZ0 ist mir gestern auch
aufgefallen. Das hatte den Vorteil, dass mir einige Unstimmigkeiten in
meinen alten selbstgeschriebenen Programmen aufgefallen sind.
Grundsätzlich kommt ja nach UCSZ0 gleich UCSZ1. wird jetzt eine 3
reingeschoben, werden beide Bits gesetzt.
Ich werde mir das heute alles nochmal anschauen, kann ja nicht sein,
dass ich für dieses Fuzelchen an Programmcode 2 Wochen brauche.
Nun werde ich wohl nochmal einen Schritt zurückgehen und die
Befehlserkennung separat programmieren, das macht das debuggen dann
hoffentlich einfacher.
Mein Controller ist übrigens der Mega8
Ich melde mich dann wieder,
Gruß, Jürgen