Ich versuche, einige WS2812-LEDs anzusteuern, die ein (400 ns hoch + 800 ns niedrig) oder (800 ns hoch + 400 ns niedrig) Signal benötigen, um eine 0 oder eine 1 anzuzeigen.
Im Wesentlichen versuche ich also, ein Array von Daten zu nehmen und es direkt an einen GPIO mit etwa 2,5 MHz auszugeben. Ich habe den DMA noch nie zuvor verwendet, aber meines Wissens sollte er in der Lage sein, Daten direkt aus dem Speicher an einen GPIO auszugeben.
Kann jemand eine Anleitung geben, wie man den DMA dafür einrichtet, oder ob es bessere Möglichkeiten gibt, Daten auf einem GPIO mit einem konsistenten Takt auszugeben?
Sie sollten die Verwendung einer UART-, SPI- oder I2S-Schnittstelle in Betracht ziehen und ein Byte verwenden, um die Wellenform für ein Bit zu generieren. Der wichtige Punkt ist, dass solche Schnittstellen einen FIFO-Puffer haben, sodass die Aktivitäten der CPU nicht genau synchron mit dem Ausgangssignal sein müssen.
Ein Schüler von mir hat das erfolgreich auf einem LPC1114 gemacht.
Vielleicht können Sie DMA verwenden, um die serielle Schnittstelle zu speisen, aber Sie müssten die Daten auf ein Byte pro Bit "aufblähen".
Das Datenblatt bestätigt, dass das Umschalten von GPIO bei 2,5 MHz möglich ist
Schnelles I/O-Handling ermöglicht I/O-Toggeln bis zu 36 MHz
DMA-Schreibvorgänge auf GPIO sind möglich (Blick auf das Blockdiagramm des DMA-Abschnitts). Wenn Sie GPIO direkt in GPIO_data-Register schreiben könnten.
DMA kann aufgrund Ihrer Einschränkung im Arbeitszyklus für logisch niedrig und logisch hoch nicht verwendet werden. Ich würde vorschlagen, die Codierung in C zu versuchen und die GPIOs direkt anzusteuern (wechseln Sie zu Asm oder Inline, falls von der Toolchain unterstützt), wenn eine Geschwindigkeit von 1/400 ns = 2,5 MHz erforderlich ist und zusätzliche Zeit dazwischen erforderlich ist.
Bearbeiten: Um DMA gemäß dem folgenden Kommentar zu verwenden, damit der Prozessor frei sein kann, beträgt das Tastverhältnis immer noch 66,66% und 33,33% gemäß der Anforderung in OP. Aber die einzige Sache ist, dass die Rate auf 2,5 MHz erhöht wird. Ich muss noch die DMA-Konfiguration erkunden, um die Möglichkeit zu prüfen.
1.Stellen Sie bei einem STM32 die Taktgeschwindigkeit auf 40/80/120 MHz ein und verwenden Sie den SPI mit Ausgabe auf MOSI. Verwenden Sie den SPI- und DMA-Kanal. Der Puls liegt bei 400us. Bei 80 MHz ist der SPI-Teiler 32.
Richten Sie den SPI so ein:
hdma_spi1_tx.Instance = DMA1_Channel3;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
3. Richten Sie den DMA-Port wie folgt ein:
DMA1_Channel3->CPAR = (uint32_t)&(SPI1->DR);
DMA1_Channel3->CMAR = (uint32_t) Pixel; // zum Senden an ws2812
DMA1_Kanal3->CCR |= DMA_CCR_DIR | DMA_CCR_MINC;
NVIC_SetPriority (DMA1_Channel2_3_IRQn, 0);
NVIC_EnableIRQ (DMA1_Channel2_3_IRQn);
4.Codieren Sie die Daten vor dem Senden korrekt. Bit 1 ist 110 und Bit 0: 100. Wenn Sie also 10 LEDs haben, sind WS2812 x 3 Bytes (24 Bits) x 3 Impulse = 90 Bytes
6. Senden Sie Daten an den WS2812 mit dem DMA HAL_SPI_Transmit_DMA (&hspi1, Pixel, numBytes);
7. Warten Sie 1,25 ms x LEDs, bevor Sie erneut senden
Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams
Benutzer323693