I am trying to control a WS2812 LED with STM32F103. The LED is a digital RGB LED also known as Neopixel. They are controlled by sending 24 bits of color data per LED to the first LED's data pin.
The STM32 is 3.3V and the LED is 5V. To be able to control it I put a transistor in between like this:
This solves the level shifting problem, but causes another one: now the data signal for the LED is inverted. When the STM32 pin is low, LED data is high and vice-versa. I USE Timer PWM and DMA to control the LED. I pass the buffer with color value bits to DMA like that:
HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_1, (uint32_t *)&BUF_DMA, ARRAY_LEN);
This produces a nice PWM signal on MC pin. Here is how a bunch of zeros at 800KHz look like: But the transistor inverts the signal making it useless:
I need to pass the inverted signal from the MC pin somehow. So that the transistor will UN-INVERT it back. Is there a way to invert PWM/pin signal completely? So that MC pin is always HIGH by default, so that LED data line stays LOW?
A few notes:
- I use PB5 and PB6 to control two separate lines of WS2812
- The PCBs are already printed and all the components are SMD, so hardware workarounds are barely possible.
- I already tried to remove the transistor completely and use MC pin to pull 5V line to ground internally in open drain mode, but PB5 is not 5V tolerant. No luck here.