Hallo zusammen, ich versuche einen LED-Streifen mit WS2812 LEDs zum Laufen zu bekommen. Dabei nutze ich die light_ws2812_ARM Bibliothek. Ich bin den Anweisungen in der README-Datei gefolgt und die Anpassungen auf dem Mikrocontroller haben soweit funktioniert. Allerdings leuchtet der Streifen nicht in der von mir gewünschten Farbe. Durch verschiedene Einstellungen an F_CPU und anschließende Messung mit einem Oszi vermute ich, dass dies mit den wait states zusammenhängt. Wie kann ich die wait states auf 0 setzen? Folgendes hat nicht funktioniert: 1.) Set FLASH access time in clocks Chip_FMC_SetFLASHAccess( FLASHTIM_50MHZ_CPU ) 2.) Place the function that writes the data into the main RAM region __RAMFUNC(RAM) void ws2812_sendarray(uint8_t *ledarray,int length); Oder hatte jemand schon ein ähnliches Problem?
:
Beitrag #6270957 wurde von einem Moderator gelöscht.
Marvin0807 schrieb: > Wie kann ich die wait states auf 0 setzen? Bei der STM32L0 und STM32F0 Serie ist das standardmäßig bereits deaktiviert. SET_BIT(FLASH->ACR, FLASH_ACR_LATENCY); // 1 Wait state CLEAR_BIT(FLASH->ACR, FLASH_ACR_LATENCY); // 0 Wait states Der Flash Speicher fällt aber aus, denn du mit mehr als 24 MHz ohne Wait-State taktest. Welchen Mikrocontroller verwendest du denn?
Ich hatte mal einen M0, bei dem mußte man die Waitstates hochsetzen, falls er mit 48 statt 32 MHz betrieben hat. Stand ab Revision 1 dann auch im Handbuch. Meistens sind die CPUs aber schnell genug. Daher vermute ich, dass der Programmierer nicht genau weiss, was er tut.
PittyJ schrieb: > Meistens sind die CPUs aber schnell genug. Klar, aber die Wait States sind für die Peripherals, das Zeugs was an der superschnellen CPU hängt.
MaWin schrieb: > aber die Wait States sind für die Peripherals Nein, die sind für den Flash. Das ist der langsamste Part überhaupt.
Jörg W. schrieb: > Nein, die sind für den Flash. Der in der CPU wohnt, der direkt an die ALU getackert ist??? Ist der Speicher ist extern über einen BUS aun die CPU gekoppelt!
Doch, z.B. beim STM32F0 oder auch G0 muss man ab > 24MHz 1ws und > 48MHz 2ws konfigurieren. Mit dem CubeMX oder dem alten Excel-Makro Tool ("AN4055 Clock configuration tool for STM32F0xx microcontrollers") wird auch schon der Startup-Code entsprechend generiert, so dass die WS korrekt konfiguriert werden.
:
Bearbeitet durch User
auweia schrieb im Beitrag #6270957: > Wer nicht voellig geistig behindert ist, schaut einfach im > Referenzmanual des Controllers im Abschnitt "Flash" nach. Wenn ich es gefunden hätte, würde ich hier nicht fragen.. Ich verwende den LPC11C24.
In einem deiner vielen Threads zu der WS2812 Ansteuerung hatte ich schonmal geschrieben das der LPC die auch gut per SPI treiben kann, da entfällt die taktabhängige Zyklenzählerei.
Beitrag #6271709 wurde von einem Moderator gelöscht.
Marvin S. schrieb: > Wenn ich es gefunden hätte, würde ich hier nicht fragen.. Guckst Du UM10398 Kapitel 3.12: http://www.keil.com/dd/docs/datashts/nxp/lpc11xx/lpc111x_lpc11cxx_um.pdf Du setzt die Waitstates natürlich, BEVOR Du die Frequenz mittels PLL raufsetzt. Was auch noch schiefgehen kann, ist die PLL umzukonfigurieren, während der Chip schon von der PLL läuft. Oder die PLL konfigurieren und aufzuschalten, ohne zu warten, bis sie überhaupt eingeschwungen ist.
Ich habe beim LPC11C24 die Erfahrung gemacht, dass es auch eine Rolle spielt wie und wo der Code der delay() Routine am Ende im Flash steht. Das hat sicher mit den Caching-Stategien zu tun die es das auch gibt. Bei mir äußerte sich das so, dass die Zeiten des Delays sich bei manchmal nach Codeänderungen völlig verändert haben obwohl an der Routine selbst nichts gemacht wurde. Ich habe mir dann so geholfen:
1 | // Microsecond delay loop-
|
2 | void DelayuS(uint32_t uS) |
3 | {
|
4 | uint32_t CyclestoLoops; |
5 | |
6 | CyclestoLoops = SystemCoreClock<<1; |
7 | if (CyclestoLoops >= 2000000) |
8 | {
|
9 | CyclestoLoops /= 1000000; |
10 | CyclestoLoops *= uS; |
11 | }
|
12 | else
|
13 | {
|
14 | CyclestoLoops *= uS; |
15 | CyclestoLoops /= 1000000; |
16 | }
|
17 | |
18 | if (CyclestoLoops <= 100) |
19 | return; |
20 | |
21 | CyclestoLoops -= 320; // cycle count for entry/exit should be measured |
22 | CyclestoLoops /= 8; // |
23 | |
24 | if (!CyclestoLoops) |
25 | return; |
26 | |
27 | // Delay loop for Cortex M3 thumb2
|
28 | // das align 4 ist extrem wichtig, sonst
|
29 | // sind Unterschiede im faktor 2 möglich jenachdem
|
30 | // wie der Code erzeugt wird
|
31 | __asm volatile |
32 | (
|
33 | // Load loop count to register
|
34 | " mov r3, %[loops]\n" |
35 | " .align 4\n" |
36 | "loop: sub r3,#1 \n" |
37 | " bne loop \n\n" |
38 | |
39 | : // No output registers |
40 | : [loops] "r" (CyclestoLoops) // Input registers |
41 | : "r3" // clobbered registers |
42 | );
|
43 | }
|
Entscheidend war das .align 4\n im Assemblercode. Das schaffte dann Reproduzierbare Ergebnisse.
Grundsätzlich sollte man - wie schon oben erwähnt - grundsätzlich überdenken ob man die ws2812 nicht per SPI ansteuern möchte. Ich finde dieses Bitbanging ist eine absolute Krücke die es eigentlich zu vermeiden gilt.
temp schrieb: > if (CyclestoLoops <= 100) > return; > > CyclestoLoops -= 320; // cycle count for entry/exit should be measured Ich würde die 100 oben durch 320 ersetzen. Falls 100 < CyclestoLoops < 320, wird das sonst wegen wrap-around eine sehr lange Delay-Loop.
Beitrag #6271989 wurde von einem Moderator gelöscht.
Beitrag #6272120 wurde von einem Moderator gelöscht.
Nop schrieb: > Guckst Du UM10398 Kapitel 3.12: > http://www.keil.com/dd/docs/datashts/nxp/lpc11xx/lpc111x_lpc11cxx_um.pdf Genau das habe ich ja mit der unter 1.) aufgeführten Anweisung gemacht. Nur dass dies der originale Aufruf war, der die Frequenz auf 50MHz setzt. So wie du auch geschrieben hast, wird zuerst die eben beschriebene Anweisung ausgeführt und dann mittels PLL auf 4* 12MHz erhöht. An die Lösung mit SPI habe ich mich schon letztes Mal gemacht, nachdem ich davon gehört habe. Da hatte ich ein wenig Probleme durch eine zu große Lücke zwischen der Übertragung von aufeinanderfolgenden Bytes. Das ganze beruht auf dem Beispiel von LPCOpen. Nichtsdestotrotz hätte ich gerne die Bibliothek hier zum Laufen gebracht.. Die Anwedung dieser Delay-Funktion verstehe ich nicht ganz um ehrlich zu sein. Aber vielen Dank für das Bereitstellen des Quellcodes!
Beitrag #6272254 wurde von einem Moderator gelöscht.
Marvin S. schrieb: > Da hatte ich ein wenig Probleme durch eine zu > große Lücke zwischen der Übertragung von aufeinanderfolgenden Bytes. Das > ganze beruht auf dem Beispiel von LPCOpen. LPCOpen baut da eventuell zuviel Sicherheit ein, oder arbeitet mit Interrupts? Ein WS Bit muss in 3 SPI Bits gesendet werden, macht 24 Bit. Die kann man in 2x12 Bit @ 2,4 MHz verschicken. Beim Senden Pollen ob das Statusregister ready sagt, dann einfach die Daten ins DR schreiben.
Nop schrieb: >> if (CyclestoLoops <= 100) >> return; >> >> CyclestoLoops -= 320; // cycle count for entry/exit should be measured > > Ich würde die 100 oben durch 320 ersetzen. Falls 100 < CyclestoLoops < > 320, wird das sonst wegen wrap-around eine sehr lange Delay-Loop. Da gebe ich dir völlig Recht.
Markus M. schrieb: > Grundsätzlich sollte man - wie schon oben erwähnt - grundsätzlich > überdenken ob man die ws2812 nicht per SPI ansteuern möchte. > > Ich finde dieses Bitbanging ist eine absolute Krücke die es eigentlich > zu vermeiden gilt. Oder nimm ein Bluepill Board und schieb die Daten per DMA raus, das hab ich auch schon mal für 8 Kanäle gleichzeitig gemacht.
Beitrag #6272793 wurde von einem Moderator gelöscht.
Beitrag #6272803 wurde von einem Moderator gelöscht.
Beitrag #6272807 wurde von einem Moderator gelöscht.
Beitrag #6272910 wurde von einem Moderator gelöscht.
Johannes S. schrieb: > LPCOpen baut da eventuell zuviel Sicherheit ein, oder arbeitet mit > Interrupts? Es kann zwischen einem Polling- und einem Interrupt-Modus gewählt werden. So wie ich das sehe wird also in dem von mir gewählten Modus nicht mit Interrupts gearbeitet. Das Verhalten wurde auch schon hier beschrieben https://community.nxp.com/thread/487020. Ich werde nun so wie du beschrieben hast versuchen direkt in das DR zu schreiben. Zu dem anderen hätte ich aber trotzdem noch eine Frage. Die entscheidenende Funktion in der ws_light Bibliothek sieht wie folgt aus:
1 | void ws2812_sendarray(uint8_t *data,int datlen) |
2 | {
|
3 | uint32_t maskhi = ws2812_mask_set; |
4 | uint32_t masklo = ws2812_mask_clr; |
5 | volatile uint32_t *set = ws2812_port_set; |
6 | volatile uint32_t *clr = ws2812_port_clr; |
7 | uint32_t i; |
8 | uint32_t curbyte; |
9 | |
10 | while (datlen--) { |
11 | curbyte=*data++; |
12 | |
13 | asm volatile( |
14 | " lsl %[dat],#24 \n\t" |
15 | " movs %[ctr],#8 \n\t" |
16 | "ilop%=: \n\t" |
17 | " lsl %[dat], #1 \n\t" |
18 | " str %[maskhi], [%[set]] \n\t" |
19 | #if (w1&1)
|
20 | ws2812_DEL1
|
21 | #endif
|
22 | #if (w1&2)
|
23 | ws2812_DEL2
|
24 | #endif
|
25 | #if (w1&4)
|
26 | ws2812_DEL4
|
27 | #endif
|
28 | #if (w1&8)
|
29 | ws2812_DEL8
|
30 | #endif
|
31 | #if (w1&16)
|
32 | ws2812_DEL16
|
33 | #endif
|
34 | " bcs one%= \n\t" |
35 | " str %[masklo], [%[clr]] \n\t" |
36 | "one%=: \n\t" |
37 | #if (w2&1)
|
38 | ws2812_DEL1
|
39 | #endif
|
40 | #if (w2&2)
|
41 | ws2812_DEL2
|
42 | #endif
|
43 | #if (w2&4)
|
44 | ws2812_DEL4
|
45 | #endif
|
46 | #if (w2&8)
|
47 | ws2812_DEL8
|
48 | #endif
|
49 | #if (w2&16)
|
50 | ws2812_DEL16
|
51 | #endif
|
52 | " sub %[ctr], #1 \n\t" |
53 | " str %[masklo], [%[clr]] \n\t" |
54 | " beq end%= \n\t" |
55 | #if (w3&1)
|
56 | ws2812_DEL1
|
57 | #endif
|
58 | #if (w3&2)
|
59 | ws2812_DEL2
|
60 | #endif
|
61 | #if (w3&4)
|
62 | ws2812_DEL4
|
63 | #endif
|
64 | #if (w3&8)
|
65 | ws2812_DEL8
|
66 | #endif
|
67 | #if (w3&16)
|
68 | ws2812_DEL16
|
69 | #endif
|
70 | |
71 | " b ilop%= \n\t" |
72 | "end%=: \n\t" |
73 | : [ctr] "+r" (i) |
74 | : [dat] "r" (curbyte), [set] "r" (set), [clr] "r" (clr), [masklo] "r" (masklo), [maskhi] "r" (maskhi) |
75 | );
|
76 | }
|
77 | }
|
Wie hat der User temp sich jetzt mit der Delay-Funktion beholfen? Bei ihm scheint die Sache ja auf dem gleichen Controller zu laufen...
> Markus M. schrieb: > Oder nimm ein Bluepill Board und schieb die Daten per DMA raus, das hab > ich auch schon mal für 8 Kanäle gleichzeitig gemacht. Ich brauch den Controller aktuell wegen einer anderen Funktionalität, aber ich werde es im Hinterkopf behalten:)
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.