RGB led and STM32

In this tutorial we are going to interface RGB LED with STM32. Basically this is another application of PWM (Pulse Width Modulation) and should work with any microcontroller, that is capable of PWM.

I am using a Common Cathode RGB led i.e. the ground pin is common and we have to supply voltage to the other individual pins. A CC RGB led looks as picture below

The individual pins represent the following colors

  • 1 –> RED
  • 2 –> GROUND
  • 3 –> GREEN
  • 4 –> BLUE

I have connected them to STM32F446RE as:-

  • 1 –> PA8 (TIM1_CH-1)
  • 2 –> GROUND 
  • 3 –> PA9 (TIM1_CH-2)
  • 4 –> PA10 (TIM1_CH-3)

How To

Before going to the coding part, let’s see How these LEDs works. As we know that RGB stands for Red, Green and Blue and these LEDs can emit all these three colors at the same time. Basically each color have a range of intensity from 0 to 255 which depends on the voltage provided to the respective pin. We combine these intensities (0 to 255) of these three colors to produce 16 million (256x256x256) different colors.

In order to vary the voltage across these pins, we need to use PWM and for that I am using TIMER 1 of my STM32F446RE. TIMER is running at 90 MHz and we need to use prescalar and ARR to vary the duty cycle. Duty cycle describes the amount of time, the signal is in HIGH state as a percentage of total time, it takes to complete one cycle. As I mentioned, the intensity value ranges from 0 to 255, so I am going configure the timer in such a way that 100% duty cycle is equivalent to 255. So let’s start

You guys are familiar with the initial setup of cubemx so I am going to jump to TIMER CONFIGURATION section directly

As you can see above that the APB1 timer clock (TIMER1 clock) is running at 90 MHz.

Now as I mentioned, I need to configure timer in such a way that the 100% duty cycle is equivalent to 255 and so I am going to divide the clock by 255 i.e. (90 MHz / 255 = 352941). Next I want the ARR value to be set such that 100% of ARR is 255 again because this is what the timer is going to count up to and as the intensity vary from 0 to 255, it’s better to setup it as 255. So let’s further divide the clock by 255 i.e. (352941/255 = 1384). This (1384) is the value that we need to enter in the prescalar register.

Some Insight into the CODE

First I am going to write a function to feed the values in the different channels which are connected to the different pins of the RGB led.

void set_rgb (uint8_t red, uint8_t green, uint8_t blue)
	htim1.Instance->CCR1 = red;
	htim1.Instance->CCR2 = green;
	htim1.Instance->CCR3 = blue;

Next you need to start the respective channels in the main function and than feed in the desired values

int main(void)



  HAL_TIM_PWM_Start (&htim1, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start (&htim1, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start (&htim1, TIM_CHANNEL_3);

  while (1)

	  set_rgb (255,0,0);   // red only
	  HAL_Delay (1000);

	  set_rgb (0,255,0);   // green only
	  HAL_Delay (1000);

	  set_rgb (0,0,255);  // blue only
	  HAL_Delay (1000);

	  set_rgb (255,255,0);

	  set_rgb (0,255,255);
	  HAL_Delay (1000);

	  set_rgb (255,0,255);
	  HAL_Delay (1000);

	  set_rgb (192,192,192);
	  HAL_Delay (1000);





Check out the VIDEO Below

Notify of
Oldest Most Voted
Inline Feedbacks
View all comments