// 6D ukázka PWM režimu Compare kanálů // generuje PWM s frekvencí 50Hz a šířkou pulzu 1-2ms (signál pro servo na PC6) #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 pwm=1500, direction=0; LL_TIM_ClearFlag_UPDATE(TIM3); // nezapomeneme smazat vlajku if(direction){ // pokud krokujeme nahoru if(pwm<1990){pwm=pwm+10;} // pokud je ještě kam krokovat zvětši PWM else{direction=0;} // jinak přehoď směr krokování } else{ if(pwm>1010){pwm=pwm-10;} // zmenšuj PWM pokud je ještě kam else{direction=1;} // jinak změň směr krokování } LL_TIM_OC_SetCompareCH1(TIM3,pwm); // nastav nové PWM } // 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 = 19999; // f=50Hz (T=20ms) LL_TIM_Init(TIM3,&tim); // použijeme jen kanál CH1 oc.OCPolarity = LL_TIM_OCPOLARITY_HIGH; // běžná polarita oc.OCState = LL_TIM_OCSTATE_ENABLE; // přidělujeme timeru ovládání výstupu oc.OCMode = LL_TIM_OCMODE_PWM1; // režim PWM1 oc.CompareValue = 1499; // počáteční šířka pulzu 1.5ms LL_TIM_OC_Init(TIM3,LL_TIM_CHANNEL_CH1,&oc); // aplikujeme nastavení na CH1 // nutné zapnout Preload - jinak hrozí vznik glitchů při změně PWM LL_TIM_OC_EnablePreload(TIM3,LL_TIM_CHANNEL_CH1); // ! 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ýstup TIM3 na PC6 void init_gpio(void){ LL_GPIO_InitTypeDef gp; LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC); gp.Pin = LL_GPIO_PIN_6 ; gp.Mode = LL_GPIO_MODE_ALTERNATE; // Pin bude 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(); }