2025-09-03 2:37 AM - edited 2025-09-03 2:42 AM
I have the following code trying to turn 5 pixels of the LED strip to red. The setup I have is the LED strip is connected to PC6.
#include <stdint.h>
// STM32F103C8 is a medium density device, hence we use the xB header
#include <stm32f103xb.h>
#if !defined(__SOFT_FP__) && defined(__ARM_FP)
#warning \
"FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif
void enable_clock() {
RCC->CR |= RCC_CR_HSION;
while ((RCC->CR & RCC_CR_HSIRDY) == 0);
}
// @formatter:off
#define HI 6
#define LO 3
uint32_t buffer[] = {
LO, LO, LO, LO, LO, LO, LO, LO,
HI, HI, HI, HI, HI, HI, HI, HI,
LO, LO, LO, LO, LO, LO, LO, LO,
LO, LO, LO, LO, LO, LO, LO, LO,
HI, HI, HI, HI, HI, HI, HI, HI,
LO, LO, LO, LO, LO, LO, LO, LO,
LO, LO, LO, LO, LO, LO, LO, LO,
HI, HI, HI, HI, HI, HI, HI, HI,
LO, LO, LO, LO, LO, LO, LO, LO,
LO, LO, LO, LO, LO, LO, LO, LO,
HI, HI, HI, HI, HI, HI, HI, HI,
LO, LO, LO, LO, LO, LO, LO, LO,
LO, LO, LO, LO, LO, LO, LO, LO,
HI, HI, HI, HI, HI, HI, HI, HI,
LO, LO, LO, LO, LO, LO, LO, LO,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
// @formatter:on
void blink_dma_to_gpio() {
enable_clock();
// GPIO C configuration
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // Enable IO port C
GPIOC->CRL &= ~(GPIO_CRL_CNF6 | GPIO_CRL_MODE6); // GPIO C: Clear pin 6 configuration
GPIOC->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_MODE6; // GPIO C: Set pin 6 to alternate function push-pull 50MHz output
// TIM3 configuration
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // Enable TIM3
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // Enable alternate function
AFIO->MAPR |= AFIO_MAPR_TIM3_REMAP; // Full remap TIM3
TIM3->PSC = 1 - 1;
TIM3->ARR = 10 - 1;
TIM3->BDTR |= TIM_BDTR_MOE;
TIM3->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // PWM mode 1
TIM3->CCER |= TIM_CCER_CC1E; // Enable capture compare 1
TIM3->CCMR2 |= TIM_CCMR2_OC3M_0; // Active on match
TIM3->CCER |= TIM_CCER_CC3E; // Enable capture compare 3
TIM3->DIER |= TIM_DIER_CC3DE; // Enable DMA1 request
// DMA1 configuration
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // Enable DMA1
DMA1_Channel2->CPAR = (uint32_t) &TIM3->CCR1;
DMA1_Channel2->CMAR = (uint32_t) &buffer;
DMA1_Channel2->CNDTR = 168;
DMA1_Channel2->CCR = DMA_CCR_MSIZE_1 // 32 bit memory
| DMA_CCR_PSIZE_1 // 32 bit peripheral
| DMA_CCR_MINC // Increment memory
| DMA_CCR_CIRC // Circular memory
| DMA_CCR_DIR // Memory to peripheral
| DMA_CCR_HTIE // Half transfer interrupt
| DMA_CCR_TCIE // Transfer complete interrupt
;
// Enable peripherals
DMA1_Channel2->CCR |= DMA_CCR_EN;
TIM3->CR1 |= TIM_CR1_CEN;
}
int main() {
blink_dma_to_gpio();
for (;;);
}
I already had the output hooked up to an oscilloscope and the output waves look correct. However, when I run this code, nothing changes on the LED strip. I just want to ask if there is something wrong with my code here, or could there be any potential hardware issues I did not think of.
Solved! Go to Solution.
2025-09-03 3:51 AM
Thank you for the comments, I checked again and I had the configuration for the GPIO wrong. I configured it to be open-drain while it should be push-pull instead. Changing to push-pull makes the edges cleaner and the LEDs now have the expected colors.
2025-09-03 2:44 AM
Please show your schematic.
@Beartama wrote:I already had the output hooked up to an oscilloscope and the output waves look correct.
Please share scope screenshots - someone may be able to spot something...
If your scope has a screenshot facility, please use it - this will be far better than trying to photograph the screen!
@Beartama wrote:when I run this code, nothing changes on the LED strip.
Do you see changes on the scope?
Do you have a known-good, working implementation to compare against; eg, Arduino?
2025-09-03 2:56 AM
Please show your schematic.
RM STATUS LIGHT CTRL LV is the LED strip.
Please share scope screenshots - someone may be able to spot something...
The high spike is for bit 1 to be sent to the LED, and the low spike is for bit 0. The high spike is high for 0.75us and the low spike is high for 0.375us, these are according to the spec of WS2812B.
Do you have a known-good, working implementation to compare against; eg, Arduino?
No
2025-09-03 3:08 AM - edited 2025-09-03 3:17 AM
That doesn't show how the STM32 is actually connected to the LED strip, nor the LED power supply.
@Beartama wrote:Please share scope screenshots - someone may be able to spot something...
you missed:
@Andrew Neil wrote:
If your scope has a screenshot facility, please use it - this will be far better than trying to photograph the screen!
Your scope does have that facility:
Anyhow, that waveform looks terrible: there should be clear pulses with clean edges, and consistent height; eg,
from: https://www.pjrc.com/2017/10/
PS:
From the LED datasheet:
You haven't shown what your VDD is for the LEDs but, if it's 3.3V, that would mean that the minimum 'High' voltage is 2.3V.
In your scope trace, the short spikes aren't even reaching 2V, and even the tall ones are marginal.
2025-09-03 3:51 AM
Thank you for the comments, I checked again and I had the configuration for the GPIO wrong. I configured it to be open-drain while it should be push-pull instead. Changing to push-pull makes the edges cleaner and the LEDs now have the expected colors.