Включаем тактирование для порта светодиодов и таймера:
/* enable led port */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
/* enable tim4 */
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
Также настроим выводы порта на режим альтернативных фунций и настроим их на подключение к таймеру №4:
/* set led pins to af state */
LED_PORT->MODER |=
GPIO_MODER_MODER12_1 | GPIO_MODER_MODER13_1 |
GPIO_MODER_MODER14_1 | GPIO_MODER_MODER15_1;
/* select af block - tim3..5(af2 function) to led pins */
LED_PORT->AFR[1] |= (GPIO_AF2_TIM3_5 << GPIO_AFP12) | (GPIO_AF2_TIM3_5 << GPIO_AFP13) |
(GPIO_AF2_TIM3_5 << GPIO_AFP14) | (GPIO_AF2_TIM3_5 << GPIO_AFP15);
Также настроим таймер (настройки почти аналогичные примеру Регистры сравнения/захвата шим) за исключением значения для каналов:
/* tim4 setup presc */
TIM4->PSC = 16000 - 1;
/* tim4 setup preload reg */
TIM4->ARR = 1000;
/* tim4 load values to ccr1..4 */
TIM4->CCR1 = 500;
TIM4->CCR2 = 0;
TIM4->CCR3 = 0;
TIM4->CCR4 = 0;
/* tim4 setup cc chanel1..4 */
TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2;
TIM4->CCMR2 |= TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2;
/* tim4 setup cc chanel1..4 to corresponding output pin */
TIM4->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E;
Настроим ФАПЧ на значения умножителя 64 и делителя 32, т.е. коэффициент умножения 2, а так как предделитель для ФАПЧ по умолчанию равен 2, то получаем на выходе ту же частоту что и на входе:
/* pll configuration */
RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN);
RCC->PLLCFGR |= (64 << 6) | 32;
Включаем ФАПЧ:
/* pll enable */
RCC->CR |= RCC_CR_PLLON;
Также не забудем согласно ДШ задать количество циклов ожидания для максимальной частоты 64 МГц - 2 цикла ожидания:
/* enable flash wait to 2 ws */
FLASH->ACR |= FLASH_ACR_LATENCY_2WS;
Ждем стабилизацию частоты ФАПЧ и переключаемся на тактирование от него:
/* wait to ready pll and switch to it */
while ((RCC->CR && RCC_CR_PLLRDY) == 0);
RCC->CFGR &= ~RCC_CFGR_SWS;
RCC->CFGR |= RCC_CFGR_SWS_PLL;
Активируем прерывания от таймера и сам таймер №4:
/* tim4 enable update interrupt */
TIM4->DIER |= TIM_DIER_UIE;
/* tim4 enable clock */
TIM4->CR1 |= TIM_CR1_CEN;
Также активируем прерывания для этого таймера:
/* tim4 irq */
NVIC_EnableIRQ(TIM4_IRQn);