Skip to main content
Graduate II
January 17, 2024
Question

How to start PWM using the registers.

  • January 17, 2024
  • 6 replies
  • 5945 views

What am I doing wrong?

Why is PWM don't work on the STM32F767ZI?

 

RCC->APB2ENR |= 1; // Enable clock for TIM1 on APB2.
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN; // Enable clock for GPIOE port on AHB1.

GPIOE->MODER &= ~(1 << 18); // Clear/reset PE9 mode.
GPIOE->MODER |= (2 << 18); // Set PE9 mode.

// Enable alternative function AFIO. Connect TIM to the pin accordingly!
GPIOE->AFR[1] &= ~(0xF << 4); // Clear bits 4 to 7.
GPIOE->AFR[1] |= (1 << 4); // Set bit 9.

TIM1->PSC = 216 - 1; // Set prescaler for > 10KHz.
TIM1->ARR = 100 - 1; // Set auto-reload value for 1Hz.
TIM1->CCR1 = 50; // Set initial comparison value (PWM duty cycle).
TIM1->CNT = 0; // Reset the current count.

TIM1->CCMR1 |= (0x6UL << TIM_CCMR1_OC1M_Pos ); // Set PWM mode 1.
TIM1->CCMR1 |= (0x68 << 0);

TIM1->CCER = 1; // Enable PWM Channel 1.
TIM1->CR1 = 1; // Enable timer.

 

 

Q1.pngQ2.pngQ3.png

    This topic has been closed for replies.

    6 replies

    Super User
    January 17, 2024

    On advanced timers, you need to set the MOE bit in the BDTR register to enable output.

    DK.7Author
    Graduate II
    January 17, 2024

    Thank you for the response! I have set the necessary values in the register TIM1->BDTR->MOI.
    But still, nothing is working!
    The same settings work when using the HAL library! However, I'm not able to get it to work with the registers!

    Q4.png

    Super User
    January 17, 2024

    Not real sure. Is this a custom board or ST design? Might not be hooked up how you think. Recheck schematic.

    Set up PE9 as a GPIO output and toggle it. to verify it connects to what you think it does.

    You can also examine GPIOx->IDR register when PWM is active. For a 50% PWM, it should be toggling between 0 and 1 with equal probability.

    What does "PWM don't work" mean here specifically? How are you verifying that it's active/inactive?

    DK.7Author
    Graduate II
    January 18, 2024

    I checked it with a digital analyzer and an oscilloscope, see photo! The result is no signal with the same behavior on both devices.

    I have a regular NUCLEO-F767ZI board that works perfectly if I create a project using the HAL library. However, when I try to implement a similar project using only registers, nothing works!1.png

    Super User
    January 18, 2024

    So why dont you just use the working HAL , then look in debug , what the start_pwm_chxx  or whatever is doing - then you see, what you have to write to the TIM registers.

    Or (as i did sometimes) just look in SFR view, what registers are set to some values, then set it to this values just by write to registers, without any HAL then. And you have it running...

    Graduate II
    January 18, 2024

    I have down this for a F767 Nucleo some years ago, I'm pretty sure it worked, just a little bit clock enable and GPIO HAL stuff:

     

     

     

    /* TIM11 Initialization Function
     * 		PWM output for testing,
     *		GPIO PF7
     */
    
    /* "manual" register settings, safer than Cube HAL stuff */
    void MX_TIM11_Init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStruct = { 0 };
    
    	/* Peripheral clock enable */
    	__HAL_RCC_TIM11_CLK_ENABLE();
    
    	TIM11->CR1	= 0;
    	TIM11->DIER 	= 0;
    	TIM11->PSC	= 7;
    	TIM11->ARR	= 29;			/* auto-reload: PWM frequency */
    	TIM11->CCR1	= TIM11->ARR >> 1;	/* 50% duty cycle */
    	TIM11->EGR	= 0;
    	TIM11->CCMR1	= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
    	TIM11->CCER	= TIM_CCER_CC1E | TIM_CCER_CC1P;
    	TIM11->OR	= 0;
    
    	TIM11->CNT 	= 0;
    	TIM11->SR	= 0;
    
    	/* Configure GPIO pin : Timer 11 channel output compare PWM PF7 */
    	/* TIM11 GPIO Configuration PF7 ------> TIM11_CH1 */
    	GPIO_InitStruct.Pin 		= GPIO_PIN_7;
    	GPIO_InitStruct.Mode 		= GPIO_MODE_AF_PP;
    	GPIO_InitStruct.Pull 		= GPIO_NOPULL;
    	GPIO_InitStruct.Speed 		= GPIO_SPEED_FREQ_MEDIUM;//GPIO_SPEED_FREQ_HIGH;
    	GPIO_InitStruct.Alternate 	= GPIO_AF3_TIM11;
    	HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
    
    	/* TIM11 enable */
    	TIM11->CR1 = TIM_CR1_ARPE | TIM_CR1_CEN;
    }

     

     

     

    Graduate II
    January 18, 2024

    When I compare my code to yours:

    - TIM: you have not set the ARPE bit in CR1, not sure though if that is really needed, check RM

    RM:

    You must enable the corresponding preload register by setting the
    OCxPE bit in the TIMx_CCMRx register, and eventually the auto-reload preload register (in
    upcounting or center-aligned modes) by setting the ARPE bit in the TIMx_CR1 register.

    IDK if that applies to your stuff.

    - clock enables and GPIO:  that's where I am lazy and use the HAL stuff. Maybe just for checking, you use HAL stuff for that, then see if your PWM starts doing something.

    DK.7Author
    Graduate II
    January 18, 2024

    Thank you, I will verify everything and I'll reply to you!

    Visitor II
    January 18, 2024

    I wrote an article on ARM Timers using registers, NOT HAL, that might be of some help.

     

    https://jaxcoder.com/Post/Index?guid=456f6a89-1a93-4a72-bab9-4cf3a9e7f9b6 

     

     

    Super User
    January 18, 2024

    Read out and check/post TIM and GPIO registers' content. That's always the first step in debugging software on mcu, as it works out of registers, not out of the source code.

    JW