Hi All,
my problem here is BLUE.PILL→DMA→SPI ; I have done it successfully with CubeIDE (HAL) , but now I have to import this to STM32duino , and I am afraid of this
Probably some of you did the trick , or are able to give me some important advices , so thank you !
USB↔BLUE.PILL→DMA→SPI→WS2812B
Re: USB↔BLUE.PILL→DMA→SPI→WS2812B
Great. Could you share your code?
Here an example how to convert a cube example:
viewtopic.php?t=110
Here an example how to convert a cube example:
viewtopic.php?t=110
-
- Posts: 39
- Joined: Wed Jul 12, 2023 11:09 am
Re: USB↔BLUE.PILL→DMA→SPI→WS2812B
Hi fpiSTM , thanks !
I will try
here is my code about SPI→WS2812B
I use 3 SPI bits to make 1 RGB bit ; the duration of 1 RGB bit must be ~1.26us , so the duration of each SPI bit = 0.42us
For the STM32F103 @72MHz , I have set the SPI prescaler at /32 , so the duration of 1 SPI bit is 32/72 = 0.444us ; it works fine
RGB bit 0 : |‾|_._ ; RGB bit 1 : |‾.‾|_ ; both = 1.26us
the clock must be set this way :
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
I will try
here is my code about SPI→WS2812B
I use 3 SPI bits to make 1 RGB bit ; the duration of 1 RGB bit must be ~1.26us , so the duration of each SPI bit = 0.42us
For the STM32F103 @72MHz , I have set the SPI prescaler at /32 , so the duration of 1 SPI bit is 32/72 = 0.444us ; it works fine
RGB bit 0 : |‾|_._ ; RGB bit 1 : |‾.‾|_ ; both = 1.26us
the clock must be set this way :
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
Code: Select all
/* ws.h */
// some colors
const uint8_t ws_black[3] = { 0, 0, 0 };
const uint8_t ws_green[3] = { 25, 0, 0 };
const uint8_t ws_red[3] = { 0, 25, 0 };
const uint8_t ws_blue[3] = { 0, 0, 25 };
const uint8_t ws_white[3] = { 25, 25, 25 };
const uint8_t ws_purple[3] = { 0, 25, 25 };
const uint8_t ws_yell[3] = { 25, 25, 0 };
const uint8_t ws_turq[3] = { 25, 0, 25 };
#define ws833dim (8 * 3 * 3)
uint8_t ws833[ws833dim];
uint8_t ws83[8][3];
// some colors for 8 RGBchips
void ws_83() {
for (int c = 0; c < 3; c++) {
ws83[0][c] = ws_green[c];
ws83[1][c] = ws_red[c];
ws83[2][c] = ws_blue[c];
ws83[3][c] = ws_white[c];
ws83[4][c] = ws_black[c];
ws83[5][c] = ws_yell[c];
ws83[6][c] = ws_turq[c];
ws83[7][c] = ws_purple[c];
}
};
// 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
// |‾|_._|‾|_._|‾|_._|‾|_._|‾|_._|‾|_._|‾|_._|‾|_._ // 146 73 36 // all RGB bits = 0
// 128 64 32 16 8 4 2 1
// |‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_ // 219 109 182 // all RGB bits = 1
// each RGB bit needs 3 SPI bits to be sent , thus , each RGB byte needs 3 SPI bytes
// (they are 3 RGB bytes for each chip , so each chip needs 9 SPI bytes)
// convert RGB byte to 1st SPI byte
uint8_t ws_color_0(uint8_t c) {
uint8_t b = 0b10010010; // all RGB bits = 0
if (c & 128) b += 0b01000000; // RGB MSB = 1
if (c & 64) b += 0b00001000; // aso.
if (c & 32) b += 1;
return b;
};
// convert RGB byte to 2nd SPI byte
uint8_t ws_color_1(uint8_t c) {
uint8_t b = 0b01001001;
if (c & 16) b += 0b00100000;
if (c & 8) b += 0b00000100;
return b;
};
// convert RGB byte to 3rd and last SPI byte
uint8_t ws_color_2(uint8_t c) {
uint8_t b = 0b00100100;
if (c & 4) b += 0b10000000;
if (c & 2) b += 0b00010000;
if (c & 1) b += 0b00000010;
return b;
};
// make the whole area to be sent by DMA→SPI
void ws_833() {
uint8_t p = 0, w;
ws_83();
for (int ws = 0; ws < 8; ws++) { // 8 RGB chips in my case
for (int c = 0; c < 3; c++) { // 3 bytes for each RGB chip
w = ws83[ws][c];
ws833[p] = ws_color_0(w); // 1st SPI byte
p++;
ws833[p] = ws_color_1(w); // 2nd SPI byte
p++;
ws833[p] = ws_color_2(w); // 3rd SPI byte
p++; // at the end , p gives the total of SPI bytes
}
}
};
-
- Posts: 39
- Joined: Wed Jul 12, 2023 11:09 am
Re: USB↔BLUE.PILL→DMA→SPI→WS2812B
I made some tests with cubeMx and cubeIDE (fast compile and upload , easy debug) :
NSS , MISO and even SCK pins can be reused as GPIOs , or ADC inputs , but not for the timer peripherals (contrary to cubeMx)
still hoping for some help in order to make DMA→SPI→WS2812B
NSS , MISO and even SCK pins can be reused as GPIOs , or ADC inputs , but not for the timer peripherals (contrary to cubeMx)
still hoping for some help in order to make DMA→SPI→WS2812B
Re: USB↔BLUE.PILL→DMA→SPI→WS2812B
If you just want to get your LEDs to work, the Adafruit Neopixel library has worked for some people. The timing of the pulses it generates is not very precise, but should be good enough. A potential problem with it, depending on what else you need to do, is that it disables interrupts for the duration of entire pulse stream for all your LEDs, but for only 8 LEDs that is not too bad.
If this is a learning exercise, or you have some other reason to want to use DMA and SPI then show us how you tried to merge your working HAL code into a sketch (not just the code that sets up the SPI data).
If this is a learning exercise, or you have some other reason to want to use DMA and SPI then show us how you tried to merge your working HAL code into a sketch (not just the code that sets up the SPI data).
-
- Posts: 39
- Joined: Wed Jul 12, 2023 11:09 am
Re: USB↔BLUE.PILL→DMA→SPI→WS2812B
thank you ozcar
1) my project will light 8 RGB chips every 100ms ; the whole duration for one transmission is ~2us , so there is no problem to use a blocking little piece of code , but yes , I hate this way to do
2) SPI and DMA are , with GPIO , the simplest peripherals in a STM32 , so they are easy to program : I finally used LL , and got success ; it lacks 90% of the code used by HAL , but it works ok for me ; thus , I am no more interested to import HAL , but if someone want to do it , I will help if I can
1) my project will light 8 RGB chips every 100ms ; the whole duration for one transmission is ~2us , so there is no problem to use a blocking little piece of code , but yes , I hate this way to do
2) SPI and DMA are , with GPIO , the simplest peripherals in a STM32 , so they are easy to program : I finally used LL , and got success ; it lacks 90% of the code used by HAL , but it works ok for me ; thus , I am no more interested to import HAL , but if someone want to do it , I will help if I can
Re: USB↔BLUE.PILL→DMA→SPI→WS2812B
Where does the 2μs come from?trimarco232 wrote: Mon Jun 02, 2025 11:25 pm the whole duration for one transmission is ~2us , so there is no problem to use a blocking little piece of code
For 800kHz LEDs the nominal transfer time is 1.25μs. Of course, that is per bit, so for 8 RGB LEDs the Neopixel library would disable interrupts for around 8x24x1.25 = 240μs, plus maybe the "reset" time (I'm not sure if that library is smart enough to keep that out of the disabled time).
-
- Posts: 39
- Joined: Wed Jul 12, 2023 11:09 am
Re: USB↔BLUE.PILL→DMA→SPI→WS2812B
oops , right
Re: USB↔BLUE.PILL→DMA→SPI→WS2812B
Why what?
Why it takes that length of time to send data for 8 LEDs?
Why the code in question runs with interrupts disabled?
How SPI can be used instead?
BTW there are many old threads here where different ways of controlling such LEDs have been discussed.