/* * tim2.c * * Created on: Dec 30, 2023 * Author: Francesco Gritti * * This file contains implementation of booth timer 2 input capture and PWM * generation features. only one of the two features can be enabled by * defining the macros "tim2_pwm" or "tim2_ic". * * GPIOs connected to the input/output channels of the timer should be * defined in main.h and they are initialized into the TIM2_init function */ #include "main.h" #include "mcu.h" #ifdef tim2_adc_timebase void TIM2_init (void) { RCC_TIM2_CLK_ENABLE(); TIM2->CR1 = 0x0000; TIM2->CR2 = (0b010 << TIM_CR2_MMS_Pos); TIM2->DIER = 0x0000; // disable all interrupt requests TIM2->PSC = TIM2_PSC; TIM2->ARR = TIM2_PERIOD; TIM2->CR1 |= TIM_CR1_CEN; } #endif #ifdef tim2_pwm void TIM2_pwm_config_ch1 (TIM_OC_ACTIVE_STATE_enum activeState, u16 value) { TIM2->CCMR1 = (TIM_FORCE_INACTIVE << TIM_CCMR1_OC1M_Pos) | TIM_CCMR1_OC1PE; if (activeState == TIM_OC_ACTIVE_HIGH) TIM_PWM_SET_CH1_POLARITY_ACTIVE_HIGH (TIM2); else TIM_PWM_SET_CH1_POLARITY_ACTIVE_LOW (TIM2); TIM2->CCR1 = value; TIM_CH1_FORCE_INACTIVE(TIM2); TIM_CH1_ENABLE(TIM2); } void TIM2_pwm_config_ch2 (TIM_OC_ACTIVE_STATE_enum activeState, u16 value) { TIM2->CCMR1 = (TIM_FORCE_INACTIVE << TIM_CCMR1_OC2M_Pos) | TIM_CCMR1_OC2PE; if (activeState == TIM_OC_ACTIVE_HIGH) TIM_PWM_SET_CH2_POLARITY_ACTIVE_HIGH (TIM2); else TIM_PWM_SET_CH2_POLARITY_ACTIVE_LOW (TIM2); TIM2->CCR2 = value; TIM_CH2_FORCE_INACTIVE(TIM2); TIM_CH2_ENABLE(TIM2); } void TIM2_pwm_config_ch3 (TIM_OC_ACTIVE_STATE_enum activeState, u16 value) { TIM2->CCMR2 = (TIM_FORCE_INACTIVE << TIM_CCMR2_OC3M_Pos) | TIM_CCMR2_OC3PE; if (activeState == TIM_OC_ACTIVE_HIGH) TIM_PWM_SET_CH3_POLARITY_ACTIVE_HIGH (TIM2); else TIM_PWM_SET_CH3_POLARITY_ACTIVE_LOW (TIM2); TIM2->CCR3 = value; TIM_CH3_ENABLE(TIM2); } void TIM2_pwm_config_ch4 (TIM_OC_ACTIVE_STATE_enum activeState, u16 value) { TIM2->CCMR2 = (TIM_FORCE_INACTIVE << TIM_CCMR2_OC4M_Pos) | TIM_CCMR2_OC4PE; if (activeState == TIM_OC_ACTIVE_HIGH) TIM_PWM_SET_CH4_POLARITY_ACTIVE_HIGH (TIM2); else TIM_PWM_SET_CH4_POLARITY_ACTIVE_LOW (TIM2); TIM2->CCR4 = value; TIM_CH4_ENABLE(TIM2); } void TIM2_pwm_init (void) { RCC_TIM2_CLK_ENABLE (); TIM2->CR1 = 0x0000; TIM2->CR2 = 0x0000; TIM2->SMCR = 0x0000; TIM2->DIER = 0x0000; // disable all channels TIM2->CCER = 0x0000; // force CH1 and CH2 inactive, enable compare PRELOAD TIM2->CCMR1 = 0x0000; TIM2->CCMR2 = 0x0000; // reset counter TIM2->CNT = 0x0000; //set PRESCALER TIM2->PSC = TIM2_PSC; // set PERIOD TIM2->ARR = TIM2_PERIOD; // reset all PWM periods TIM2->CCR1 = 0x0000; TIM2->CCR2 = 0x0000; TIM2->CCR3 = 0x0000; TIM2->CCR4 = 0x0000; TIM_COUNTER_ENABLE (TIM2); } /*GPIO_AF_PP (TIM2_PWM_CH1); GPIO_AF_PP (TIM2_PWM_CH2); GPIO_AF_PP (TIM2_PWM_CH3); GPIO_AF_PP (TIM2_PWM_CH4); GPIO_SET_AFRL (TIM2_PWM_CH1, GPIO_AF_TIM2); GPIO_SET_AFRL (TIM2_PWM_CH2, GPIO_AF_TIM2); GPIO_SET_AFRL (TIM2_PWM_CH3, GPIO_AF_TIM2); GPIO_SET_AFRL (TIM2_PWM_CH4, GPIO_AF_TIM2);*/ #elif defined(tim2_ic) void TIM2_init(void) { RCC_TIM2_CLK_ENABLE(); RCC_GPIOA_CLK_ENABLE(); /* =============== configure GPIO ================*/ GPIO_AF_PP (TIM2_IN_CH2); GPIO_SET_AFRL (TIM2_IN_CH2, 0x02); /* ====== configure timer capture channels ======*/ // configure channel 2 as input capture with filter 3 TIM2->CCMR1 = (3 << TIM_CCMR1_IC2F_Pos) | (0b01 << TIM_CCMR1_CC2S_Pos); // capture on falling edge only, enable channel TIM2->CCER = TIM_CCER_CC2P | TIM_CCER_CC2E; /* Configure base timer */ // enable interrupt on timer update and on channel2 input capture TIM2->DIER = TIM_DIER_UIE | TIM_DIER_CC2IE; TIM2->PSC = TIM2_PSC; // 54; TIM2->ARR = TIM2_PERIOD; // 65535; // request UEV event only on underflow/overflow and enable timer TIM2->CR1 = TIM_CR1_URS | TIM_CR1_CEN; // set highest priority since the handler is a non blocking function NVIC_SetPriority(TIM2_IRQn, 0); NVIC_EnableIRQ(TIM2_IRQn); } __attribute__ ((weak)) void TIM2_IRQHandler (void) { // clear IT flag } #endif