2024-04-17 08:01 AM
Hello! Recently I got into STM programming for my internship and I cannot figure out register level programming yet, I have this piece of code
```
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_APB1ENR_TIM2EN;
GPIOA->MODER |=GPIO_MODER_MODE5_1 | GPIO_MODER_MODE5_0;
TIM2->CCER|=TIM_CCER_CC1E;
TIM2->CR1 |=TIM_CR1_ARPE;
TIM2->CCMR1 |=TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_0|TIM_CCMR1_OC1PE;
TIM2->PSC=42; //trivial
TIM2->ARR=1000; //trivial values
TIM2->CCR1=250; //trivial
TIM2->EGR |=TIM_EGR_UG;
TIM2->CR1 |=TIM_CR1_CEN;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
```
Which in theory, to me, looks like it should work, however there are things I still do not fully understand, for example: Here I wanted to use Tim2 on channel 1 because I can use that on my PA5 pin which is LED2 on my Nucleo f401RE board, and I wanted to produce a PWM signal on it, however, it just doesn't display, if someone could provide some feedback or guidance it would be greatly appreciated.
Solved! Go to Solution.
2024-04-18 12:40 PM
This is the final code that worked, thank you for your help Jan
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER |= ( 0x2UL << GPIO_MODER_MODE5_Pos); //alternate mode
GPIOA->AFR[0]|= 0x000100000;//alternate function for port A 5
TIM2->PSC = 840 - 1; // Set prescaler
TIM2->ARR = 1000; // Set auto-reload
TIM2->CCMR1 |= ( 0x6UL << TIM_CCMR1_OC1M_Pos );
TIM2->CCMR1 |= TIM_CCMR1_OC1PE;
TIM2->CR1 |= TIM_CR1_ARPE|TIM_CR1_CEN|TIM_CR1_URS;
TIM2->CCER &= ~TIM_CCER_CC1P;
TIM2->CCER |= TIM_CCER_CC1E;
TIM2->EGR |= TIM_EGR_UG;
TIM2->DIER |= ( TIM_DIER_CC1IE | TIM_DIER_UIE );
TIM2->SR &= ~( TIM_SR_CC1IF | TIM_SR_UIF );
2024-04-17 11:26 AM
> GPIOA->MODER |=GPIO_MODER_MODE5_1 | GPIO_MODER_MODE5_0;
What does this do?
You may need to set TIMx_AFR[] too, see AF assignment table in the Datasheet.
> TIM2->CCMR1 |=TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_0|TIM_CCMR1_OC1PE;
What does this do?
JW
2024-04-17 11:32 AM
Doesn't
> GPIOA->MODER |=GPIO_MODER_MODE5_1 | GPIO_MODER_MODE5_0;
Set my pins mode to Alternate function? I am playing with Pin A 5 so... I figured id need to configure Mode5 to 10
TIM2->CCMR1 |=TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_0|TIM_CCMR1_OC1PE;
Sets my Timer's mode to PWM1, according to the data sheet pwm 1 is "110" in the OC bits, and OC1PE is for preloading the register but im not really sure what that is.
2024-04-17 06:54 PM
Updated the code to this, still doesnt work
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER |= ( 0x2UL << GPIO_MODER_MODE5_Pos); //alternate mode
GPIOA->AFR[0]|= 0x000000010;//alternate function for port A 5
TIM2->PSC = 840 - 1; // Set prescaler
TIM2->ARR = 1000; // Set auto-reload
TIM2->CCMR1 |= ( 0x6UL << TIM_CCMR1_OC1M_Pos );
TIM2->CCMR1 |= TIM_CCMR1_OC1PE;
TIM2->CR1 |= TIM_CR1_ARPE;
TIM2->CCER &= ~TIM_CCER_CC1P;
TIM2->CCER |= TIM_CCER_CC1E;
TIM2->CR1 |= TIM_CR1_URS;
TIM2->EGR |= TIM_EGR_UG;
TIM2->DIER |= ( TIM_DIER_CC1IE | TIM_DIER_UIE );
TIM2->SR &= ~( TIM_SR_CC1IF | TIM_SR_UIF );
2024-04-18 09:15 AM
> Doesn't
>> GPIOA->MODER |=GPIO_MODER_MODE5_1 | GPIO_MODER_MODE5_0;
> Set my pins mode to Alternate function? I am playing with Pin A 5 so... I figured id need to configure Mode5 to 10
Yes, but that code sets MODE5 to 0b11.
> TIM2->CCMR1 |=TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_0|TIM_CCMR1_OC1PE;
> Sets my Timer's mode to PWM1, according to the data sheet pwm 1 is "110" in the OC bits,
That sets mode to 0b011 (and sets the 1st bit twice).
Reading code - including one's own - is an equally important skill as writing it.
>and OC1PE is for
> preloading the register but im not really sure what that is.
If you set TIMx_CCR1 preloading, the value you write into TIMx_CCR1 does not get active immediately, but only after the next Update event.
> Updated the code to this, still doesnt work
> GPIOA->AFR[0]|= 0x000000010;//alternate function for port A 5
That's not value for PA5 but for PA1. There are 4 bits per pin in that register.
> TIM2->SR &= ~( TIM_SR_CC1IF | TIM_SR_UIF );
This is not the source of problem here, but generally, don't use RMW to clear TIMx_SR bits.
JW
2024-04-18 12:40 PM
This is the final code that worked, thank you for your help Jan
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER |= ( 0x2UL << GPIO_MODER_MODE5_Pos); //alternate mode
GPIOA->AFR[0]|= 0x000100000;//alternate function for port A 5
TIM2->PSC = 840 - 1; // Set prescaler
TIM2->ARR = 1000; // Set auto-reload
TIM2->CCMR1 |= ( 0x6UL << TIM_CCMR1_OC1M_Pos );
TIM2->CCMR1 |= TIM_CCMR1_OC1PE;
TIM2->CR1 |= TIM_CR1_ARPE|TIM_CR1_CEN|TIM_CR1_URS;
TIM2->CCER &= ~TIM_CCER_CC1P;
TIM2->CCER |= TIM_CCER_CC1E;
TIM2->EGR |= TIM_EGR_UG;
TIM2->DIER |= ( TIM_DIER_CC1IE | TIM_DIER_UIE );
TIM2->SR &= ~( TIM_SR_CC1IF | TIM_SR_UIF );