Forum: Mikrocontroller und Digitale Elektronik UART auf dem Arduino-UNO über RX und TX


von C0der (Gast)


Lesenswert?

Hallo, ich hoffe Ihr könnt mir helfen.


Bin jetzt ziemlich lange an einem Problem mit dem Arduino Uno dran und 
finde keinen Ansatz es zu lösen.
Ich habe mit Assembler eine serielle Kommunikation realisiert, welche 
über die USB-Schnittstelle auch einwandfrei funktioniert. Jetzt wollte 
ich die Signale einmal an den RX und TX Pins abfangen und die Probleme 
fingen an.

Normal sollte bei Start des Programms ein 0x05 über die Leitung gesendet 
werden, stattdessen kommt zuverlässig ein 0xC1. Passe ich diese Werte im 
Programm an, verändern sich auch die gesendeten Werte, sind aber nie 
korrekt.

Wenn ich einen Test-Sketch aus den Arduino Beispielen hochlade und 
darüber die serielle Kommunikation an den Pins abfange, kommen die 
korrekten Zeichen zurück.

Leider habe ich noch nicht mal einen Ansatzpunkt, woher dieses Verhalten 
kommen könnte. Wie gesagt:

Fall 1: Seriell über USB -> alles funktioniert
Fall 2: Seriell über RX- / TX-Pins -> falsche Übertragung

Wenn Ihr irgendwelchen Code braucht meldet euch, aber im Grunde würde 
mir schon ein Ansatz helfen, woher dieses Verhalten kommen könnte.

Hier habe ich schon mal meine UART Initialisierung:
1
uart_init:
2
; Baudrate einstellen
3
    LDI    WREG0, HIGH(UBRR_VAL)
4
    STORE  UBRR0H, WREG0
5
    LDI    WREG0, LOW(UBRR_VAL)
6
    STORE  UBRR0L, WREG0
7
8
; Frame-Format: 8 Bit
9
    LDI    WREG0, (1<<UCSZ00) | (1<<UCSZ01)
10
    STORE  UCSR0C, WREG0
11
    
12
; Sender und Empfänger aktivieren
13
    LDI    WREG0, (1<<RXEN0) | (1<<TXEN0)
14
    STORE   UCSR0B,WREG0
15
    RET

Das senden der Zeichen funktioniert folgendermaßen:
1
uart_write:
2
    PUSH  WREG0
3
    PUSH  WREG1
4
    LOAD  WREG1, UCSR0A
5
    SBRS  WREG1, UDRE0
6
    RJMP  uart_write
7
    STORE  UDR0, WREG0
8
    RCALL  uart_sync
9
    POP    WREG1
10
    POP   WREG0
11
    RET
12
    
13
; kleine Pause zum Synchronisieren des Empfängers                               
14
uart_sync:
15
    PUSH  WREG0
16
    PUSH  WREG1
17
    LDI    WREG0, 0x20
18
uart_sync_1:
19
    LDI    WREG1, 0x00
20
uart_sync_loop:
21
    DEC    WREG1
22
    BRNE  uart_sync_loop
23
    DEC    WREG0
24
    BRNE   uart_sync_1
25
    POP    WREG1
26
    POP   WREG0
27
    RET

Vielen Dank im Voraus!

von S. Landolt (Gast)


Lesenswert?

Die erste Vermutung ist, dass UBRR_VAL falsch ist - also den Wert 
hiervon angeben sowie Systemtakt und verlangte Übertragungsrate.

Nur am Rande: sobald UDRE0=0 ist, sammelt sich Müll im Stack an.

von S. Landolt (Gast)


Lesenswert?

Die Offenlegung dieses "STORE" wäre auch nicht schlecht.

von C0der (Gast)


Lesenswert?

Hallo,

also hier die Berechnung von UBRR_VAL
1
; Baudrate berechnen
2
.equ F_CPU = 16000000              ; Systemtakt in Hz
3
.equ BAUD  = 9600                ; Baudrate
4
5
; Berechnung der Baudrate
6
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
7
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
8
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
9
10
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
11
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
12
.endif
13
; Quelle: https://www.mikrocontroller.net/articles/AVR-Tutorial:_UART (24.03.2017)

Store ist mir eben auch aufgefallen:
1
.MACRO STORE   ;Arguments: Address, Register
2
  .if  @0>0x3F
3
    sts  @0, @1
4
  .else
5
    out  @0, @1
6
  .endif
7
.ENDMACRO

von Stefan E. (sternst)


Lesenswert?

C0der schrieb:
> Wenn Ihr irgendwelchen Code braucht meldet euch,

Wieso Code? Wenn es je nach Außenbeschaltung mal geht, und mal nicht, 
dann liegt doch wohl die Vermutung nahe, dass es an ebendieser 
Außenbeschaltung liegt, und nicht am Code.
Also, was bedeutet dies:
> Jetzt wollte
> ich die Signale einmal an den RX und TX Pins abfangen

Was genau hängt da jetzt wie genau an den Pins?

von JoKu (Gast)


Lesenswert?

C0der schrieb:
> im Grunde würde
> mir schon ein Ansatz helfen

GND verbunden?

;)

von S. Landolt (Gast)


Lesenswert?

Ohne den Absatz
> Wenn ich einen Test-Sketch aus den Arduino Beispielen hochlade und
> darüber die serielle Kommunikation an den Pins abfange, kommen die
> korrekten Zeichen zurück.
hätte ich gesagt, da fehlt vielleicht ein Inverter.
Was dient denn als Empfänger?

von Manfred (Gast)


Lesenswert?

C0der schrieb:
> die Signale einmal an den RX und TX Pins abfangen
Kollision der Daten vom USB-Wandler auf dem Uno-Board mit dem Signal von 
extern.

Schaltplan angucken, mit der tatsächlichen Schaltung vergleichen und 
ggfs. Widerstände runter.

von C0der (Gast)


Lesenswert?

Stefan E. schrieb:
> Wieso Code? Wenn es je nach Außenbeschaltung mal geht, und mal nicht,
> dann liegt doch wohl die Vermutung nahe, dass es an ebendieser
> Außenbeschaltung liegt, und nicht am Code.

Naja, es ist ja genau anders rum. Wenn ich Fremdcode (einen 
Arduino-Sketch) hochlade funktioniert der Empfang, wenn ich meinen Code 
hochlade funktioniert es nicht...

JoKu schrieb:
> GND verbunden?

Jop ;)

S. Landolt schrieb:
> hätte ich gesagt, da fehlt vielleicht ein Inverter.
> Was dient denn als Empfänger?

Ein selbstgebauter RS232 12V - 5V Umsetzer aus unserem Labor, alles 
weitere könnte ich morgen nachliefern. Wobei es ja, wie oben 
geschrieben, mit anderem Code funktioniert.

Kann es Probleme mit dem Anschluss von USB an den PC, für die 
Stromversorgung, und der parallelen Nutzung der Pins 0 und 1 geben? Darf 
man die gleichzeitig an einen PC anschließen?

von C0der (Gast)


Lesenswert?

Manfred schrieb:
> Kollision der Daten vom USB-Wandler auf dem Uno-Board mit dem Signal von
> extern.
>
> Schaltplan angucken, mit der tatsächlichen Schaltung vergleichen und
> ggfs. Widerstände runter.

Ah, da war ich zu langsam :)

Also liegt es deiner Meinung nach tatsächlich an dem angeschlossenen 
Wandler und nicht am Code. Das freut mich schon einmal! Oder meinst Du, 
dass ich etwas auf dem UNO selber ändern müsste?

von Wolfgang (Gast)


Lesenswert?

C0der schrieb:
> Ein selbstgebauter RS232 12V - 5V Umsetzer aus unserem Labor, alles
> weitere könnte ich morgen nachliefern.

Dann wird er hoffentlich nicht nur die Pegel umsetzen, sondern auch noch 
das Signal invertieren.

von S. Landolt (Gast)


Lesenswert?

> ...nicht am Code...
Das, was davon zu sehen ist, läuft; der oben beschriebene, üble Fehler 
in uart_write tritt nicht auf wegen der Verzögerung per uart_sync 
(was auch immer das sein soll).

von Einer K. (Gast)


Lesenswert?

C0der schrieb:
> Naja, es ist ja genau anders rum. Wenn ich Fremdcode (einen
> Arduino-Sketch) hochlade funktioniert der Empfang, wenn ich meinen Code
> hochlade funktioniert es nicht...

Tipp:
Lese die Baudrate Register aus, um zu erfahren, welche Werte das Arduino 
Programm setzt.
Vergleiche mit deinen Werten, und Zack, der Fehler ist gefunden.

Das "Warum", solltest du dann allerdings auch noch ergründen....

von C0der (Gast)


Lesenswert?

Also...

Entwarnung. Habe mir heute morgen einen anderen USB-Seriell-Wandler 
besorgt und jetzt funktioniert es. Nach Rücksprache mit dem Betreuer 
stellte sich heraus, dass der Wandler vorher an einem anderen 
SPannungspegel (3V) mit einem RaspberryPi betrieben wurde. Es war also 
am ehesten dieser Lösungsansatz:

Manfred schrieb:
> Kollision der Daten vom USB-Wandler auf dem Uno-Board mit dem Signal von
> extern.
>
> Schaltplan angucken, mit der tatsächlichen Schaltung vergleichen und
> ggfs. Widerstände runter.

Danke hierfür schon mal!

Mich würde noch genauer das Problem mit UDRE0 interessieren.

S. Landolt schrieb:
> Die erste Vermutung ist, dass UBRR_VAL falsch ist - also den Wert
> hiervon angeben sowie Systemtakt und verlangte Übertragungsrate.
>
> Nur am Rande: sobald UDRE0=0 ist, sammelt sich Müll im Stack an.

Würde sich hier noch einmal jemand erbarmen :)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

C0der schrieb:
> Würde sich hier noch einmal jemand erbarmen :)
Schau dir das hier an:
> uart_write:
>     PUSH  WREG0
>     PUSH  WREG1
>     LOAD  WREG1, UCSR0A
>     SBRS  WREG1, UDRE0
>     RJMP  uart_write
>     STORE  UDR0, WREG0
>     RCALL  uart_sync
>     POP    WREG1
>     POP   WREG0
>     RET

Was passiert, wenn UDRE0 nicht gesetzt ist? Richtig, er springt zum 
Anfang der Routine und pusht WREG0 und WREG1 wieder auf den Stack. Du 
solltest also hinter die PUSHs hüpfen und nicht davor.

von spess53 (Gast)


Lesenswert?

Hi

>Würde sich hier noch einmal jemand erbarmen :)

uart_write:
        PUSH  WREG0
        PUSH  WREG1
xxx:    LOAD  WREG1, UCSR0A
        SBRS  WREG1, UDRE0
        RJMP  xxx
        ...

MfG Spess

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Übrigens pures Glück, das du soweit gekommen bist. Normalerweise läuft 
der Stack bei sowas in Nullkommanix über und -> Feierabend.

von C0der (Gast)


Lesenswert?

Ups, Tatsache. Da war ich wohl ziemlich Betriebsblind :(

Danke!

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.