LED Brightness Control Using PWM

[JUST FOR MY FUTURE USE]

[i explained in my own words for myself so i can see this in future, so dont see my submission since it wont be clear and neat. Just wanna keep a place to store these. so dont mind me] 

Solving Approach:

 

How do you plan to solve it?

TIM2 -> PWM for LED

TIM4 -> Delay

I will use PWM to change the brightness of LED. 

Lets initialise PWM first. I will be using timer 2 for this. We can check the alternate function map table and we can see TIM2_CH1 in a GPIO port. So this is where LED is connected. I am choosing PA5 as PWM pin.


First ,  i provide clock access to PA5, then i set mode to alternate function mode using MODER register. then i will use AFR register to set which AF line to use. Configuration for GPIO is done. 

Now lets configure PWM Timer.  
First lets provide clock access to timer 2, Then set the prescale value and auto reload value using PSC and ARR registers.

Peripheral frequency = 16MHz

If we use Prescaler as 16, We tone it down to 1MHz. Then we can set resolution of PWM Using ARR. This indicates number of steps for a change in brightness in this case. So Lets keep 10000 as resolution. This means, 10000 times new brightness will be either increased or decreased. So ARR is 10000. Lets make the Count register 0. Lets make the PWM Mode as Mode 1.Lets enable the channel and timer. Channel can be enabled using CCER register. Timer can be enabled using CR register.

So in main function, we call this function. 
Now we need delay of 2s and 1s. so we use another timer. i will choose timer 4 for this task. Lets provide clock access to this timer as well. then inside a infinite loop, we start our task. 

Lets first disable the timer 4 for now. We will set prescaler and ARR in this time. We need to prescale to 1MHz. then for rising action we need to increase brightness from 0 to 100% within 2 seconds. we put ARR as 200. 

Main reason to do this is, we create a for loop from 0 to end of resolution which is 10000. so each iteration, we increase brightness of led by 1 using CCR register, then we give 200us delay. so after 10000 steps , with each step of 200us delay, we get 2seconds and brightness of led would have become max. 

Now we need to drop the brightness to 0 in 1s. so we configure same timer 4 accordingly. ARR is kept 100 now. so 100us for each step. each step brightness is decreased. so after 10000 steps, with each of 100us delay, we get 1s. led is fully dim now. This continues forever.

 

Code

#include "stm32f4xx.h"

#define GPIOAEN   (1U<<0)
#define TIM2EN    (1U<<0)
#define TIM4EN    (1U<<2)

#define SR_UIF    (1U<<0)

/* ================= PWM INIT (TIM2 → PA5) ================= */
void pwm_tim2_init(void)
{
    /* Enable clocks */
    RCC->AHB1ENR |= GPIOAEN;
    RCC->APB1ENR |= TIM2EN;

    /* PA5 → Alternate function */
    GPIOA->MODER &= ~(3U<<10);
    GPIOA->MODER |=  (2U<<10);

    /* AF1 → TIM2_CH1 */
    GPIOA->AFR[0] |= (1U<<20);

    /* Timer config */
    TIM2->PSC = 16 - 1;        // 1 MHz timer clock (1 µs tick)
    TIM2->ARR = 10000 - 1;     // 10000 steps (PWM resolution)

    TIM2->CCR1 = 0;

    /* PWM mode 1 */
    TIM2->CCMR1 |= (6U << 4);

    /* Enable channel */
    TIM2->CCER |= (1U << 0);

    /* Start timer */
    TIM2->CR1 |= (1U << 0);
}

/* ================= MAIN ================= */
int main(void)
{
    pwm_tim2_init();

    /* Enable TIM4 clock */
    RCC->APB1ENR |= TIM4EN;

    while(1)
    {
        /* ================= RISE (2 sec) ================= */
        TIM4->CR1 &= ~(1U<<0);   // stop

        TIM4->PSC = 15;          // 16 MHz → 1 MHz (1 µs per tick)
        TIM4->ARR = 200 - 1;     // 200 µs delay

        TIM4->CNT = 0;
        TIM4->CR1 |= (1U<<0);    // start

        for(int i = 0; i <= 10000; i++)
        {
            TIM2->CCR1 = i;

            while(!(TIM4->SR & SR_UIF)); // wait overflow
            TIM4->SR &= ~SR_UIF;         // clear flag
        }

        /* ================= FALL (1 sec) ================= */
        TIM4->CR1 &= ~(1U<<0);

        TIM4->PSC = 15;
        TIM4->ARR = 100 - 1;     // 100 µs delay

        TIM4->CNT = 0;
        TIM4->CR1 |= (1U<<0);

        for(int i = 10000; i >= 0; i--)
        {
            TIM2->CCR1 = i;

            while(!(TIM4->SR & SR_UIF));
            TIM4->SR &= ~SR_UIF;
        }
    }
}


 

Output

 

Video

Add video of output (know more)

 

 

 

 

 

Photo of Output

Add a photo of your hardware showing the output.

 

 


 

Upvote
Downvote

Submit Your Solution

Note: Once submitted, your solution goes public, helping others learn from your approach!