www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zeichenkette vom UART auswerten AVR Assembler


Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
main:
        ldi r16, 0xf0
  out portb, r16
  rcall warte_1s

  ldi r16, 0x0f
  out portb, r16
  rcall warte_1s

  in r16, UDR    ; Zeichen auslesen
  cpi r16,0x74    ; prüfen ob t gedrückt wurde
  brne no_enter  
  out UDR, r16
 wait_RX1:
  sbis UCSRA,RXC
  rjmp wait_RX1

no_m:
  in r16, UDR    ; Zeichen auslesen
  cpi r16,0x6D    ; prüfen ob m gedrückt wurde
  brne no_m
  out UDR, r16
 wait_RX2:
  sbis UCSRA,RXC
  rjmp wait_RX2

no_p:
  in r16, UDR    ; Zeichen auslesen
  cpi r16,0x70    ; prüfen ob p gedrückt wurde
  brne no_p
  out UDR, r16
 wait_RX3:
 
  rcall get_temp
no_enter:
rjmp main

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
UART_INIT:
.equ BAUD = 38400
.equ UBRRVAL = F_CPU/(BAUD*16)-1
; Baudrate einstellen
  ldi r16, LOW(UBRRVAL)
  out UBRRL, r16
  ldi r16, HIGH(UBRRVAL)
  out UBRRH, r16
; Frame-Format: 8 Bit
  ldi r16, (1<<URSEL)|(3<<UCSZ0)
  out UCSRC, r16
  sbi UCSRB,TXEN    ; TX aktivieren
  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

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab nochmal ein altes Prgramm ausprobiert, ich vermute fast mal dass ein 
Hardwaredefekt vorliegt oder irgendwas mit meinem Windows nicht stimmt.

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Hardwareloop funktioniert. Trotz Einfügen der Warteschleife aber 
immernoch kein Ergebnis. :-(

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.