STM32F100, a PWM on Timer 17

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

ruslanpopov
Posts: 35
Joined: Sun Aug 19, 2012 9:36 pm

STM32F100, a PWM on Timer 17

Post by ruslanpopov »

Hello,

I try to generate PWM with Timer 17 but can't to find how to do this. Demo sources and mcuconf.h uses Timer 8 maximum.

What is about TIM17?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: STM32F100, a PWM on Timer 17

Post by Giovanni »

TIM17 is not supported currently, it could be added but it only supports a single comparator so you could only use channel 0.

Giovanni
ruslanpopov
Posts: 35
Joined: Sun Aug 19, 2012 9:36 pm

Re: STM32F100, a PWM on Timer 17

Post by ruslanpopov »

Do I understand right that currently it isn't possible to make PWM with TIM17?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: STM32F100, a PWM on Timer 17

Post by Giovanni »

Using the PWM driver currently not, you could enable the timer at registers level and do it anyway, not particularly hard to do.

Giovanni
ruslanpopov
Posts: 35
Joined: Sun Aug 19, 2012 9:36 pm

Re: STM32F100, a PWM on Timer 17

Post by ruslanpopov »

Please, add support of TIM15, TIM16 and TIM17 for STM32F100.
ruslanpopov
Posts: 35
Joined: Sun Aug 19, 2012 9:36 pm

Re: STM32F100, a PWM on Timer 17

Post by ruslanpopov »

The following code runs PWM on TIM17:

Code: Select all

    //Enable clock for the timer
        RCC->APB2ENR |= RCC_APB2ENR_TIM17EN;
        // Enable ARR preloading
        TIM17->CR1 |= TIM_CR1_ARPE;
        // Enable CCR1 preloading
        TIM17->CCMR1 |= TIM_CCMR1_OC2PE;
        // PWM mode 1: OC1M = 110
        TIM17->CCMR1 |= (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1);
        // Prescaler keeps zero to allow control PWM frequency
        TIM17->PSC = 0;
        // PWM Frequency 36 kHz
        TIM17->ARR = 667 - 1;
        // Duty cycle: 33%
        TIM17->CCR1 = 222;
        // Uncomment to change polarity
        //TIM2->CCER |= TIM_CCER_CC2P;
        // Enable Capture/Compare output 1, ie PB9
        TIM17->CCER |= TIM_CCER_CC1E;
        // Main Output enable
        TIM17->BDTR |= TIM_BDTR_MOE;
        // Start timer
        TIM17->CR1 |= TIM_CR1_CEN;
ruslanpopov
Posts: 35
Joined: Sun Aug 19, 2012 9:36 pm

Re: STM32F100, a PWM on Timer 17

Post by ruslanpopov »

Image

Top three graphics are captured when I have used ChibiOS' PWM on TIM4 channel 3. Looks so strange.

Bottom graphic is captured when I use register's PWM, described above.

The last one is looked as normal PWM. How to get the same with ChibiOS PWM module?

Source code: https://github.com/RaD/armka_demos/blob/97b2d331d92ae2552d04ab2f0d9c51c9718c3f62/apps/ir-tester/main.c
ruslanpopov
Posts: 35
Joined: Sun Aug 19, 2012 9:36 pm

Re: STM32F100, a PWM on Timer 17

Post by ruslanpopov »

This night gave me an idea to check timer's registers after preparing PWM module. Results are following:

[*] TIM17/CH1 (registers way):

Code: Select all

TIM17->PSC = 0
TIM17->ARR = 24001
TIM17->CCR1 = 12000

[*] TIM4/CH4 (PWM module way):

Code: Select all

TIM4->PSC = 23999
TIM4->ARR = 99
TIM4->CCR1 = 0


That's the reason of my problem!

Btw, these timers share the same pin on a chip.

How to tune PWM module to have the values of TIM17 for TIM4?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: STM32F100, a PWM on Timer 17

Post by Giovanni »

The PWM driver works as intended here. The values in the registers come from the settings in the PWM configuration structure and I find unlikely you can have the CCR1 set to zero.

If you explain what you expect to get from the PWM and post your configuration structure I could help.

Giovanni
ruslanpopov
Posts: 35
Joined: Sun Aug 19, 2012 9:36 pm

Re: STM32F100, a PWM on Timer 17

Post by ruslanpopov »

Digging in sources have helped me to solve this problem.

Register way:

Code: Select all

//Enable clock for the timer
RCC->APB2ENR |= RCC_APB2ENR_TIM17EN;
// Enable ARR preloading
TIM17->CR1 |= TIM_CR1_ARPE;
// Enable CCR1 preloading
TIM17->CCMR1 |= TIM_CCMR1_OC2PE;
// PWM mode 1: OC1M = 110
TIM17->CCMR1 |= (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1);
// Prescaler keeps zero to allow control PWM frequency
TIM17->PSC = 0;
// PWM Frequency
TIM17->ARR = (uint16_t) (STM32_SYSCLK / PWM_FREQ);
// Duty cycle
TIM17->CCR1 = (uint16_t) (TIM17->ARR * PWM_WIDTH);
// Uncomment to change polarity
//TIM2->CCER |= TIM_CCER_CC2P;
// Enable Capture/Compare output 1, ie PB9
TIM17->CCER |= TIM_CCER_CC1E;
// Main Output enable
TIM17->BDTR |= TIM_BDTR_MOE;
// Start timer
TIM17->CR1 |= TIM_CR1_CEN;

chprintf((BaseSequentialStream *) &SD1, "TIM17->PSC = %d\n", TIM17->PSC);
chprintf((BaseSequentialStream *) &SD1, "TIM17->ARR = %d\n", TIM17->ARR);
chprintf((BaseSequentialStream *) &SD1, "TIM17->CCR1 = %d\n", TIM17->CCR1);


Its output is:

Code: Select all

TIM17->PSC = 0
TIM17->ARR = 24000
TIM17->CCR1 = 12000


PWM Module way:

Code: Select all

static PWMConfig pwmcfg = {
    STM32_SYSCLK,                           /* PWM clock frequency, PSC register. */
    (uint16_t) (STM32_SYSCLK / PWM_FREQ) + 1,   /* Initial PWM period. ARR register*/
    NULL,                                   /* Periodic callback pointer. */
    {                                       /* Channel configuration set dynamically below, */
        {PWM_OUTPUT_DISABLED, NULL},
        {PWM_OUTPUT_DISABLED, NULL},
        {PWM_OUTPUT_DISABLED, NULL},
        {PWM_OUTPUT_DISABLED, NULL}
    },
    0                                       /* TIM CR2 register initialization data. */
#if STM32_PWM_USE_ADVANCED
    ,0                                      /* TIM BDTR register initialization data. */
#endif
};

PWMChannelConfig chcfg = { PWM_OUTPUT_ACTIVE_HIGH, NULL };
pwmcfg.channels[PWM4_CHANNEL] = chcfg;
pwmStart(&PWMD4, &pwmcfg);
pwmEnableChannel(&PWMD4, PWM4_CHANNEL,
    PWM_PERCENTAGE_TO_WIDTH(&PWMD4, PWM_WIDTH * 10000));

chprintf((BaseSequentialStream *) &SD1, "TIM4->PSC = %d\n", TIM4->PSC);
chprintf((BaseSequentialStream *) &SD1, "TIM4->ARR = %d\n", TIM4->ARR);
chprintf((BaseSequentialStream *) &SD1, "TIM4->CCR4 = %d\n", TIM4->CCR4);


Its output is:

Code: Select all

TIM4->PSC = 0
TIM4->ARR = 24000
TIM4->CCR4 = 12000


My "oscilloscope" shows the following in appropriate order:
Image

I would appreciate an explanation when I should increment ARR value? I talk about this:

Code: Select all

(uint16_t) (STM32_SYSCLK / PWM_FREQ) + 1


How to get the same result using prescaler value lower that STM32_SYSCLK?
Post Reply