Добавим вектор обработчика таймера №4:
0, /*!%29 TIM3 */ tim4_irq_hanlder, /*!%30 TIM4 */ 0, /*!%31 I2C1 Event */И сам обработчик прерывания:
/* timer4 irq handler */void tim4_irq_hanlder(void) { if (TIM4->SR & TIM_SR_UIF) { static int counter; char divide; static char direct; counter++;Каждую итерацию таймера для удобства отображения мы расширим до 4-х циклов:
if (counter > 3) { counter = 0;Для стабильности мы переключаемся на внутренний высокоскоростной осциллятор:
/* switch to HSI and wait for stable*/ RCC->CFGR &= ~RCC_CFGR_SW; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);Выключаем ФАПЧ для перенастройки:
/* disable PLL and wait for off */ RCC->CR &= ~RCC_CR_PLLON; while ((RCC->CR & RCC_CR_PLLRDY) == 1);Вносим в локальную переменную значение делителя и сбрасываем его значение:
/* setup PLL, enable and wait to ready */ divide = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLM;Вычисляем значение нового и загружаем это значение обратно в регистр настроек ФАПЧ:
/* calculate new divide value */ if (direct) if (divide > 8) divide -= 4; else direct = 0; else if (divide < 32) divide += 4; else direct = 1; RCC->PLLCFGR |= divide;Включаем ФАПЧ и ждем его стабилизации
RCC->CR |= RCC_CR_PLLON; while ((RCC->CR & RCC_CR_PLLRDY) == 0);Переключаемся на ФАПЧ, ждем окончания переключения и выходим из прерывания:
/* select PLL for system clock and wait to select */ RCC->CFGR &= ~RCC_CFGR_SW; RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS_PLL) == 0); } /* clear status bit */ TIM4->SR &= ~TIM_SR_UIF; }}