



#define GPIOAEN (1U<<0)
#define TIM2EN (1U<<0)
#define CR1_CEN (1U<<0)
void tim2_pa0_pa1_pwm_init(void)
{
/**********GPIO Configuration**********/
/*Enable clock access to GPIOA*/
RCC->AHB1ENR |= GPIOAEN;
/*Set PA0 and PA1 mode to alternate function mode*/
/*PA0*/
GPIOA->MODER &= ~(1U<<0);
GPIOA->MODER |= (1U<<1);
/*PA1*/
GPIOA->MODER &= ~(1U<<2);
GPIOA->MODER |= (1U<<3);
/*Set alternate function type to TIM2 (AF01)*/
/*PA0*/
GPIOA->AFR[0] |= (1U<<0);
GPIOA->AFR[0] &= ~(1U<<1);
GPIOA->AFR[0] &= ~(1U<<2);
GPIOA->AFR[0] &= ~(1U<<3);
/*PA1*/
GPIOA->AFR[0] |= (1U<<4);
GPIOA->AFR[0] &= ~(1U<<5);
GPIOA->AFR[0] &= ~(1U<<6);
GPIOA->AFR[0] &= ~(1U<<7);
/**********TIM2 Configuration**********/
/*Enable clock access to TIM2*/
RCC->APB1ENR |= TIM2EN;
/*Set timer Prescaler*/
TIM2->PSC = 10; // 16 000 000 no divider = 16 000 000 (the default clock is 16mhz in stm32))
/*Set auto-reload value*/
TIM2->ARR = 1000 - 1; // 16 000 000 / 1000 = 16kHz
/*Reset the timer count*/
TIM2->CNT = 0;
/*Set PA1 (ch2) and PA0 (ch1) to 110 : PWM mode 1*/
/*ch1*/
TIM2->CCMR1 &= ~(1U<<4);
TIM2->CCMR1 |= (1U<<5);
TIM2->CCMR1 |= (1U<<6);
/*ch2*/
TIM2->CCMR1 &= ~(1U<<12);
TIM2->CCMR1 |= (1U<<13);
TIM2->CCMR1 |= (1U<<14);
/*Enable ch1 and ch2*/
/*ch1*/
TIM2->CCER |= (1U<<0);
/*ch2*/
TIM2->CCER |= (1U<<4);
/*Enable timer*/
TIM2->CR1 |= CR1_CEN;
}
// Function to set PWM duty cycle for TIM2 channels on PA0 and PA1
void tim2_pa0_pa1_pwm_set_dutycycle(uint8_t ch, uint32_t dutycycle)
{
/*Select channel*/
switch(ch)
{
/*Set dutycycle*/
case 1:
TIM2->CCR1 = dutycycle;
break;
case 2:
TIM2->CCR2 = dutycycle;
break;
default:
break;
}
}
int main(void)
{
/*Init pwm at pa0 and pa1*/
tim2_pa0_pa1_pwm_init();
tim2_pa0_pa1_pwm_set_dutycycle(1, 100);
tim2_pa0_pa1_pwm_set_dutycycle(2, 1);
while(1)
{
}
}
result:

