Forum: Mikrocontroller und Digitale Elektronik U(S)ART auf XMega D4?


von Rookie (Gast)


Lesenswert?

Hi,

ich habe hier Code, der eigentlich für einen ATMega328P gedacht ist und 
versuche, diesen für einen XMega D4 zu übersetzen. Bei der seriellen 
Schnittstelle wirft mir der Compiler diverse Fehler über unbekannte 
Register/Bezeichner UCSR0A, UCSR0B, U2X0, UBRR0H, UBRR0L, RXEN0, TXEN0, 
RXCIE0, UDRIE0 und USART_RX_vect.

Was hat sich beim D4 hier geändert - wie heißen die richtigen Register 
für die serielle Schnittstelle an PortC? Gibt es irgend eine 
Tabelle/Liste, wo die vergleichbaren Register zu finden sind?

:-)

von Alt Backen (Gast)


Lesenswert?

ATMega und ATXMega haben grundsätzlich unterschiedliche Registernamen.

Rookie schrieb:
> Gibt es irgend eine
> Tabelle/Liste, wo die vergleichbaren Register zu finden sind?

Ja, die beiden Datenblätter der Controller die du benutzt.

von Rookie (Gast)


Lesenswert?

Alt Backen schrieb:
> ATMega und ATXMega haben grundsätzlich unterschiedliche
> Registernamen.

Sind denn nur die Namen anders oder haben die auch eine andere 
Funktionsweise?

> Ja, die beiden Datenblätter der Controller die du benutzt.

Leider kenne ich mich damit nicht wirklich aus und versuche her nur, 
eine Anleitung aus dem Internet umzusetzen...

von Timmo H. (masterfx)


Lesenswert?

Rookie schrieb:
> Sind denn nur die Namen anders oder haben die auch eine andere
> Funktionsweise?
Beides. Die UARTS vom Xmega sind viel universeller z.B. auch im 
SPI-Mode.

Mir reicht eigentlich immer sowas:
1
static FILE mystdout = FDEV_SETUP_STREAM( uart_putc, NULL, _FDEV_SETUP_WRITE);
2
static FILE mystdin = FDEV_SETUP_STREAM( NULL, uart_getc, _FDEV_SETUP_READ);
3
4
int main(void){
5
  init_cpuclock();
6
  init_uart();
7
  stdout = &mystdout;
8
  stdin = &mystdin;
9
10
  printf("Hallo Welt\n");
11
12
  //dein Code
13
14
}
15
16
//uart.c
17
void init_uart(void){
18
  PORTE.DIR |= (1<<PIN3);
19
  
20
  USARTE0.CTRLC = USART_CHSIZE_8BIT_gc;
21
  USARTE0.BAUDCTRLA = 131; //115200 Baud @ 32 MHz
22
  USARTE0.BAUDCTRLB = 0xD0; 
23
24
  USARTE0.CTRLB |= (1<<USART_TXEN_bp) | (1<<USART_RXEN_bp);
25
26
}
27
28
29
void uart_putc(unsigned char c, FILE *stream){
30
31
  while (!(USARTE0_STATUS & (1<<USART_DREIF_bp)));
32
33
  USARTE0_DATA = c;
34
35
}
36
unsigned char uart_getc(FILE *stream){
37
  while(!(USARTE0_STATUS & (1<<USART_RXCIF_bp)));
38
  return USARTE0_DATA;
39
}

: Bearbeitet durch User
von J. Zimmermann (Gast)


Lesenswert?

Dieses Register-Namen-Durcheinander wie bei den Megas oder 8bit-PIGs 
gibts beim XMEGA nicht. Immer: HARDWARE-UNIT PUNKT REGISTER, also 
USARTC0.CTRLA ...
Scheint anfangs aufwendiger, hat Vorteile. Ich verwende selbst bei 
kleinen Projekten nur noch XMEGAs.
z.B. lassen sich auch sehr schön alias verwenden, gibt der HW-UNIT 
einfach den Namen seiner Nutzung, f.E., #define RS485_UART USARTC0, der 
Quelltext wird übersichtlicher. Hardware-Änderungen bei lfd. Entwicklung 
sind so viel einfacher "einarbeitbar".
Serielle Kommunikation: Der "reichliche" RAM  der XMEGAs erlaubt die 
Verwendung von 256-Byte-Ringpuffern, als quasi "wartefreies" Senden:
(Atmel Studio 7, ohne ini)

#define SERCOM USARTC0
#define SERCOM_DREINT USARTC0_DRE_vect
#define SERCOM_RXCINT USARTC0_RXC_vect

byte rxbuffer[256];
volatile byte rxbuffer_write_ix;
volatile byte rxbuffer_read_ix;
byte txbuffer[256];
volatile byte txbuffer_write_ix;
volatile byte txbuffer_read_ix;
volatile byte rxed_cmd_cnt;

rs232_send_char(char c)
{
  if(SERCOM.STATUS & USART_DREIF_bm) SERCOM.DATA=c;
  else
  {
    txbuffer[txbuffer_write_ix++]=c;
    SERCOM.CTRLA |= USART_DREINTLVL_LO_gc;
  }
}

ISR (SERCOM_DREINT)
{
  if(txbuffer_read_ix==txbuffer_write_ix) SERCOM.CTRLA &=
        ~USART_DREINTLVL_LO_gc;
  else SERCOM.DATA=txbuffer[txbuffer_read_ix++];
 }

ISR (SERCOM_RXCINT)
{
  byte rxd=SERCOM.DATA;
  if(rxd==rx_term)
  {
    rxed_cmd_cnt++;
  }
  else rxbuffer[rxbuffer_write_ix++]=rxd;
}

interrupt.h include nicht vergessen, bei "grossem" Datenverkehr müssen 
die Buffer selbstredend auf Overrun getestet werden.

mfg
Achim

von Auf Gemerkt (Gast)


Lesenswert?

J. Zimmermann schrieb:
> interrupt.h include nicht vergessen, bei "grossem" Datenverkehr müssen
> die Buffer selbstredend auf Overrun getestet werden.

Schön wie die Fachleute hier rücksichtslos ihre Fachbeiträge
reinknallen. Kann eigentlich nur der Selbstdarstellung dienen,
wenn ich den Level und die Einstellung des Anliegen-Habenden
betrachte.

Rookie schrieb:
> Leider kenne ich mich damit nicht wirklich aus und versuche her nur,
> eine Anleitung aus dem Internet umzusetzen...

von Dieter F. (Gast)


Lesenswert?

Rookie schrieb:
> Leider kenne ich mich damit nicht wirklich aus und versuche her nur,
> eine Anleitung aus dem Internet umzusetzen...

Welche? (Link)

Warum auf XMega umsetzen?

von J. Zimmermann (Gast)


Lesenswert?

Auf Gemerkt:
> Schön wie die Fachleute hier rücksichtslos ihre Fachbeiträge
> reinknallen. Kann eigentlich nur der Selbstdarstellung dienen,
> wenn ich den Level und die Einstellung des Anliegen-Habenden
> betrachte.
Wollte eigentlich helfen, aber wenn das so rüberkommt, kann ich's auch 
lassen, dann können Leute wie Du hier Ihren inhaltslosen Quatsch 
ablassen.
mfg
Achim

von Rookie (Gast)


Lesenswert?

Dieter F. schrieb:
> Rookie schrieb:
>> Leider kenne ich mich damit nicht wirklich aus und versuche her nur,
>> eine Anleitung aus dem Internet umzusetzen...
>
> Welche? (Link)
>
> Warum auf XMega umsetzen?

Ich versuche das hier zu bauen: https://github.com/gnea/grbl

Dazu hatte ich noch ein HOWTO, das beschrieben hat, was für eine andere 
CPU zu ändern ist (das war allerdings auch nicht für den XMega).

Im Makefile habe ich den Wert für DEVICE und CLOCK schon angepasst. 
Ebenso die anderen PORT-Werte in der cpu_map.h. Jetzt stolpert er mir 
halt noch über die Fehler in grbl/serial.c sowie über ein

grbl/cpu_map.h:159:25: Warnung: »USART_UDRE_vect« appears to be a 
misspelled signal handler, missing __vector prefix [-Wmisspelled-isr]
   #define SERIAL_UDRE   USART_UDRE_vect

XMega deswegen, weil ich so ein Board hier habe und keins mit dem 328P.

von Dieter F. (Gast)


Lesenswert?

Rookie schrieb:
> XMega deswegen, weil ich so ein Board hier habe und keins mit dem 328P.

Ganz ehrlich, kaufe Dir ein Arduino Nano board (um die 5 € bei eBay z.B. 
https://www.ebay.de/itm/Arduino-Nano-Atmega328P-BEREITS-GELOTET-verlotet-fertig-aufgebaut/253638131454) 
- wenn Du Zeit hast auch für deutlich weniger Geld aus China - und packe 
dort die Software drauf.

Die Alternative ist, dass Du Dich wirklich mit den beiden Datenblättern 
und den "Besonderheiten" des ATXMega beschäftigst. Eine Portierung von 
ATMega auf ATXMega ist schon eine mittlere Aufgabe - das wird hier 
niemand für Dich erledigen.

von J. Zimmermann (Gast)


Lesenswert?

in Atmel-Studio (?)
#define SERIAL_UDRE USARTC0_DRE_vect
oder #define SERIAL_UDRE USARTC1_DRE_vect
jenachdem, ob Du USARTC0 (RXD auf C2, TXD C3) oder USARTC1 (RXD C6, TXD 
C7) benutzt
mfg
Achim

von Auf Gemerkt (Gast)


Lesenswert?

Dieter F. schrieb:
> Eine Portierung von
> ATMega auf ATXMega ist schon eine mittlere Aufgabe - das wird hier
> niemand für Dich erledigen.

Ist doch schon gemacht.

Ein Fachmann klatscht hier seine Sourcen und seine Fach-
ausdrücke rein - und schon ist das Problem gelöst.

von Rookie (Gast)


Lesenswert?

Dieter F. schrieb:
> Ganz ehrlich, kaufe Dir ein Arduino Nano board (um die 5 € bei eBay z.B.
> Ebay-Artikel Nr. 253638131454)
> - wenn Du Zeit hast auch für deutlich weniger Geld aus China - und packe
> dort die Software drauf.

Es ist keine Preisfrage, vielmehr läuft der XMega mit der doppelten 
Taktfrequenz und ich hoffe, auf die Art auch eine doppelte maximale 
Stepfrequenz zu erreichen.

J. Zimmermann schrieb:
> in Atmel-Studio (?)
> #define SERIAL_UDRE USARTC0_DRE_vect
> oder #define SERIAL_UDRE USARTC1_DRE_vect
> jenachdem, ob Du USARTC0 (RXD auf C2, TXD C3) oder USARTC1 (RXD C6, TXD
> C7) benutzt
> mfg
> Achim

Funktioniert! Jetzt hängen da noch so Fehler wie

grbl/serial.c:73:5: Fehler: »UCSR0A« nicht deklariert (erste Verwendung 
in dieser Funktion)
     UCSR0A |= (1 << U2X0);  // baud doubler on for high baud rates, 
i.e. 115200
     ^
grbl/serial.c:73:5: Anmerkung: jeder nicht deklarierte Bezeichner wird 
nur einmal für jede Funktion, in der er vorkommt, gemeldet
grbl/serial.c:73:21: Fehler: »U2X0« nicht deklariert (erste Verwendung 
in dieser Funktion)
     UCSR0A |= (1 << U2X0);  // baud doubler on for high baud rates, 
i.e. 115200
                     ^
grbl/serial.c:75:3: Fehler: »UBRR0H« nicht deklariert (erste Verwendung 
in dieser Funktion)
   UBRR0H = UBRR0_value >> 8;
   ^
grbl/serial.c:76:3: Fehler: »UBRR0L« nicht deklariert (erste Verwendung 
in dieser Funktion)
   UBRR0L = UBRR0_value;
   ^
grbl/serial.c:79:3: Fehler: »UCSR0B« nicht deklariert (erste Verwendung 
in dieser Funktion)
   UCSR0B |= (1<<RXEN0 | 1<<TXEN0 | 1<<RXCIE0);
   ^
grbl/serial.c:79:17: Fehler: »RXEN0« nicht deklariert (erste Verwendung 
in dieser Funktion)
   UCSR0B |= (1<<RXEN0 | 1<<TXEN0 | 1<<RXCIE0);
                 ^
grbl/serial.c:79:28: Fehler: »TXEN0« nicht deklariert (erste Verwendung 
in dieser Funktion)
   UCSR0B |= (1<<RXEN0 | 1<<TXEN0 | 1<<RXCIE0);

rum.

von Bastian W. (jackfrost)


Lesenswert?

Du wir’s es komplett portieren  müssen, da die Register anders sind beim 
xMega.

Gruß JackFrost

von J Zimmermann (Gast)


Lesenswert?

Auf Gemerkt:
> Ein Fachmann klatscht hier seine Sourcen und seine Fach-
> ausdrücke rein - und schon ist das Problem gelöst.
Hättest Du gern mehr solche hohlen Beiträge wie Deine? Wenn Dich Dein 
Unwissen zerfrisst, geh zu Freud.

Rookie:
> XMega deswegen, weil ich so ein Board hier habe und keins mit dem 328P.
Halte auch nichts davon, jedes mal, wenn ein Programmier-Problem 
auftritt, die Plattform zu wechseln, das bedeutet auch Zeitaufwand und 
irgendwann hast Du dann einen Schrank voller nicht funktionierender 
Hardware.

Wenn Du weiter XMEGA programmieren willst: Nimm Dir das Datenblatt, 
wähle das Kapitel der zu programmierenden Hardware-Unit, Unterkapitel 
Registerbeschreibung und arbeite die einzelnen Register der Reihe nach 
ab.

statt RXCIE0:
USARTC0.CTRLA=USART_RXCINTLVL_LO_gc;
statt RXEN0, TXEN0, U2X0:
USARTC0.CTRLB=USART_RXEN_bm | USART_TXEN_bm | USART_CLK2X_bm;
statt UBRR0L, H:
USARTC0.BAUDCTRLA=0x0F;
USARTC0.BAUDCTRLB=0xD1;

Ausserdem muss beim XMEGA der Programmierbare Interrupt Controller
eingestellt werden:
PMIC.CTRL=PMIC_LOLVLEN_bm | PMIC_RREN_bm;

Der TX-Port als Ausgang, Hi:
#define TX_PIN  3 // (für USARTC1: 7 einsetzen)
PORTC.OUTSET=1<<TX_PIN;
PORTC.DIRSET=1<<TX_PIN;

Wir kriegen das zum Laufen, auch wenn hier einer immer dazwischen 
labert.

mfg
Achim

von Dieter F. (Gast)


Lesenswert?

J Zimmermann schrieb:
> Halte auch nichts davon, jedes mal, wenn ein Programmier-Problem
> auftritt, die Plattform zu wechseln, das bedeutet auch Zeitaufwand und
> irgendwann hast Du dann einen Schrank voller nicht funktionierender
> Hardware.

Rookie schrieb:
> Es ist keine Preisfrage, vielmehr läuft der XMega mit der doppelten
> Taktfrequenz und ich hoffe, auf die Art auch eine doppelte maximale
> Stepfrequenz zu erreichen.

Mir scheint, da fehlt Erfahrung auf beiden Plattformen. Aber ich möchte 
nicht weiter stören ... :-)

von Rookie (Gast)


Lesenswert?

Dieter F. schrieb:

> Rookie schrieb:
>> Es ist keine Preisfrage, vielmehr läuft der XMega mit der doppelten
>> Taktfrequenz und ich hoffe, auf die Art auch eine doppelte maximale
>> Stepfrequenz zu erreichen.
>
> Mir scheint, da fehlt Erfahrung auf beiden Plattformen. Aber ich möchte
> nicht weiter stören ... :-)

Wieso sollte das nicht so sein? Die PWM-Frequenz leitet sich ja auch vom 
CPU-Takt ab!

von Timmo H. (masterfx)


Lesenswert?

Rookie schrieb:
> Es ist keine Preisfrage, vielmehr läuft der XMega mit der doppelten
> Taktfrequenz und ich hoffe, auf die Art auch eine doppelte maximale
> Stepfrequenz zu erreichen.
Also die ISR(TIMER1_COMPA_vect) die bei GRBL letzten Endes die Steps 
erzeugt arbeitet mit 30 kHz. Es sind also maximal 30000 kSteps/s 
möglich. Was bei 16 µSteps mit einer Spindel mit 8mm Steigung 75 mm/s 
sind.

Der begrenzende Faktor dabei ist, dass eben die ISR schneller 
abgearbeitet sein muss bevor der nächste Tick erzeugt wird. Beim Xmega 
werden die Befehle natürlich durch die höhere Taktrate i.d.R. schneller 
abgearbeitet weswegen man den Tick dann auch beschleunigen kann. Im 
besten Fall eben um das doppelte.
Problem ist eben dass bei steigender Geschwindigkeit eben auch das 
Drehmoment der Schrittmotoren abnimmt. Zwar wird hier mit Beschleunigung 
gearbeitet, aber irgendwann ist halt Schluss.

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Rookie schrieb:
> Wieso sollte das nicht so sein? Die PWM-Frequenz leitet sich ja auch vom
> CPU-Takt ab!

Hast Du Dein Zitat auch mal gelesen? Ich schrieb, das es scheinbar an 
Erfahrung auf beiden (Hardware-) Plattformen fehlt. Nichts von Frequenz 
und Takt etc.

von Krrx (Gast)


Lesenswert?

Timmo H. schrieb:
> Rookie schrieb:
>> Es ist keine Preisfrage, vielmehr läuft der XMega mit der doppelten
>> Taktfrequenz und ich hoffe, auf die Art auch eine doppelte maximale
>> Stepfrequenz zu erreichen.
> Also die ISR(TIMER1_COMPA_vect) die bei GRBL letzten Endes die Steps
> erzeugt arbeitet mit 30 kHz.

Diese Begrenzung existiert aber nur, wenn MAX_STEP_RATE_HZ gesetzt ist!? 
Per Default ist dieser Parameter zwar auf 30000 festgelegt, in GRBL 1.1 
aber auskommentiert.

von Timmo H. (masterfx)


Lesenswert?

Krrx schrieb:
> Diese Begrenzung existiert aber nur, wenn MAX_STEP_RATE_HZ gesetzt ist!?
Nein das Define ist nur zum Prüfen und standardmäßig deaktiviert, aber 
das steht ja auch im Kommentar darüber
1
// Sets the maximum step rate allowed to be written as a Grbl setting. This option enables an error 
2
// check in the settings module to prevent settings values that will exceed this limitation. The maximum
3
// step rate is strictly limited by the CPU speed and will change if something other than an AVR running
4
// at 16MHz is used.
5
// NOTE: For now disabled, will enable if flash space permits.
6
// #define MAX_STEP_RATE_HZ 30000 // Hz
Die tatsächliche Tickrate wird in Zeile 772ff (stepper.c) berechnet und 
gesetzt.

: Bearbeitet durch User
von Rookie (Gast)


Lesenswert?

Timmo H. schrieb:

> Die tatsächliche Tickrate wird in Zeile 772ff (stepper.c) berechnet und
> gesetzt.

Da steht was von

      #ifdef VARIABLE_SPINDLE
        bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); // 
Force update whenever updating block.
      #endif

Für mich sieht das eher aus, als ob da irgend ein Bit gesetzt wird?

von Timmo H. (masterfx)


Lesenswert?

Bei 1.1 stehts 171 Zeilen weiter unten
https://github.com/gnea/grbl/blob/master/grbl/stepper.c#L943

von Krrx (Gast)


Lesenswert?

Timmo H. schrieb:
> Bei 1.1 stehts 171 Zeilen weiter unten
> https://github.com/gnea/grbl/blob/master/grbl/stepper.c#L943

Und dort berechnet sich TICKS_PER_MICROSECOND aus F_CPU - d.h. ein 
erhöhen der Taktfrequenz sollte also in der Tat für einen höhere 
maximale Stepfrequenz sorgen können. Die Annahme des TO ist also 
richtig.

von Timmo H. (masterfx)


Lesenswert?

Gerade auf Hackaday gesehen, dass jemand GRBL auf den ESP32 portiert 
hat. Vielleicht auch mal ganz interessant.

http://www.buildlog.net/blog/2018/07/grbl-cnc-firmware-on-esp32/

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.