Forum: Mikrocontroller und Digitale Elektronik unterschiedliche SPI Geschwindigkeiten


von Andreas S. (Firma: keine) (ovoron)


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

von Karl H. (kbuchegg)


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.

von Andreas S. (Firma: keine) (ovoron)


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.

von xfr (Gast)


Lesenswert?

Klar, kannst Du machen. In die anderen Register wird dann halt nochmal 
das geschrieben, was schon drinnen stand. Kostet ein paar Takte mehr, 
sollte aber keine Nebenwirkungen haben.

von QUAX (Gast)


Lesenswert?

hi,
ich hab mal festgestellt, dass vor Änderungen die register resettet 
werden müssn sonst kommt das timinig beim umschalten durceinander

bye

von Andreas S. (Firma: keine) (ovoron)


Lesenswert?

@QUAX
kannst du noch etwas mehr dazu schreiben.
Und wie hast du die Register resettet ?
Wenn ich alle neu ueberschreibe und das ganze eh nicht im Interrupt 
laufen habe sollte es doch keine Probleme geben.

von Gerhard G. (g_g)


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.

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.