WS2811 Lib (optimierungen)

OP #3626317
Lesenswert?

Hallo,

ich habe mir mal eine WS2811 Library geschrieben. Nunja, diese verstehe 
ich wenigstens. Klappen tut auch alles soweit aber ich würde diese noch 
ein wenig optimieren.

Mir geht es hautpsächlich darum das man das ganze noch mit der Frequenz 
machen kann. Also anhand der F_CPU.

Mit der berrechnung habe ich leider noch nicht soviele erfahrungen.

Derzeit habe ich das Fix auf 8Mhz erstellt. Ein Takt dauert demnach 
125ns aber wenn ich nun berechne z.b.

takttime = (((1 / F_CPU) * 1000) * 1000) * 1000

dann habe ich in takttime die taktzeit, bei 8Mhz also 125ns, aber wie 
geht es dann weiter?

Wenn ich das wiederrum mit einer berrechne und das wiederrum durch eine 
Schleife laufen lasse habe ich ja wieder ein timing problem was 
angepasst werden muss.

Ich hoffe ihr könnt mir da weiter helfen.
Angehängte Dateien:
OP #3626351
Lesenswert?

Habe mal was angepasst.

ws2811.h
1
int takttime = (((1 / F_CPU) * 1000) * 1000) * 1000;
2

3
int onehightakte = (1250 / takttime) - 1;
4
int onelowtakte =  (1250 / takttime) - 1;
5
int zerohightakte = (500 / takttime) - 1;
6
int zerolowtakte = (2000 / takttime) - 1;
ws2811.c
1
void wswrite_zero(void)
2
{
3
  // 500ns +- 150ns high
4
  WSPORT |= (1<<WSPIN); // 125ns
5
  for (int i=0; i<zerohightakte; i++)
6
  {
7
    nop();
8
  }
9
  // 2000ns +- 150ns low
10
  WSPORT &= ~(1<<WSPIN); // 125ns
11
  for (int i=0; i<zerolowtakte; i++)
12
  {
13
    nop();
14
  }
15

16
}
17

18
void wswrite_one(void)
19
{
20
  // 1200ns +- 150ns high
21
  WSPORT |= (1<<WSPIN); // 125ns
22
  for (int i=0; i<onehightakte; i++)
23
  {
24
    nop();
25
  }
26
  // 1300ns +- 150ns low
27
  WSPORT &= ~(1<<WSPIN); // 125ns
28
  for (int i=0; i<onelowtakte; i++)
29
  {
30
    nop();
31
  }
32
}
Moderator Persönliche Seite #3626394
Lesenswert?

Tobias N. schrieb:
> Habe mal was angepasst.
>
> ws2811.h
>
1
> int takttime = (((1 / F_CPU) * 1000) * 1000) * 1000;
2
> 
3
> int onehightakte = (1250 / takttime) - 1;
4
> int onelowtakte =  (1250 / takttime) - 1;
5
> int zerohightakte = (500 / takttime) - 1;
6
> int zerolowtakte = (2000 / takttime) - 1;
7
>

Da dieses Werte alle konstant sind, rate ich Dir, sie mit 
Preprocessor-Konstanten zu erschlagen. Dann kann die Berechnung durch 
den Compiler erfolgen und muß nicht mühselig vom µC erledigt werden.

Also:
1
#define TAKTTIME (((1 / F_CPU) * 1000) * 1000) * 1000

bzw. kürzer:
1
#define TAKTTIME (1000000000UL / F_CPU)

Rest:
1
#define ONEHIGHTAKTE  ((1250 / TAKTTIME) - 1)
2
#define ONELOWTAKTE   ((1250 / TAKTTIME) - 1)
3
#define ZEROHIGHTAKTE (( 500 / TAKTTIME) - 1)
4
#define ZEROLOWTAKTE  ((2000 / TAKTTIME) - 1)

Dieser Mischmasch aus deutsch und Englisch sieht aber schon irgendwie 
beknackt aus, oder? ;-)

Was meinst Du, was der Compiler daraus macht:
1
> for (int i=0; i<onelowtakte; i++)
2
> {
3
>     nop();
4
> }

Neben Initialisierung und ständigem Vergleich mit einer Variablen bzw. 
einem festen Wert auch noch "nebenbei" mal ein NOP. Deine Schleifen 
verbrauchen ein Vielfaches!

Mein Tipp: Benutze besser _delay_us(), das kann das wesentlich besser. 
Damit kannst Du dann Deine ganze Taktberechnungen bzw. Schleifen wieder 
rausschmeissen.
Moderator Persönliche Seite #3626419
Lesenswert?

Tobias N. schrieb:
> Ja sieht schon ein wenig komisch aus :) Kann man ja noch ändern *g*

Solltest Du auch, wenn Du es nochmal brauchst. Aber Du brauchst die 
Dinger gar nicht, s.u.

> Jetzt muss ich noch noch das Timing der Schleifen anpassen, richtig?

Schmeiss die Schleifen raus und ersetze sie durch delay_us (), also:
1
...
2
#include <util/delay.h>        // einfügen! Hier muss F_CPU bekannt sein!
3
...
4
void wswrite_zero(void)
5
{
6
  // 500ns +- 150ns high
7
  WSPORT |= (1<<WSPIN); // 125ns
8
  _delay_us (500);
9

10
  // 2000ns +- 150ns low
11
  WSPORT &= ~(1<<WSPIN); // 125ns
12
  _delay_us (2000);
13
}
14

15
void wswrite_one(void)
16
{
17
  // 1200ns +- 150ns high
18
  WSPORT |= (1<<WSPIN); // 125ns
19
  _delay_us (1200);
20

21
  // 1300ns +- 150ns low
22
  WSPORT &= ~(1<<WSPIN); // 125ns
23
  _delay_us (1300);
24
}

Dann kannst Du Dir den ganzen Takte-Heckmeck mit den Schleifen sparen.
Gast #3626425
Lesenswert?

och nö. so funktioniert c nicht. eine hochsprache ist einfach nicht 
dafür gedacht, taktzyklengenaues timing zu erzeugen.

versuche doch einen der hundert anderen ansätze hier auf dem board zu 
verstehen. da ist deine zeit besser investiert. --> wS2812
Moderator Persönliche Seite #3626442
Lesenswert?

Tobias N. schrieb:
> die nop(); sind ja asm. ein nop = 1 takt, 1 takt = 125ns :)

und Dein for(...) verbraucht nichts an CPU-Takten? Wenn Dein µC 10 NOPs 
machen soll, dann macht er auch noch mindestens 10 Vergleiche (Variable 
i mit einem Wert). Und das kostet bei jedem(!) Vergleich ein Vielfaches 
eines NOPs.

Deshalb schrieb ich: Wundert mich, dass es überhaupt mit Deinen 
Schleifen funktioniert.

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