en.radzio.dxp.pl

Lesson 6. Pulse Width Modulation (PWM)
In lesson 5 we learn how to blink led with Compare unit of timer TIM3. Compare unit can be also used in pulse width modulation mode for brightness control of LED. Now, go to section number 13.3.9 of RM0041 document.

pulse width modulation
  Different PWM duty

Configuration of compare module are slighty different from previous example :

TIM3->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 |
              TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; // PWM mode on channel 3 & 4

Now, CCR3 and CCR4 registers holds PWM duty value. Write initial duty value to registers :

TIM3->CCR3 = 0;   // Start PWM duty for channel 3
TIM3->CCR4 = 500; // Start PWM duty for channel 4

Each time when timer reload new value we want to change current PWM duty in both channels. So in interrupt handler from TIM3 we well be change duty on both channels. On CH3 we increase duty by 1% each time, on CH4 we decrease duty by 1% each time :

void TIM3_IRQHandler(void)
{
if(TIM3->SR & TIM_SR_UIF)  // if UIF flag is set
  {
  TIM3->SR &= ~TIM_SR_UIF; // clear UIF flag
  TIM3->CCR3 += 5;         // increase ch3 duty
  if(TIM3->CCR3 == 500)    // if maximum
    TIM3->CCR3 = 0;        // set to zero
  TIM3->CCR4 -= 5;         // decrease ch4 duty
  if(TIM3->CCR4 == 0)      // if minimum
    TIM3->CCR4 = 500;      // set to maximum
}
}

Complete source code :

//=============================================================================
// STM32VLDISCOVERY tutorial
// Lesson 6. Pusle Width Modulation (PWM)
// Copyright : Radoslaw Kwiecien
// http://en.radzio.dxp.pl
// e-mail : radek(at)dxp.pl
//=============================================================================
#include "stm32f10x.h"
#include "antilib_gpio.h"
//=============================================================================
// Defines
//=============================================================================
#define LED_BLUE_GPIO GPIOC
#define LED_BLUE_PIN 8

#define LED_GREEN_GPIO GPIOC
#define LED_GREEN_PIN 9
//=============================================================================
// main function
//=============================================================================
int main(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;

#if (LED_BLUE_PIN > 7)
  LED_BLUE_GPIO->CRH = (LED_BLUE_GPIO->CRH & CONFMASKH(LED_BLUE_PIN)) |
    GPIOPINCONFH(LED_BLUE_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));
#else
  LED_BLUE_GPIO->CRL = (LED_BLUE_GPIO->CRL & CONFMASKL(LED_BLUE_PIN)) |
    GPIOPINCONFL(LED_BLUE_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));
#endif

#if (LED_GREEN_PIN > 7)
  LED_GREEN_GPIO->CRH = (LED_GREEN_GPIO->CRH & CONFMASKH(LED_GREEN_PIN)) |     GPIOPINCONFH(LED_GREEN_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));
#else
  LED_GREEN_GPIO->CRL = (LED_GREEN_GPIO->CRL & CONFMASKL(LED_GREEN_PIN)) |     GPIOPINCONFL(LED_GREEN_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));
#endif

AFIO->MAPR = AFIO_MAPR_TIM3_REMAP; // Full TIM3 remap

TIM3->PSC = 239; // Set prescaler to 24 000 (PSC + 1)
TIM3->ARR = 500; // Auto reload value 500

TIM3->CCR3 = 0;   // Start PWM duty for channel 3
TIM3->CCR4 = 500; // Start PWM duty for channel 4

TIM3->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 |
              TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; // PWM mode on channel 3 & 4

TIM3->CCER = TIM_CCER_CC4E | TIM_CCER_CC3E; // Enable compare on channel 3 & 4
TIM3->CR1  = TIM_CR1_CEN; // Enable timer

TIM3->DIER = TIM_DIER_UIE; // Enable update interrupt (timer level)
NVIC_EnableIRQ(TIM3_IRQn); // Enable interrupt from TIM3 (NVIC level)

while (1) {}
}
//=============================================================================
// TIM3 Interrupt Handler
//=============================================================================
void TIM3_IRQHandler(void)
{
if(TIM3->SR & TIM_SR_UIF) // if UIF flag is set
  {
  TIM3->SR &= ~TIM_SR_UIF;  // clear UIF flag
  TIM3->CCR3 += 5;          // increase ch3 duty
  if(TIM3->CCR3 == 500)     // if maximum
    TIM3->CCR3 = 0;         // set to zero
  TIM3->CCR4 -= 5;          // decrease ch4 duty
  if(TIM3->CCR4 == 0)       // if minimum
    TIM3->CCR4 = 500;       // set to maximum
}
}
//=============================================================================
// End of file
//=============================================================================

 

 
(c) Radosław Kwiecień