Forum: Mikrocontroller und Digitale Elektronik XMega USART läuft nicht


von Markus R. (maggus)


Lesenswert?

Hallo zusammen,

ich habe mir jetzt mal so zum Ausprobieren einen XMega32A4 geholt und 
bring es einfach nicht fertig, ein Zeichen per USART zu senden. Im 
Terminal empfange ich lediglich jede Sekunde den Wert 0xF8, auf dem Oszi 
sieht man am TxD-Ausgang des AVRs nur einen kurzen Wechsel 3V->0V->3V. 
Habe ich irgendeine Konfiguration falsch / vergessen?
Quarz: 16Mhz mit PLL auf 32Mhz
BSCALE = -4 , BSEL = 3332  => 9600,96 Baud (mit den Formeln aus dem 
Datenblatt)
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
5
6
void clk_config(void) {
7
  // 16Mhz crystal, 256CKL startup
8
  OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_256CLK_gc;
9
  // enable external oscillator
10
  OSC.CTRL = OSC_XOSCEN_bm;
11
  // PLL-Source = external crystal,  PLL Factor = 2
12
  OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 2;
13
  while(!(OSC.STATUS & OSC_XOSCRDY_bm)); //Crystal Ready
14
  // enable PLL
15
  OSC.CTRL |= OSC_PLLEN_bm;
16
  while(!(OSC.STATUS & OSC_PLLRDY_bm)); //PLL Ready
17
  CLK.PSCTRL = 0x00;  // No Prescalers
18
  CCP = 0xD8;
19
  // Clock Source = PLL
20
  CLK.CTRL = CLK_SCLKSEL_PLL_gc;
21
}
22
23
24
void usart_init(void) {
25
  
26
  USARTD1.CTRLB = 0x18;  // RXEN, TXEN
27
  USARTD1.CTRLC = 0x02;  // 8N1 Asynchron
28
  
29
  USARTD1.BAUDCTRLB = 205;
30
  USARTD1.BAUDCTRLA = 4;
31
32
}
33
34
void usartC0_putc(unsigned char chr) {
35
36
  while(!(USARTD1.STATUS & USART_DREIF_bm));
37
  USARTD1.DATA = chr;
38
}
39
40
41
int main(void) {
42
43
  PORTD.DIR |= (1<<PIN7);    // TXD output
44
  PORTD.DIR &= ~(1<<PIN6);  // RXD input
45
  
46
  clk_config();
47
48
  usart_init();
49
  
50
  PORTD.DIR |= (1<<PIN3);  // LED
51
52
  while(1) {
53
    PORTD.OUTTGL |= PIN3_bm;  // LED Toggle
54
    _delay_ms(1000);
55
56
    usartC0_putc('x');
57
  }
58
59
60
61
}

mfg Markus

von Roland H. (batchman)


Lesenswert?

Ich habe es mir nicht im Detail angesehen, ein paar Dinge sind mir 
aufgefallen:

Deine Funktion benennt C0, in der Funktion verwendest Du D1 ... wirklich 
richtig angeschlossen?

Läuft er wirklich mit 16 MHz? Im Zweifel erst Mal den clock Kram 
weglassen und mit dem internen Standard probieren.

Und dann vergiss mal die olle attiny/atmega Schreibweise, und verwende 
die xmega Notation für GPIO: Das sollte so aussehen (die |= und &= ~ 
sind nicht mehr "in"):
1
    /* Enable USARTD1, RX, PD6 */
2
    PORTD.DIRCLR = PIN6_bm;
3
4
    /* Enable USARTD1, TX, PD7 */
5
    PORTD.DIRSET = PIN7_bm;
6
7
    PORTD.OUTTGL = PIN3_bm;  // LED Toggle

|= mag bei DIR ja noch gehen, aber bei OUTTGL?

Stört Dein LED toggle durch das |= die USART-Einstelllungen? Lege es mal 
auf einen anderen Port. In meinem Beispiel gibt es KEIN |=, nur ein =. 
Nicht, dass das |= die USART Settings löscht.

Bitte die Konstanten in usart_init aufdröseln, das entziffer ich nicht. 
Bitte mal USART_CMODE_ASYNCHRONOUS_gc, USART_RXEN_bm und Konsorten 
verwenden. Deinen Kommentaren traue ich nicht :-)

von XMEGA (Gast)


Lesenswert?

Servus,

Markus R. schrieb:
> Habe ich irgendeine Konfiguration falsch / vergessen?

so mach ich es, und es funktioniert.

void usart_init(void) {
  // Init USART 9600 bps  -> (F_CPU 32000000 0x7B/0xD6)
  // Init USART 9600 bps  -> (F_CPU 16000000 0xE5/0xBC)

  USARTD1.BAUDCTRLA = 0x7B;
  USARTD1.BAUDCTRLB = 0xD6;
  USARTD1.CTRLC = 0x03;  // Async, No Parity, 1 stop bit, 8 data bits
  USARTD1.CTRLB = 0x18;  // Enable RX and TX // kein CLK2X  !!!!!

}

Gruß XMEGA

von Ansgar K. (paulderbademeister)


Lesenswert?

Ist die Optimierung an?
1
  CCP = 0xD8;
2
  // Clock Source = PLL
3
  CLK.CTRL = CLK_SCLKSEL_PLL_gc;
Sonst könnte es hier passieren, dass der write nicht innerhalb von vier 
Zyklen erfolgt und dein Controller immer noch auf 2 MHz läuft.

Du kannst dir auch die Periphal Clock auf einen Portpin ausgeben lassen. 
Diese würde ich erst einmal mit dem Oszi messen und gucken, ob sie 
tatsächlich 32MHz beträgt. Wäre blöd am Rest rumzudoktern, wenn der 
Fehler dort liegt.

Ansonsten hat Roland recht, was die neuen GPIO der xmega angeht - 
read-modify-write ist sooooo 2009 ;)

1
USARTD1.CTRLC = 0x02;  // 8N1 Asynchron
Das hier sind allerdings auch 7 Datenbit laut Datenblatt.

von Markus R. (maggus)


Lesenswert?

Ansgar K. schrieb:
>
1
USARTD1.CTRLC = 0x02;  // 8N1 Asynchron
> Das hier sind allerdings auch 7 Datenbit laut Datenblatt.

Thx, daran lag es. Jetzt funktionierts einwandfrei.

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.