// 6C ukázka Toggle režimu Compare kanálů // generuje fázově posunuté průběhy (500Hz) na PC6,7,8,9 a fázi posledního kanálu postupně mění #include "stm32f0xx.h" #include "stm32f0xx_ll_bus.h" #include "stm32f0xx_ll_rcc.h" #include "stm32f0xx_ll_gpio.h" #include "stm32f0xx_ll_utils.h" #include "stm32f0xx_ll_tim.h" void init_clock(void); void init_gpio(void); void init_tim3(void); int main(void){ init_clock(); // 48MHz (HSE bypass) init_gpio(); // LED na PC9 init_tim3(); while (1){ // není co dělat... } } // rutina přerušení timeru void TIM3_IRQHandler(void){ static uint16_t counter; static uint16_t phase=0; LL_TIM_ClearFlag_UPDATE(TIM3); // nezapomeneme smazat vlajku counter++; // odpočítáváme 100ms if(counter>=100){ // každých 100ms změníme fázi na kanálu 4 counter=0; // počítáme znovu od začátku phase=phase+10; // zpozdi kanál 4 o dalších 10us if(phase>999){phase=0;} // víc jak 1000 nemá smysl (strop časovače) LL_TIM_OC_SetCompareCH4(TIM3,phase); // nastav fázi na CH4 } } // konfigurace timeru void init_tim3(void){ LL_TIM_InitTypeDef tim; LL_TIM_OC_InitTypeDef oc; // inicializujeme struktury (abychom je nemuseli vyplňovat celé) LL_TIM_StructInit(&tim); LL_TIM_OC_StructInit(&oc); // povolíme clock pro TIM3 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3); tim.Prescaler = 47; // 1MHz do timeru (clock čipu 48MHz) tim.Autoreload = 999; // přetečení každou ms (1kHz) LL_TIM_Init(TIM3,&tim); // část nastavení shodná pro všechny kanály oc.OCPolarity = LL_TIM_OCPOLARITY_HIGH; // tímto lze kanál invertovat oc.OCState = LL_TIM_OCSTATE_ENABLE; // přidělujeme timeru ovládání výstupu oc.OCMode = LL_TIM_OCMODE_TOGGLE; // přepnout výstup při Compare události oc.CompareValue = 99; // 100us po přetečení timeru LL_TIM_OC_Init(TIM3,LL_TIM_CHANNEL_CH1,&oc); oc.CompareValue = 199; // 200us po přetečení timeru LL_TIM_OC_Init(TIM3,LL_TIM_CHANNEL_CH2,&oc); oc.CompareValue = 299; // 300us po přetečení timeru LL_TIM_OC_Init(TIM3,LL_TIM_CHANNEL_CH3,&oc); oc.CompareValue = 399; // 400us po přetečení timeru LL_TIM_OC_Init(TIM3,LL_TIM_CHANNEL_CH4,&oc); LL_TIM_EnableIT_UPDATE(TIM3); // povolím přerušení od přetečení NVIC_SetPriority(TIM3_IRQn,3); // nízká priorita NVIC_EnableIRQ(TIM3_IRQn); // a čítač spustíme LL_TIM_EnableCounter(TIM3); } // výstupy TIM3 na PC6,7,8,9 void init_gpio(void){ LL_GPIO_InitTypeDef gp; LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC); gp.Pin = LL_GPIO_PIN_6 | LL_GPIO_PIN_7 | LL_GPIO_PIN_8 | LL_GPIO_PIN_9; gp.Mode = LL_GPIO_MODE_ALTERNATE; // Piny budou patřit timeru gp.Alternate = LL_GPIO_AF_0; // na STM32F051 je pro GPIOC všechno na AF0 (víc možností není) gp.OutputType = LL_GPIO_OUTPUT_PUSHPULL; // push-pull výstup (výchozí varianta) gp.Speed = LL_GPIO_SPEED_HIGH; // vysoká rychlost přeběhu (nehraje teď roli) LL_GPIO_Init(GPIOC,&gp); } // 48MHz z externího 8MHz signálu void init_clock(void){ LL_UTILS_PLLInitTypeDef pll; LL_UTILS_ClkInitTypeDef clk; pll.Prediv = LL_RCC_PREDIV_DIV_2; // 8MHz / 2 = 4MHz pll.PLLMul = LL_RCC_PLL_MUL_12; // 4MHz * 12 = 48MHz clk.AHBCLKDivider = LL_RCC_SYSCLK_DIV_1; // APB i AHB bez předděličky clk.APB1CLKDivider = LL_RCC_APB1_DIV_1; // voláme konfiguraci clocku LL_PLL_ConfigSystemClock_HSE(8000000,LL_UTILS_HSEBYPASS_ON,&pll,&clk); // aktualizuj proměnnou SystemCoreClock SystemCoreClockUpdate(); }