unterschiedliche SPI Geschwindigkeiten

OP (Firma: keine) #2932899
Lesenswert?

Hallo,

ich habe folgende Frage.
Ich arbeite mit einem ATXMega128A1 und habe 4 SPI Teilnehmer an einer 
SPI Schnittstelle (Port F)
F_CPU 8MHz
prescaler 4
Das hat auch immer mit allen Busteilnehmer funktioniert allerdings muss 
ich für einen neue SPI Teilnehmer die Geschwindigkeit herabsetzen.
Kann man das in der Software ? Für jeden Busteilnehmer einen anderen 
prescaler definieren also während das programm läuft den prescaler 
einfach korrigieren ?

SPI_MasterInit(&spiMasterF,
                 &SPIF,
                 &PORTF,
                 false,
                 SPI_MODE_0_gc,
                 SPI_INTLVL_OFF_gc,
                 false,
                 SPI_PRESCALER_DIV4_gc);

Müsste ich dann jedesmal wenn ich die Geschw. korrigiere diese Funktion 
aufrufen ?

Vielen dank für Eure Bemühungen. Ich hoffe das ich mein problem 
verständlich dargestellt habe.

MfG
#2932901
Lesenswert?

Andreas S. schrieb:
> Für jeden Busteilnehmer einen anderen
> prescaler definieren also während das programm läuft den prescaler
> einfach korrigieren ?

Prinzipiell ja. Zumindest die Hardware hat da nichts dagegen.

> SPI_MasterInit(&spiMasterF,
>                  &SPIF,
>                  &PORTF,
>                  false,
>                  SPI_MODE_0_gc,
>                  SPI_INTLVL_OFF_gc,
>                  false,
>                  SPI_PRESCALER_DIV4_gc);
>
> Müsste ich dann jedesmal wenn ich die Geschw. korrigiere diese Funktion
> aufrufen ?

Tja. Da musst du mal in diese SPI Library reinschauen, was dir die an 
Funktionen anbietet und unter Umständen dann eben eine Funktion 
nachrüsten, mit der du nur den Prescaler änderst.
OP (Firma: keine) #2932937
Lesenswert?

Hallo,

das ganze basiert auf die application notes von Atmel.
Und die sieht so aus.
void SPI_MasterInit(SPI_Master_t *spi,
                    SPI_t *module,
                    PORT_t *port,
                    bool lsbFirst,
                    SPI_MODE_t mode,
                    SPI_INTLVL_t intLevel,
                    bool clk2x,
                    SPI_PRESCALER_t clockDivision)
{
  spi->module         = module;
  spi->port           = port;
  spi->interrupted    = false;

  spi->module->CTRL   = clockDivision |                  /* SPI 
prescaler. */
                        (clk2x ? SPI_CLK2X_bm : 0) |     /* SPI Clock 
double. */
                        SPI_ENABLE_bm |                  /* Enable SPI 
module. */
                        (lsbFirst ? SPI_DORD_bm  : 0) |  /* Data order. 
*/
                        SPI_MASTER_bm |                  /* SPI master. 
*/
                        mode;                            /* SPI mode. */

  /* Interrupt level. */
  spi->module->INTCTRL = intLevel;

  /* No assigned data packet. */
  spi->dataPacket = NULL;

   /* MOSI and SCK as output. */
  spi->port->DIRSET  = SPI_MOSI_bm | SPI_SCK_bm;
}

Jetzt kann ich natürlich eine Funktion ergänzen sodass ich nur noch den 
prescaler verändere. OK
Spricht etwas dagegen die ganze Initialisierung nochmal mit dem neuen 
prescaler aufzurufen ? Das ich dadurch Zeit vergeude weiss ich auch aber 
für mich wäre das zunächst die einfachste Variante.
#2933567
Lesenswert?

Hallo,

das Ganze schaut auf unterster Ebene so aus:
z.B.

SPIF.CTRL=SPI_MODE_0_gc|SPI_PRESCALER_DIV4_gc|(1<< SPI_ENABLE_bp)|(1<< 
SPI_MASTER_bp);
SPIF.INTCTRL = SPI_INTLVL_OFF_gc;
SPIF.STATUS = 0;


Nach dem die Datenübertragung abgeschlossen ist, würde ich den SPIF mit:

SPIF.CTRL &= ~(1<<SPI_ENABLE_bp) sperren und anschließend mit den 
veränderten Prescaler wieder starten.

SPIF.CTRL = SPI_PRESCALER_DIV64_gc|(1<< SPI_ENABLE_bp)wieder aktivieren.
SPIF.STATUS = 0;


Ein Versuch is es wert!


Gruß G.G.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren