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
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
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
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
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
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
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
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
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.
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.