Forum: Mikrocontroller und Digitale Elektronik ATxmega USART Hilfe


von Fabian K. (fabian_k)


Lesenswert?

Guten Abend,

ich bin ein wenig am verzweifeln. Will als erstes mit meinem neuen 
xmega-Board USART zum laufen bringen. Der USB-USART-Wandler ist auf dem 
Board mit PF2(RX) und PF3(TX) verbunden. Aber es funktioniert einfach 
nicht. Hier der code:

int main(void)
{
  OSC.CTRL = 0b00000010;              // oszillator auf 32Mhz einstellen
  while((OSC.STATUS & 0b000000010) == 0b00000000)  // warten bis der 
oszillator stabil ist
  {
  }
  CCP = 0b11011000;    //
  CLK.CTRL = 0b00000001;  // clock auf 32Mhz einstellen


  PORTF.OUT = 0b00001000;
    PORTF.DIR = 0b00001000;    // TX-port aus ausgang

  USARTF0.BAUDCTRLB = 0b00000000;  // baudraten-skalierungsfaktor: 
keinen, also 0
  USARTF0.BAUDCTRLA = USART_VAL;  // baudrateneinstellung nach #defines 
oben

    USARTF0.CTRLA = 0b00000000;    // keine interrupts aktivieren, keine 
extras
    USARTF0.CTRLC = 0b01000011;    // synchroner USART, parity: keine, 
stop-bits: 1, character-size: 8bit
  USARTF0.CTRLB = 0b00011000;    // sender und empfaenger aktivieren, 
sonst nichts

    while(1)
    {
        while ((USARTF0.STATUS & 0b00100000) == 0b00000000)
    {
    }
    USARTF0.DATA = 'c';
    }

  return(0);
}

Danke im vorraus

von Fabian K. (fabian_k)


Lesenswert?

Achja noch die Berechnungen:

#define F_CPU 32000000
#define USART_BAUD 115200    // baudrate fuer usart
#define USART_VAL ((F_CPU/(2*USART_BAUD))-1)  // register-wert berechnen 
mit baudrate und CPU-frequenz

von Steffen H. (avrsteffen)


Lesenswert?

Teilt sich die Baudrate nicht 2 Register?

von Fabian K. (fabian_k)


Lesenswert?

Ja, aber wenn der Wert schon in in ein Register passt (8bit), braucht 
man das andere nicht.

von Roland H. (batchman)


Lesenswert?

Ich würde mir ja die Mühe machen, den Source anzusehen.
Allein mir fällt der Vergleich mit meinem Referenz-Source arg schwer, da 
ich dort nur die "offiziellen" Konstanten einsetze:

Beispiel:
1
USARTF0.CTRLC = 
2
    USART_CMODE_ASYNCHRONOUS_gc | 
3
    USART_CHSIZE_8BIT_gc | 
4
    USART_PMODE_DISABLED_gc;

In Deinem Kommentar steht "synchron". Ist es das, was Du willst?

Deinen Kommentaren wird der Compiler auch nicht trauen :-)

von Coder (Gast)


Lesenswert?

1) Synchron geht nicht.

2) Was geht konkret nicht? Wird z.B. ein Zeichen gesendet und es kommt 
"durcheinander" an?

von Fabian K. (fabian_k)


Lesenswert?

Es kommt gar nichts. Ich bevorzuge ehrlichgesagt jetzt mehr die 
Bitschreibweise, einfach viel weniger Schreibarbeit, 
Registerbeschreibungen kann ich in den Kommentaren ja immer noch 
ergänzen.

von Fabian K. (fabian_k)


Lesenswert?

OK, danke schonmal, synchron war auf jeden Fall das Falsche. Allerdings 
empfange ich jetzt nur Nullen statt den 'c's.

von Roland H. (batchman)


Lesenswert?

Fabian K. schrieb:
> Es kommt gar nichts. Ich bevorzuge ehrlichgesagt jetzt mehr die
> Bitschreibweise, einfach viel weniger Schreibarbeit,

Bedeutet aber viel mehr Lesearbeit für den Rest der Welt

> Registerbeschreibungen kann ich in den Kommentaren ja immer noch
> ergänzen.

Du bist nicht verzweifelt genug :-)

von Fabian K. (fabian_k)


Lesenswert?

Das versteh ich natürlich. Einfach den Code vergessen. Was können 
mögliche Fehlerursachen für die Nullen sein? Baudratenberechnung?

((F_CPU/(16*USART_BAUD))-1) ist meine Berechnungsformel da mein 
Skalierungsfaktor 0 ist. Stimmt das? (Hab schon 1000mal alles 
kontrolliert, aber ich kann mich ja täuschen)

Danke im vorraus

von Coder (Gast)


Lesenswert?

1) Liegt tatsächlich der gewünschte CPU Takt an (z.B. mit blinkender LED 
prüfen, wenn Led 1Hz blinken soll, macht sie das auch? )

2) Empfängerseite richtig eingestellt?

3) Stimmt das Frameformat

von Roland H. (batchman)


Lesenswert?

> Einfach den Code vergessen.

Der war gut ;-)

> Was können
> mögliche Fehlerursachen für die Nullen sein? Baudratenberechnung?
>
> ((F_CPU/(16*USART_BAUD))-1) ist meine Berechnungsformel da mein
> Skalierungsfaktor 0 ist.

Was ist ein Skalierungsfaktor?

Zur Baudratenberechnung: Die sollte korrekt sein, ich verwende 
allerdings immer eine optimierte Formel, die findest Du hier im 
Tutorial.
Weiterhin füge ich der F_CPU ein "ul" an, und an die 16 würde ich ein 
"l" anhängen. Kann aber gut sein, dass der Compiler das dennoch korrekt 
macht.

Die Nullen können ein Indiz für einen "falschen" Takt sein. Entweder 
läuft der xmega nicht mit 32 MHz (mir ist Deine Initialsierung der Clock 
viel zu kurz, ich vermisse die Kalibierung) oder aber ist der Takt für 
die USART nicht gleich dem Takt der CPU. Ich setzte explizit "F_CPU" = 
"T_TIMER". Es kann z. B. sein, dass Dein USART mit F_CPU / 2 läuft.

von Fabian K. (fabian_k)


Lesenswert?

Hallo nochmal,

Empfängerseite ist sicher richtig eingestellt. Skalierungsfaktor ist zum 
skalieren der Baudrate, versteh ich auch nicht ganz, näheres steht im 
Datenblatt, brauch ich aber nicht.
Ich vermute die Clock-Init funktioniert nicht richtig, da die 
delay-Funktion gar nicht funktioniert und den Programmcode stoppt. Hier 
nochmal der Codeausschnitt:

OSC.CTRL = 0b00000010;  // 7:reserved | 6:reserved | 5:reserved | 
4:PLLEN    | 3:XOSCEN    | 2:RC32KEN  | 1:RC32MEN  | 0:RC2MEN
  while((OSC.STATUS & 0b000000010) == 0b00000000)  // warten bis der 
oszillator stabil ist
  {
  }
  CCP = 0b11011000;    // schutz
  CLK.CTRL = 0b00000001;  // 7:reserved | 6:reserved | 5:reserved | 
4:reserved | 3: reserved | 2:SCLKSEL2 | 1:SCLKSEL1 | 0:SCLKSEL0
  DFLLRC32M.CTRL = DFLL_ENABLE_bm;  // kalibrierung ?

Kann vielleicht irgendwer einen funktionierenden Code für die 
Initialisierung des Clock posten?

Danke im vorraus

von jojo (Gast)


Lesenswert?

Hallo Fabian,

soweit sieht deine Initialisierung OK aus, richtige Bits werden gesetzt 
und abgefragt (allerdings ist es wirklich einfacher die neue 
Schreibweise zu benutzen).
Eine Sache ist mir allerdings aufgefallen: Willst du den USART wirklich 
synchron benutzen? Wenn ja ist deine Formel richtig, andernfalls gelten 
die im Datenblatt obendrüber.

Für asynchronen Modus bekäme ich das raus:

BSEL: 2094 BSCALE: -7 Error: 0.010001 (ohne Garantie)

Hast du mal den Fehler überprüft, den du mit der obigen 
Baudratenberechnung hast?

Hier mal noch meine Clock-Init:

/*Oscillator auf 32Mhz einstellen PIN1 = OSC_RC32MEN wird gesetzt */
OSC.CTRL |= OSC_RC32MEN_bm;
/*Wenn Oscillator stabil wird das Flag RC32MRDY
* gesetzt und 32Mhz können benutzt werden*/
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
/*I/O Protection*/
CCP = CCP_IOREG_gc;
/*Clock auf 32Mhz einstellen*/
CLK.CTRL |= CLK_SCLKSEL_RC32M_gc;


Ist glaube ich auch zusammenkopiert, hat aber funktioniert.

Viele Grüße

Jojo

von Roland H. (batchman)


Lesenswert?

>   CCP = 0b11011000;    // schutz
>   CLK.CTRL = 0b00000001;  // 7:reserved | 6:reserved | 5:reserved |
> 4:reserved | 3: reserved | 2:SCLKSEL2 | 1:SCLKSEL1 | 0:SCLKSEL0

Clock source erst nach der Kalibierung

>   DFLLRC32M.CTRL = DFLL_ENABLE_bm;  // kalibrierung ?

Zu spät und unvollständig.
Aber immerhin die erste Konstante. Geht doch :-)

> Kann vielleicht irgendwer einen funktionierenden Code für die
> Initialisierung des Clock posten?

So und jetzt suchst Du nach "DFLLRC32M.CTRL = DFLL_ENABLE_bm" in diesem 
Forum.

Dann findest Du einen Thread "xmega interner 32 MhZ Takt geht nicht".
Dann nimmst Du den Code von Simon K. Mit den Konstanten.

Und spätestens jetzt sollte ein Licht aufgehen, warum das mit den 
Konstanten sinnvoll ist.

von Fabian K. (fabian_k)


Lesenswert?

Diesen Thread finde ich leider nicht. Diese Konstanten machen aber 
keinen Unterschied zu der Bitschreibweise, außer dass man ohne 
Kommentierung gleich erkennt was man setzt. Diese Group-Configurations 
sind schon was annderes, die machen einiges leichter.

von Fabian K. (fabian_k)


Lesenswert?

Schon gefunden.

von Fabian K. (fabian_k)


Lesenswert?

So, jetzt bin ich aber endgültig am verzweifeln. Code, wie von Roland 
vorgeschlagen aus dem Thread kopiert. Dazu hab ich ein Soft-PWM mit der 
_delay-Funktion gemacht. Port wird auf High gesetzt und das Programm 
hängt in der _delay-Funktion. Ich will wieder Fuse-Bits /:

von Roland H. (batchman)


Lesenswert?

> Ich will wieder Fuse-Bits /:

Nun, dann wäre Dein xmega inzwischen ziemlich "verfused" ;-)

Zeig mal den ganzen neuen Code, meine Glaskugel ist gerade kaputt.

von Fabian K. (fabian_k)


Angehängte Dateien:

Lesenswert?

Ich hab inzwischen den ganzen code nochmal neu geschrieben, die
entsprechenden Kapitel im Datenblatt durchgelesen, diesmal in der neuen
Schreibweise ( Roland wird sich freuen (: ). Ich hab den c-Code
angehängt.

von Fabian K. (fabian_k)


Lesenswert?

Achja, code geht trotz allem immer noch nicht. Hoffe irgendwer findet 
was (:

von xmega (Gast)


Lesenswert?

Servus,


Fabian K. schrieb:
> Hoffe irgendwer findet sich was


das wollen wir doch hoffen!

Ich habe mal vor einiger Zeit eine Anwendung für deine Probleme 
geschrieben.

Siehe: http://www.basteln-mit-avr.de/atxmega128a3.html#anfaenger

Gruß XMEGA

von Fabian K. (fabian_k)


Lesenswert?

Hey Danke (: dein Code funktioniert, jetzt muss ich nur noch 
herausfinden, warum meiner nicht funktioniert.

Vielen Dank

von Fabian K. (fabian_k)


Lesenswert?

Wenn ich den Code allerdings in ein neues Projekt packe und neu 
kompiliere, funkt es auch nicht.

von Fabian K. (fabian_k)


Lesenswert?

Das Ding will meine Clock nicht einstellen. Wie kann es sein, dass es 
bei allen in 4 Zeilen super funktioniert (was es ja auch sollte lt. 
Datenblatt), und bei mir nicht?

OSC.CTRL = OSC_RC32MEN_bm;  // internen oszillator (32Mhz) aktivieren
  while(!(OSC.STATUS & OSC_RC32MRDY_bm))
  {
  }
  DFLLRC32M.CTRL = DFLL_ENABLE_bm;  // autokalibrierung aktivieren

  CCP = CCP_IOREG_gc;          // schutz deaktivieren, zum aendern der 
mpu-clock
  CLK.CTRL = CLK_SCLKSEL_RC32M_gc;  // mpu-clock kann jetzt geaendert 
werden, 32Mhz als MPU-clock nutzen
  CCP = CCP_IOREG_gc;          // schutz deaktivieren, zum aendern des 
LOCK-registers
  CLK.LOCK = CLK_LOCK_bm;        // ab hier kann die MPU-clock bis zum 
naechsten RESET nicht geaendert werden!


Schutz hab ich deaktiviert, alles so wie es sein sollte. Hab dann mit 
einer LED abgefragt, ob die Bits richtig gesetzt wurden: NEIN.

Geht einfach nicht

von xmega (Gast)


Lesenswert?

Hallo,



Fabian K. schrieb:
> Geht einfach nicht

ist auf dem Board ein Quarz vorhanden, gelötet/gesteckt ?


Bei einigen Atxmega128.. ist es schon öfters vorgekommen, dass der nicht 
gebrauchte Takt explizit deaktiviert werden musste.

Bei dem Internen Takt von 2 Mhz

// Disable the unused oscillators: 32 MHz, 32 kHz

OSC.CTRL&= ~(OSC_RC32MEN_bm | OSC_RC32KEN_bm | OSC_XOSCEN_bm | 
OSC_PLLEN_bm);

Oder halt umgekehrt- bei dem Internen Takt von 32 Mhz


// Disable the unused oscillators: 2 MHz, internal 32 kHz

OSC.CTRL&= ~(OSC_RC2MEN_bm | OSC_RC32KEN_bm | OSC_XOSCEN_bm | 
OSC_PLLEN_bm);


Gruß Xmega

von Fabian K. (fabian_k)


Lesenswert?

Wo genau muss ich die unbenutzen Oszillatoren ausschalten? Bevor ich den 
anderen setze, nach der Kalibrierung, ...?


Hier nochmal die Init:

  OSC.CTRL = OSC_RC32MEN_bm;  // internen oszillator (32Mhz) aktivieren
  while(!(OSC.STATUS & OSC_RC32MRDY_bm))
  {
  }
  DFLLRC32M.CTRL = DFLL_ENABLE_bm;  // autokalibrierung aktivieren

  CCP = CCP_IOREG_gc;          // schutz deaktivieren, zum aendern der 
mpu-clock
  CLK.CTRL = CLK_SCLKSEL_RC32M_gc;  // mpu-clock kann jetzt geaendert 
werden, 32Mhz als MPU-clock nutzen
  CCP = CCP_IOREG_gc;          // schutz deaktivieren, zum aendern des 
LOCK-registers
  CLK.LOCK = CLK_LOCK_bm;        // ab hier kann die MPU-clock bis zum 
naechsten RESET nicht geaendert werden!

Es ist übrigens ein externer Quarz von 32kHz am TOSC1 und 2 PIN.
Ich bin wirklich kurz davor das Teil wieder zurückzuschicken.

Danke im vorraus

von Roland H. (batchman)


Lesenswert?

> Ich bin wirklich kurz davor das Teil wieder zurückzuschicken.

Stellt Dich diese Art von Problemlösung zufrieden?

Du hast geschrieben, dass es 1x funktioniert hat. Wo ist nun das 
Problem?

Bei den Code-Stücken, welche Du nach dieser Meldung gepostet hast, fehlt 
konsequent die Einstellung des Taktes für den USART - siehe Code von 
xmega. Ohne das wird es vermutlich nicht gehen.

Die Kalibrierung ist ebenso m. E. immer noch unvollständig, m. E. macht 
das nur Sinn, wenn z. B. gegen den internen 32kHz Oszillator kalibiert 
wird - siehe Code von Simon. K. Diese Kalibirierung ist vermutlich nicht 
einmal nötig, siehe Code von xmega. Schaden tut sie nicht, empfehlen 
würde ich es allemal.

Lass es ein paar Tage ruhen. Dann nochmals den ganzen Thread hier 
durchlesen, hier steht m. E. nach alles drin. Den funktionierenden Code 
als Ausgangsbasis nehmen. Und dann insbesondere die Behandlung des 
CLK.PSCTRL verstehen. Dazu muss man das "Clock system" des xmega 
verstehen.

Ja, es ist komplizierter als ein attiny/atmega. Aber es ist immer noch 
weit einfacher als z. B. das gleiche Setup eines ARMs, insbesondere wenn 
noch ein "fractional baud rate generator" ins Spiel kommt. Also, wo 
bleibt Dein Ehrgeiz ? :-)

Ich bin raus hier, weiteres Consulting nur gegen harte (oder inzwischen 
weiche) Euros :-)

von Fabian K. (fabian_k)


Lesenswert?

Ehrlichgesagt stellt mich das nich zufrieden, wenn ich das Teil 
zurückschicke.
Es hat einmal funktioniert ja, mit einem fertigem hex-File, dann wollte 
ich es neu kompilieren, geht nicht.
Ich hab die Kapitel im Datenblatt jetzt sicher schon 10x gelesen: 
Kalibrierung braucht man gar nicht, da werksseitig schon vorkalibriert 
ist. Die Kalibrierung findet standardmäßig mit dem 32khz-Quarz statt, 
außer man ändert das entsprechende Bit auf 1, dann wird der externe 
verwendet, also nicht unvollständig.
Ich finde es nur merkwürdig, dass der funktionierende Code auch nicht 
funktioniert, deswegen das mit dem zurückschicken.

Trotzdem Danke
Fabian

von Fabian K. (fabian_k)


Lesenswert?

Ich bins nochmal,

gibt es noch einen anderen Grund dafür, dass ich nicht in das CLK.CTRL 
Register schreiben kann, außer dass der Oszillator instabil ist und der 
Schutz noch aktiviert ist? (d.h. mein Oszillator ist stabil und der 
Schutz deaktiviert, ich kann aber dennoch nicht schreiben)

Danke im vorraus

von Uwe (Gast)


Lesenswert?

> Die Kalibrierung findet standardmäßig mit dem 32khz-Quarz statt,
> außer man ändert das entsprechende Bit auf 1.

Es gibt keinen internen Quarz nur einen internen RC-Oszillator.

von Gerhard G. (xmega)


Lesenswert?

Hallo,

also ich habe deinen Code usart_tests.c mal eingespielt- und er ist 
absolut stabil und lauffähig.

Vergiss  das mal mit der Kalibrierung. Die  ist eher für 
Langzeitstabilität interessant. Für kurze Tests klappt's auch so!

Es dürfte dann doch noch irgendwo ein Problem sein. Board, 
Terminalprogramm,FTDI-USB RS232 oder seriell

Kannst du deine eigenen Eingaben sehen, wenn du rxt mit txt brückst.

Noch ein Tipp: CodeWizardAVR V2.05.3 Evaluation
http://www.hpinfotech.ro/

CodeWizardAVR ist ein echt geniales Tool. Etwas eingeschränkt aber 
trotzdem für Clock, USART, SPI, Ports usw. Ins besonders für die 
Clock-Einstellung unverzichtbar!!!


Gruß xmega

von Fabian K. (fabian_k)


Lesenswert?

Na super, das lässt mich nur noch mehr verzweifeln, dass ich weiß, dass 
mein Code nur bei mir nicht funktioniert (:
Nein egal, Danke fürs Testen. Hab übrigens auch noch den Code vom 
Codewizard getestet (zum setzen der Clock), funkt aber auch nicht. (Aber 
super Programm (; ,danke für den Tipp )
Ich glaube ich wende mich an den Hersteller (mikroe).

von Fabian K. (fabian_k)


Lesenswert?

Danke an alle, die sich hier beteiligt haben. Ich habs jetzt 
hinbekommen. Die ganaue Ursache weiß ich auch nicht, ich habs über die 
Konsole kompiliert und es ging (:  Vielleicht hat mein AVR-Studio ja 
was.

MfG
Fabian

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.