C XMEGA -> USART -> SPI Mode

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. C#
Moin,

Die Baudrate passt überhaupt nicht habe ich das Gefühl.
Habe ich was bei der Berechnung übersehen?



CodeBox C

#define SPI_USART_CALC_BSEL( BSEL ) ([I]uint16_t[/I]) ( F_CPU / ( 2 * ( BSEL + 1 ) ) )

#define SPI_USART_CALC_BAUD( BAUD ) ([I]uint16_t[/I]) ( ( F_CPU / ( SPI_USART_CALC_BSEL( BAUD ) * 2 ) ) - 1 )


/* set baudrate */


usartx->usartUnit->BAUDCTRLA = ( SPI_USART_CALC_BAUD ( baud ) & 0x00FF );

usartx->usartUnit->BAUDCTRLB = ( ( SPI_USART_CALC_BAUD ( baud ) & 0x0F00 ) >> 8 );



upload_2018-7-20_10-3-0.png
 
Hallo Jan,

musst du nicht einfach nur die Gleichung in der Tabelle unten rechts verwenden, um BSEL zu ermitteln? Du mixt das irgendwie mit der Gleichung links daneben (die ist aber identisch nur umgestellt nach FBAUD).

Dirk :ciao:
 
Ja, in den beiden Baud-Controlregistern stehen die 12 Baud-Rate-Bits (BSEL11..0) und die vier Baud-Rate-Scale-Factor-Bits (BSCALE3..0).
Wenn also eine vorgegebene Baudrate eingestellt werden soll, müssen die entsprechenden BSELs berechnet und zugewiesen werden. Also die BSEL-Formel verwenden.

(Die andere Formel brauchst Du nur, wenn Du aus einer gegebenen BSEL-Einstellung die tatsächliche Baudrate berechnen willst (zB zum Bestimmen eines Baudratenfehlers. Ich hatte auch mal einen UART (+PWM-Timer) über 'ne IR-LED und'n TSOPfragmichmal geschickt. Die Baudrate wurde mittels Tastern ähnlich der BSELs eingestellt. Da habe ich dann die tatsächliche Baudrate auf'm Display sehen wollen (um zu sehen, wie weit der TSOP mitkam)).

In der Tabelle tauchen beim SPI-Mode keine fraktionellen Anteile mehr auf - die greifen nur im konventionellen UART? (will mich jetzt nicht durch das DB kauen...)
 
Du hast es grade nötig.

Wenn man Dich bittet ein compilierbares Projekt zu posten, wirst Du pampig

Dutzende von crosspostings in einem Jahr, obwohl Du mehrfach darauf hingewiesen wurdest, daß das nicht gerne gesehen wird.

Danach muß man nicht suchen, die fallen auf, egal unter welchem Pseudonym Du grade schreibst.

Wer nicht sagen kann oder will, wo er sonst noch überall fragt oder gefragt hat, dem unterstelle ich, daß er entweder zu faul oder zu blöd ist…

Bricht Dir ein Zacken aus der Krone, wenn Du schreibst (mit Link, und zwar in beiden Foren) wo Du zum Thema noch fragst?

Mehr verlangt doch niemand.

Dann weiß man, was andere schon geantwortet haben und braucht nicht nochmal das gleiche zu schreiben und kann sogar noch darauf aufbauen. Es läge also sogar noch in Deinem eigenen Interesse, wenn Du tatsächlich eine Lösung finden wolltest.

Wenn man allerdings nur raubmordkopieren und nichts lernen will, bleibt man natürlich besser anonym...
 
Zuletzt bearbeitet:
Hallo Jan,

musst du nicht einfach nur die Gleichung in der Tabelle unten rechts verwenden, um BSEL zu ermitteln? Du mixt das irgendwie mit der Gleichung links daneben (die ist aber identisch nur umgestellt nach FBAUD).

Dirk :ciao:

Am Anfang hatte ich diese Formel genommen gehabt.


CodeBox C
#define SPI_USART_CALC_BAUD( BAUD ) (uint16_t) ( ( F_CPU / ( F_CPU * 2  )  )  - 1 )

Also sollte es damit gegessen sein?
 
Wenn man Dich bittet ein compilierbares Projekt zu posten, wirst Du pampig
Das man noch auf solch alten Pferden reitet. Das Projekt von damals konnte ich mit einem ATMEL Studio 7.x kompilieren. Ich weiß ehrlich gesagt auch nicht wieso das bei Dir nicht funktionierte.

Dutzende von crosspostings in einem Jahr, obwohl Du mehrfach darauf hingewiesen wurdest, daß das nicht gerne gesehen wird.
Gebe ich ja auch zu. Ich komme mir wirklich "doof" vor, wenn ich etwas nicht verstehe und hier direkt ein "Thema" dazu aufmache. In dem anderen Forum, fallen so "kleine" Fragen überhaupt nicht groß auf.
Da dort leider auch keine Antwort kam und ich gerne wissen möchte was ich falsch mache, habe ich hier um Hilfe gebeten.

Wer nicht sagen kann oder will, wo er sonst noch überall fragt oder gefragt hat, dem unterstelle ich, daß er entweder zu faul oder zu blöd ist…
Das ist deine Sache, was du anderen unterstellst ;)
 
Am Anfang hatte ich diese Formel genommen gehabt.

#define SPI_USART_CALC_BAUD( BAUD ) (uint16_t) ( ( F_CPU / ( F_CPU * 2 ) ) - 1 )
Also sollte es damit gegessen sein?

Der Parameter BAUD kommt in der Gleichung nicht vor. Das funktioniert so garnicht.

Ich habe nicht in das Datenblatt geschaut, nach deinem Screenshot wird es wahrscheinlich so in Ordnung sein:

BSEL = (FPER / (2 x FBAUD)) -1

FPER ist die Taktfrequenz für das Peripheriemodul, das wird bei dir FCPU sein.

Ich habe selber bei Xmega schon das UART Modul im MasterSPI Mode verwendet, müsste aber jetzt mein Projekt raussuchen ... wird aber mit obiger Gleichung schon stimmen.

Berechne BSEL doch einfach auch mal manuell für deinen Fall.

Offtopic:
Wegen den Crosspostings, wäre es schon gut, wenn du kurz drauf hinweist.
Das wäre fair zu denjenigen, welche dir hier versuchen zu helfen.
https://de.wikipedia.org/wiki/Crossposting#Crossposting_in_Webforen
 
Moin,

@Dirk bist Du sicher das dass richtig ist?
9600 Baud ist langsamer..


CodeBox C
spiUsartxInit( spiUsart , 9600 , USART_SPI_MODE0 , USART_SPI_MSB_FIRST );


als wenn ich z.B


CodeBox C
spiUsartxInit( spiUsart , 40 , USART_SPI_MODE0 , USART_SPI_MSB_FIRST );

nehme..

Müsste es nicht eigentlich bei höheren Baudraten schneller gehen und nichts anders herum 0.o?

Hier initialisiere ich das Modul..


CodeBox C
void spiUsartxInit( spiIO_t *usartx , uint16_t baud , usartxSpiMode_enum mode , usartxSpiDataOrder_enum dataOrder )
{
 usartx->ports.spi->DIRSET   = (1<<usartx->bitPos.mosi);
 usartx->ports.spi->DIRSET   = (1<<usartx->bitPos.sck);
 
 usartx->ports.spi->DIRCLR   = (1<<usartx->bitPos.miso);

 
 /* master spi mode */
 usartx->usartUnit->CTRLC   = USART_CMODE_MSPI_gc;
 
  /* set baudrate */
 usartx->usartUnit->BAUDCTRLA  = SPI_USART_CALC_BSEL( baud ) & 0x00FF;
 usartx->usartUnit->BAUDCTRLB  = ( SPI_USART_CALC_BSEL( baud ) & 0x0F00 ) >> 8;
 
 switch ( dataOrder )
 {
  case USART_SPI_LSB_FIRST:
  {
   usartx->usartUnit->CTRLC |= ( 1<<USARTx_UDORD_bp ); // lsb first
  }break;
 
  case USART_SPI_MSB_FIRST:
  {
   usartx->usartUnit->CTRLC &= ~( 1<<USARTx_UDORD_bp ); // msb first
  }break;
 
  default:
  {
   usartx->usartUnit->CTRLC |= ( 1<<USARTx_UDORD_bp ); // lsb first
  }
 }

 
 /* set spi mode */
 switch ( mode )
 {
  case USART_SPI_MODE0: // Rising, sample  | Falling, setup
  {
   usartx->ports.spi->PIN1CTRL &= ~( PORT_INVEN_bm ); // clear inverted mode
   usartx->usartUnit->CTRLC &= ~( 1<<USARTx_UCPHA_bp );
  }break; // mode 0
  
  case USART_SPI_MODE1: // Rising, setup   | Falling, sample
  {
   usartx->ports.spi->PIN1CTRL &= ~( PORT_INVEN_bm ); // clear inverted mode
   usartx->usartUnit->CTRLC |=  ( 1<<USARTx_UCPHA_bp );
  }break; // mode 1
  
  case USART_SPI_MODE2: // Falling, sample | Rising, setup
  {
   usartx->ports.spi->PIN1CTRL |=  (PORT_INVEN_bm); // set inverted mode
   usartx->usartUnit->CTRLC &= ~(1<<USARTx_UCPHA_bp);
  }break; // mode 2
  
  case USART_SPI_MODE3: // Falling, setup  | Rising, sample
  {
   usartx->ports.spi->PIN1CTRL |= (PORT_INVEN_bm); // set inverted mode
   usartx->usartUnit->CTRLC |= (1<<USARTx_UCPHA_bp);
  }break; // mode 3
  
  default: // Falling, setup  | Rising, sample
  {
   usartx->ports.spi->PIN1CTRL |= (PORT_INVEN_bm); // set inverted mode
   usartx->usartUnit->CTRLC |= (1<<USARTx_UCPHA_bp);
  }break; // mode 3
 }

 PR.PRPC &= ~PR_USART0_bm; // enable USART
 
  /* enable spi receive enable & transmit enable */
  usartx->usartUnit->CTRLB |= ( ( 1<<USARTx_RXEN_bp ) | ( 1<<USARTx_TXEN_bp ) );
}
 
Wie sieht denn nun deine Berechnung von BSEL aus?

SPI_USART_CALC_BSEL( baud )

Zuvor hatte hier ja etwas nicht gestimmt.
 


CodeBox C
#define SPI_USART_CALC_BSEL( BAUD ) ([I]uint16_t[/I]) ( F_CPU / ( 2 * BAUD ) ) - 1
 
Hast Du einen Taschenrechner?
Dann kannst Du sehr leicht ausrechnen, was da passiert.
BSEL hat 12 Bit, also paßt da keine Zahl rein, die größer als 4095 bzw. 0xFFF ist.
Setz mal 40 in die Formel ein (in die Formel für die Baudrate natürlich und nicht in die für BSEL).
Um eine Baudrate von 40 einzustellen, darf F_CPU nicht größer als 327,68 kHz sein.

Das passiert, wenn man Code kopiert, der keine Überprüfung sinnvoller Grenzen macht...
 
BSEL hat 12 Bit, also paßt da keine Zahl rein, die größer als 4095 bzw. 0xFFF ist.
Ja, ich hatte auch gerade nachgerechnet.

Wahrscheinlich ist F_CPU 32.000.000
Dann wäre bei 40 Baud BSEL ca. 40.000, das geht somit nicht.
 
Stimmt. Er war bei 40 nur flotter weil die Berechnungen übergelaufen ist.. Bei 40 komme ich auf 65535. Das heißt es müsste dann im Register ne 1 stehen?
 
In dem Zusammenhang hat mich mal geärgert, daß man im Studio beim kompilieren zwar Warnings und Errors werfen lassen kann, aber dabei leider keine berechneten Compilerkonstanten ausgeben lassen kann...
Stimmt.
Vill. werden unsere Wünsche irgendwann nochmal erhöhrt.
 
Stimmt. Er war bei 40 nur flotter weil die Berechnungen übergelaufen ist.. Bei 40 komme ich auf 65535. Das heißt es müsste dann im Register ne 1 stehen?

Okay..
Was genau ist der Unterschied zwischen


CodeBox C
#define F_CPU         32e6


Und..


CodeBox C
#define F_CPU         32000000

???

Mit


CodeBox C
#define F_CPU         ( uint32_t ) 32e6

klappt es dann.. muss ich alles was größer als int ist bei nem #define casten?
 
Bei 40 komme ich auf 65535. Das heißt es müsste dann im Register ne 1 stehen?

Wie kommst du auf 65535 und 1?

Wenn du F_CPU 32MHz hast, kommt für BSEL 399.999 raus, geht also nicht. Max zulässig wären BSEL 4095d (12bit, 0xFFF).

Kleinstes FBAUD bei 32MHz wären 3906,25, wenn ich mich jetzt nicht vertippt habe.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)