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.
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 | }
|
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.
:
Bearbeitet durch Moderator
Hallo, cool, danke :) Ja sieht schon ein wenig komisch aus :) Kann man ja noch ändern g Jetzt muss ich noch noch das Timing der Schleifen anpassen, richtig? Und ggf. wenn eine "krumme" zahl raus kommt anpassen, richtig?
_delay_us() bringt mir nichts da ich das ganze ja im NS bereich brauche.
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.
:
Bearbeitet durch Moderator
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
Tobias N. schrieb: > _delay_us() bringt mir nichts da ich das ganze ja im NS bereich brauche. Du hast recht, mein Fehler. Sorry. Ich bin erstaunt, dass das mit den Schleifen überhaupt klappt.
meine güte, ich sehe gerade dass das bereits dein dritter thread mit diesem fehlgeleiteten ansatz ist...
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.
wurg schrieb: > versuche doch einen der hundert anderen ansätze hier auf dem board zu > verstehen. da ist deine zeit besser investiert. --> wS2812 Richtig. Man kann einfach die geniale, kaum noch zu verbessernde WS2812-LightweightLib von Tim benutzen oder das Rad eckig machen. Beitrag "Lightweight WS2811/WS2812 Library"
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.