Forum: Mikrocontroller und Digitale Elektronik atXmega UART Empfangs-Problem


von ChristianB (Gast)


Lesenswert?

Hallo. Ich bin ziemlich verzweifelt beim Versuch, von der seriellen 
Leitung zu lesen. Bitte helft! Ich benutze das aktuelle AVR Studio, 
AVRISP mkII, ein selbstgebasteltes board und einen hugepine USB<-> 
seriell-Wandler+Terminalprogramm unter WinVista

Prozessor: ATXMEGA192A3
USART D0 (PinD3/D2)

Problem: Im Test reagiert der µC nicht auf an ihn gesendete Daten. Auch 
im Simulator2 passiert überhaupt nichts, wenn ich das RXCIF Flag beim 
USARTD0 manuell setze. Eine Interruptversion habe ich 
ebenfallsausprobiert. Die I.-Routine wird aber nicht angesprungen. 
Zeichen zum PC senden klappt perfekt.

Code ohne Interrupt:
--------------------
#include <avr/io.h>
#define LEDPORT PORTA
#define LED 7

int main(void) {
    PORTD.OUTSET |= PIN3_bm; // Für den Transmitter
    PORTD.DIRSET |= PIN3_bm; //     "
    //keine Clockconfig--> int. 2MHz Takt nutzen --> BSEL = 12 für 
9600baud
    USARTD0.BAUDCTRLA = 12;
    // 8bit UART, no parity, 1 stopbit
    USARTD0.CTRLC |= USART_CMODE_ASYNCHRONEOUS_gc|USART_CHSIZE_8BIT_gc;
    // Receiver einschalten
    USARTD0.CTRLB |= USART_RXEN_bm;

    LEDPORT.DIRSET |= (1<<LED);

    while (1) {
          while (!(USARTD0.STATUS & USART_RXCIF_bm));
          LEDPORT.OUTTGL |= (1<<LED);
    }

    return 0;
}


Code mit Interrupt:    (***:= geändert)
-------------------
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPORT PORTA
#define LED 7
volatile char c;

// *** RXC ISR ***
ISR (USARTD0_RXC_vect) {
    c = USARTD0.DATA;
}
// *********************

int main(void) {
    PORTD.OUTSET |= PIN3_bm; // Für den Transmitter
    PORTD.DIRSET |= PIN3_bm; //     "
    //keine Clockconfig--> int. 2MHz Takt nutzen --> BSEL = 12 für 
9600baud
    USARTD0.BAUDCTRLA = 12;
    // 8bit UART, no parity, 1 stopbit
    USARTD0.CTRLC |= USART_CMODE_ASYNCHRONEOUS_gc|USART_CHSIZE_8BIT_gc;

// ***  RXC Interrupt auf high priority  ***
    USART.CTRLA |= USART_RXCINTLVL_Hi_gc;
// *****************************************

    // Receiver einschalten
    USARTD0.CTRLB |= USART_RXEN_bm;

    LEDPORT.DIRSET |= (1<<LED);


    // *** Interruptcontroller: Highlevelinterrupts aktivieren ***
    PMIC.CTRL |= PMIC_HILVLEN_bm;
    // globale Interrupts aktivieren
    sei();


    while (1) {
          if (c == 111)
               LEDPORT.OUTTGL |= (1<<LED);
    }
    // **********************************************************

    return 0;
}


Habe auch schon den Transceiver mitaktiviert und diverse andere Sachen 
probiert, u.a. eine saubere Clockconfig, PortD Dir Änderungen...

Wieso kann nichts empfangen werden? Wer kann helfen?

Danke im Voraus,
Christian

von XMEGA (Gast)


Lesenswert?

Servus,


ChristianB schrieb:

PORTD.DIRSET |= PIN3_bm; // Für den Transmitter
PORTD.OUTSET |= PIN3_bm; // Für den Transmitter

PORTD.DIRCLR |= PIN2_bm; // Für den Reciver



Gruß Xmega

von ChristianB (Gast)


Lesenswert?

Danke. Klappt leider auch nach dem Einfügen von PORTD.DIRCLR |= 
PINB2_bm; nicht (PORTD-Pins sind beim Start standardmäßig alle als 
Eingänge konfiguriert).

Ich hab schon daran gedacht, dass ich den µC zu heiß eingelötet und was 
kaputt gemacht habe, aber im Simulator sollte ja was passieren!?
Christian

von XMEGA (Gast)


Lesenswert?

Servus,

bin es nochmals

ChristianB schrieb:

Falsch:

USARTD0.CTRLC |= USART_CMODE_ASYNCHRONEOUS_gc|USART_CHSIZE_8BIT_gc;

Richtig:

USARTD0.CTRLC |= USART_CMODE_ASYNCHRONOUS_gc | USART_CHSIZE_8BIT_gc;

(USART_CMODE_ASYNCHROEOUS_gc) = das ein Tippfehler oder Kopierfehler.

Ich bekomme eine Fehlermeldeung!

Gruß XMEGA

von ChristianB (Gast)


Lesenswert?

Hallo XMEGA, nochmals Danke dafür, dass Du Dich damit beschäftigst. Der 
Fehler kommt vom Abtippen. Der Code wird ohne Fehlermeldungen oder 
Warnungen kompiliert. Tut das Programm denn bei Dir was es soll, nach 
Deiner Korrektur?
Gruß, Christian

von XMEGA (Gast)


Lesenswert?

Servus,

ChristianB schrieb:
> Tut das Programm denn bei Dir was es soll

Wenn du das machen willst musst du den Port anders konfigurieren
falsch: LEDPORT.DIRSET |= (1<<LED);


richtig: LEDPORT.DIRTGL |= (1<<LED);


Dann funktioniert dein Code auf meinen Atxmega128a1 einwandfrei.

Gruß XMEGA

von ChristianB (Gast)


Lesenswert?

Zum x-ten mal nach allen möglichen Codeänderungen hab ich im Simulator 
das RXCIF flag gesetzt - ohne Effekt. Das USARTD0.DATA Register wird im 
AVR Studio Simulator 2 ebenfalls nicht richtig gelesen und ich hab 
allmählich den Verdacht, dass ich einen bug entdeckt habe oder ein Esel 
bin.
Ich gebs vorerst auf und besorge mir ein Xplain. Vielleicht bin ich ja 
tatsächlich auf eine Unzulänglichkeit im Simulator gestoßen UND habe 
meine Hardware beim Löten beschädigt. Könnte auch sein, dass es daran 
liegt, dass nicht alle Stromversorgungspins (wohl aber die der benutzten 
PORTs) angeschlossen sind. Auf dem Xplain solte dann ja alles für den 
Xmega128A1 kompiliert problemlos laufen.
Wenn noch jemandem was einfällt, bitte trotzdem posten!
Nochmals Danke für die Hilfe.
Gruß, Christian

von ChristianB (Gast)


Lesenswert?

PROBLEM GELÖST.
Es war ein Hardwarefehler. Nachdem ich eine kaum sichtbar unterbrochene 
Leierbahn repariert habe, funktioniert der Code.
Das erklärt noch nicht, warum es im Simulator nicht funktioniert hatte. 
Im Datenblatt ist das RXCIF flag als read only bezeichnet. Vielleicht 
hat es deshalb keinen Effekt, wenn ich es im Sim manuell setze?! Ebenso 
mysteriös ist mir das Datenregister. Kann man vielleicht nicht 
beschreiben, weil der Sim dann nicht weis, ob man in den TX Buffer oder 
RX Buffer schreiben will?!
Wie auch immer. Der obige Code funktioniert (ohne die Tippfehler) und 
kann auf allen XMEGA und für alle USARTs beliebig wiederverwendet 
werden.

Grüße, Christian

von Knuddelhase (Gast)


Lesenswert?

Auch wenn der Thread schon älter ist:

Ich befasse mich momentan ausführlich mit dem XMega (64A1) und seinen 
USARTS. Bei obigem Code kann man zwar empfangen, aber nichts senden 
(zumindest bei mir nicht...)
Habe da eine Theorie, mit der das ganze wieder funktioniert:

XMEGA schrieb:
> PORTD.DIRSET |= PIN3_bm; // Für den Transmitter
> PORTD.OUTSET |= PIN3_bm; // Für den Transmitter
>
> PORTD.DIRCLR |= PIN2_bm; // Für den Reciver
>
>
>
> Gruß Xmega

Besser:
PORTD.OUTSET = PIN3_bm;
PORTD.DIRSET = PIN3_bm;

PORTD.DIRCLR = PIN2_bm;

-> ohne die ODER!!

Grund:
Die ...SET/CLR-Register lesen wohl bei der VerODERung den Wert des 
Ursprungsregisters (siehe Datenblatt: "Reading this register will return
the value of the DIR register."):
DIRSET |= PIN3_bm ist DIRSET = DIR | PIN3_bm -> PIN3 in DIR wird 1

Das geht gut, solange nur Bits gesetzt werden, d.h. mit den 
...SET-REgistern.
Das tückische sind die CLR-Register:

DIRCLR |= PIN2_bm ist DIRCLR = DIR | PIN2_bm
-> alles was in DIR gesetzt war +PIN2 wird jetzt in DIRCLR gesetzt und 
somit wieder in DIR gelöscht.
Es ist eben nicht DIRCLR = DIRCLR | PIN2_bm
Richtig: DIRCLR = PIN2_bm -> Pin2 wird in DIRCLR gesetzt und in DIR 
gelöscht.

Ich hoffe ich hab mich da jetzt nicht verrannt, aber wie gesagt, lasse 
ich die ODER weg, geht der Transmitter und der Receiver, mache ich die 
ODER hin, geht nur der Receiver...
Vielleicht bringt dies ja dem ein oder anderen (wie mir...) die 
Erleuchtung.

von F. B. (flump)


Lesenswert?

hehe

des mit den dirset und dirclr habe ich heute erst ausprobiert.
Also das clr bedeutet quasi &=~
und das set bedeutet quasi |=

da muss man echt aufpassen. Das steht zwar niergends aber ist verdammt 
wichtig. Da man sonst die ganzen register aus versehen löscht obwohl man 
eigentlich nur ein bit ändern wollte.

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.