Forum: Mikrocontroller und Digitale Elektronik FCK Prescaler spi_init() sinnvoll mitteilen


von Stefan S. (sschultewolter)


Lesenswert?

Hallo,

ich hätte mal eine kurze Frage, wie man sowas am besten lösen kann.

Ich übergebe der derzeitigen spi_init() meines Attiny841 ein mit, wie 
schnell dir Frequenz sein soll.
1
void spi_init(uint8_t prescaler)
2
{
3
  DDRA |= (1<<DDRA7) | (1<<DDRA6) | (1<<DDRA4);
4
  SPCR = (1<<SPE) | (1<<MSTR);
5
  SPSR &= ~(1<<SPI2X);
6
  
7
  switch(prescaler)
8
  {
9
    case 4:    return;
10
    case 16:  SPCR |= (1<<SPR0); break;
11
    case 64:  SPCR |= (1<<SPR1); break;
12
    case 128:  SPCR |= (1<<SPR1) | (1<<SPR0); break;
13
    case 2:    SPSR |= (1<<SPI2X); break;
14
    case 8:    SPSR |= (1<<SPI2X); SPCR |= (1<<SPR0); break;
15
    case 32:  SPSR |= (1<<SPI2X); SPCR |= (1<<SPR1); break;
16
    //case 64:  SPSR |= (1<<SPI2X); SPCR |= (1<<SPR1) | (1<<SPR0); break;
17
    default:  return;
18
  }
19
}
20
21
22
23
24
// ODER
25
26
27
#define SPI_FCK      128
28
#define SPI_USE_SPI2X
29
void spi_init(void)
30
{
31
  DDRA |= (1<<DDRA7) | (1<<DDRA6) | (1<<DDRA4);
32
  SPCR = (1<<SPE) | (1<<MSTR);
33
  
34
  #if (SPI_FCK == 16)
35
  SPCR |= (1<<SPR0);
36
  #elif (SPI_FCK == 64)
37
  SPCR |= (1<<SPR1);
38
  #elif (SPI_FCK == 128)
39
  SPCR |= (1<<SPR1) | (1<<SPR0);
40
  /*
41
  #else // SPI_FCK == 4 || SPI_FCK fehlerhaft
42
  */
43
  #endif
44
  
45
  #ifdef SPI_USE_SPI2X
46
  SPSR |= (1<<SPI2X);
47
  #endif
48
}

Das ganze produziert im Vergleich zur direkten Zuweisung natürlich 
deutlich mehr Programmspeicher. Gibt es da ansonsten Ansätze, dass noch 
kürzer zu lösen?

von Mitlesa (Gast)


Lesenswert?

Stefan S. schrieb:
> as ganze produziert im Vergleich zur direkten Zuweisung natürlich
> deutlich mehr Programmspeicher.

Du vergleichst Äpfel mit Birnen. Das eine ist eine Konfiguration
"at runtime" die dort Änderungen zulässt, das andere eine
festverdrahtete unflexible Vorprogrammierung.

von Timmo H. (masterfx)


Lesenswert?

Du kannst in deiner Routine noch das F_CPU verwenden um daraus die 
Frequenz und dementsprechend den Prescaler zu errechnen.

von Stefan S. (sschultewolter)


Lesenswert?

Also mir geht es nicht darum, den Clock während des Betriebes zu ändern. 
Diesen setze ich einmal im Programm fix fest für das langsamste SPI 
Gerät.

Deshalb brauche ich die obere Lösung nicht.

Das mit der F_CPU mit reinzunehmen wäre nicht einmal eine schlechte 
Idee.

#define FCK  1000000UL // Gibt den Takt des langsamen Geraetes an

von Thomas E. (thomase)


Lesenswert?

1
#define SPI_FCK      128
2
3
void spi_init(void)
4
{
5
...
6
 switch(SPI_FCK)
7
 {
8
  case 2:... break;
9
  case 4:... break;
10
  ...
11
  case 128:... break;
12
 }
13
...

Jetzt werden nur die Anweisungen hinter "case 128" ins Programm 
eingebaut, da der Rest nie erreicht und vom Compiler wegoptimiert wird.


mfg.

von Stefan S. (sschultewolter)


Lesenswert?

Danke!

Ich hatte jetzt sowas mal mit der F_CPU Berechnung angestellt.
1
  
2
  #define SPI_FCK    10UL
3
  #define PRESCALER  (F_CPU/SPI_FCK)
4
  #if    (PRESCALER > 64)
5
  #warning "SPI Speed not supported"
6
  #elif    (PRESCALER >= 64)
7
  SPCR |= (1<<SPR1);
8
  #elif  (PRESCALER < 32)
9
  SPCR |= (1<<SPR1);
10
  SPSR |= (1<<SPI2X);
11
  #elif  (PRESCALER < 16)
12
  SPCR |= (1<<SPR0);
13
  #elif  (PRESCALER < 8)
14
  SPCR |= (1<<SPR0);
15
  SPSR |= (1<<SPI2X);
16
  #elif  (PRESCALER < 4)
17
  #elif  (PRESCALER < 2)
18
  SPSR |= (1<<SPI2X);
19
  #endif

Nur schnell zusammengeschrieben, muss nicht funktionsfähig sein, es 
können auch Fehler beim Abschreiben aus dem DB entstanden sein.

von Thomas E. (thomase)


Lesenswert?

Stefan S. schrieb:
> #elif    (PRESCALER >= 64)
>   SPCR |= (1<<SPR1);
>   #elif  (PRESCALER < 32)
>   SPCR |= (1<<SPR1);
>   SPSR |= (1<<SPI2X);
>   #elif  (PRESCALER < 16)
>   SPCR |= (1<<SPR0);
>   #elif  (PRESCALER < 8)
>   SPCR |= (1<<SPR0);
>   SPSR |= (1<<SPI2X);
>   #elif  (PRESCALER < 4)
>   #elif  (PRESCALER < 2)
>   SPSR |= (1<<SPI2X);

so funktioniert das nicht.

Wenn PRESCALER <2, 4, 8, 16 oder 32 ist, ist es auch <=64. Somit ist 
immer die erste Bedingung erfüllt.
Also den kleinsten Wert zuerst prüfen.

mfg.

von Stefan S. (sschultewolter)


Lesenswert?

Das war auch noch falsch
#elif    (PRESCALER >= 64)
Muss in die andere Richtung. Aber wie gesagt, so vom Prinzip hatte ich 
mir das Gedacht. Deine Variante mir schlank genug ! Werde den FCK 
Berechnung dann erst einmal auch nicht reinnehmen. Hab meist nur 2 
Szenarien. Entweder 8MHz oder 1MHz

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.