/* * tim3.c * * Created on: Dec 30, 2023 * Author: Francesco Gritti */ #include "main.h" #include "mcu.h" #include "gpio.h" #ifdef tim3_adc_timebase void TIM3_init (void) { RCC_TIM3_CLK_ENABLE(); TIM3->CR1 = 0x0000; TIM3->CR2 = (0b010 << TIM_CR2_MMS_Pos); TIM3->DIER = 0x0000; // disable all interrupt requests TIM3->PSC = 24-1; TIM3->ARR = 1000 -1; TIM3->CR1 |= TIM_CR1_CEN; } #endif #ifdef tim3_pwm void TIM3_pwm_config_ch1 (TIM_OC_ACTIVE_STATE_enum activeState, u16 value) { TIM3->CCMR1 = (TIM_FORCE_INACTIVE << TIM_CCMR1_OC1M_Pos) | TIM_CCMR1_OC1PE; if (activeState == TIM_OC_ACTIVE_HIGH) TIM_PWM_SET_CH1_POLARITY_ACTIVE_HIGH (TIM3); else TIM_PWM_SET_CH1_POLARITY_ACTIVE_LOW (TIM3); TIM3->CCR1 = value; TIM_CH1_FORCE_INACTIVE(TIM3); TIM_CH1_ENABLE(TIM3); } void TIM3_pwm_config_ch2 (TIM_OC_ACTIVE_STATE_enum activeState, u16 value) { TIM3->CCMR1 = (TIM_FORCE_INACTIVE << TIM_CCMR1_OC2M_Pos) | TIM_CCMR1_OC2PE; if (activeState == TIM_OC_ACTIVE_HIGH) TIM_PWM_SET_CH2_POLARITY_ACTIVE_HIGH (TIM3); else TIM_PWM_SET_CH2_POLARITY_ACTIVE_LOW (TIM3); TIM3->CCR2 = value; TIM_CH2_FORCE_INACTIVE(TIM3); TIM_CH2_ENABLE(TIM3); } void TIM3_pwm_config_ch3 (TIM_OC_ACTIVE_STATE_enum activeState, u16 value) { TIM3->CCMR2 = (TIM_FORCE_INACTIVE << TIM_CCMR2_OC3M_Pos) | TIM_CCMR2_OC3PE; if (activeState == TIM_OC_ACTIVE_HIGH) TIM_PWM_SET_CH3_POLARITY_ACTIVE_HIGH (TIM3); else TIM_PWM_SET_CH3_POLARITY_ACTIVE_LOW (TIM3); TIM3->CCR3 = value; TIM_CH3_ENABLE(TIM3); } void TIM3_pwm_config_ch4 (TIM_OC_ACTIVE_STATE_enum activeState, u16 value) { TIM3->CCMR2 = (TIM_FORCE_INACTIVE << TIM_CCMR2_OC4M_Pos) | TIM_CCMR2_OC4PE; if (activeState == TIM_OC_ACTIVE_HIGH) TIM_PWM_SET_CH4_POLARITY_ACTIVE_HIGH (TIM3); else TIM_PWM_SET_CH4_POLARITY_ACTIVE_LOW (TIM3); TIM3->CCR4 = value; TIM_CH4_ENABLE(TIM3); } void TIM3_pwm_init (void) { RCC_TIM3_CLK_ENABLE (); TIM3->CR1 = 0x0000; TIM3->CR2 = 0x0000; TIM3->SMCR = 0x0000; TIM3->DIER = 0x0000; // disable all channels TIM3->CCER = 0x0000; // enable ch3 and ch4, force them inactive TIM3->CCMR1 = 0x0000; TIM3->CCMR2 = 0x0000; // reset counter TIM3->CNT = 0x0000; //set PRESCALER TIM3->PSC = TIM3_PSC; // set PERIOD TIM3->ARR = TIM3_PERIOD; // reset all PWM periods TIM3->CCR1 = 0x0000; TIM3->CCR2 = 0x0000; TIM3->CCR3 = 0x0000; TIM3->CCR4 = 0x0000; TIM_COUNTER_ENABLE (TIM3); } #elif defined(tim3_ic) void TIM3_ic_config_ch1 (TIM_IC_ACTIVE_EDGE_enum activeState, u8 filterValue) { // disable channel TIM3->CCER &= ~TIM_CCER_CC1E; TIM3->CCMR1 = ((filterValue & 0x0f) << TIM_CCMR1_IC1F_Pos) | (0b01 << TIM_CCMR1_CC1S_Pos); // clear edge selection bit => default rising edge TIM3->CCER &= ~(TIM_CCER_CC1NP | TIM_CCER_CC1P); switch (activeState) { case TIM_IC_ACTIVE_RISING: break; case TIM_IC_ACTIVE_FALLING: TIM3->CCER |= TIM_CCER_CC1P; break; case TIM_IC_ACTIVE_BOTH: TIM3->CCER |= (TIM_CCER_CC1NP | TIM_CCER_CC1P); break; } // enable interrupt on channel compare TIM3->DIER |= TIM_DIER_CC1IE; // enable the channel TIM3->CCER |= TIM_CCER_CC1E; } void TIM3_ic_config_ch2 (TIM_IC_ACTIVE_EDGE_enum activeState, u8 filterValue) { // disable channel TIM3->CCER &= ~TIM_CCER_CC2E; TIM3->CCMR1 = ((filterValue & 0x0f) << TIM_CCMR1_IC2F_Pos) | (0b01 << TIM_CCMR1_CC2S_Pos); // clear edge selection bit => default rising edge TIM3->CCER &= ~(TIM_CCER_CC2NP | TIM_CCER_CC2P); switch (activeState) { case TIM_IC_ACTIVE_RISING: break; case TIM_IC_ACTIVE_FALLING: TIM3->CCER |= TIM_CCER_CC2P; break; case TIM_IC_ACTIVE_BOTH: TIM3->CCER |= (TIM_CCER_CC2NP | TIM_CCER_CC2P); break; } // enable interrupt on channel compare TIM3->DIER |= TIM_DIER_CC2IE; // enable the channel TIM3->CCER |= TIM_CCER_CC2E; } void TIM3_ic_config_ch3 (TIM_IC_ACTIVE_EDGE_enum activeState, u8 filterValue) { // disable channel TIM3->CCER &= ~TIM_CCER_CC3E; TIM3->CCMR2 = ((filterValue & 0x0f) << TIM_CCMR2_IC3F_Pos) | (0b01 << TIM_CCMR2_CC3S_Pos); // clear edge selection bit => default rising edge TIM3->CCER &= ~(TIM_CCER_CC3NP | TIM_CCER_CC3P); switch (activeState) { case TIM_IC_ACTIVE_RISING: break; case TIM_IC_ACTIVE_FALLING: TIM3->CCER |= TIM_CCER_CC3P; break; case TIM_IC_ACTIVE_BOTH: TIM3->CCER |= (TIM_CCER_CC3NP | TIM_CCER_CC3P); break; } // enable interrupt on channel compare TIM3->DIER |= TIM_DIER_CC3IE; // enable the channel TIM3->CCER |= TIM_CCER_CC3E; } void TIM3_ic_config_ch4 (TIM_IC_ACTIVE_EDGE_enum activeState, u8 filterValue) { // disable channel TIM3->CCER &= ~TIM_CCER_CC3E; TIM3->CCMR2 = ((filterValue & 0x0f) << TIM_CCMR2_IC4F_Pos) | (0b01 << TIM_CCMR2_CC4S_Pos); // clear edge selection bit => default rising edge TIM3->CCER &= ~(TIM_CCER_CC4NP | TIM_CCER_CC4P); switch (activeState) { case TIM_IC_ACTIVE_RISING: break; case TIM_IC_ACTIVE_FALLING: TIM3->CCER |= TIM_CCER_CC4P; break; case TIM_IC_ACTIVE_BOTH: TIM3->CCER |= (TIM_CCER_CC4NP | TIM_CCER_CC4P); break; } // enable interrupt on channel compare TIM3->DIER |= TIM_DIER_CC4IE; // enable the channel TIM3->CCER |= TIM_CCER_CC4E; } void TIM3_ic_init(void) { RCC_TIM3_CLK_ENABLE(); TIM3->CCMR1 = 0x00000000; TIM3->CCMR2 = 0x00000000; /* Configure base timer */ // enable interrupt on timer update TIM3->DIER = TIM_DIER_UIE; TIM3->PSC = TIM3_PSC; TIM3->ARR = TIM3_PERIOD; // request UEV event only on underflow/overflow and enable timer TIM3->CR1 = TIM_CR1_URS | TIM_CR1_CEN; // set highest priority since the handler is a non blocking function NVIC_SetPriority(TIM3_IRQn, 0); NVIC_EnableIRQ(TIM3_IRQn); } __attribute__ ((weak)) void TIM3_IRQHandler (void) { // clear IT flag if ((TIM3->SR & TIM_SR_CC1IF) != 0) TIM3->SR &= ~TIM_SR_CC1IF; if ((TIM3->SR & TIM_SR_CC2IF) != 0) TIM3->SR &= ~TIM_SR_CC2IF; if ((TIM3->SR & TIM_SR_CC3IF) != 0) TIM3->SR &= ~TIM_SR_CC3IF; if ((TIM3->SR & TIM_SR_CC4IF) != 0) TIM3->SR &= ~TIM_SR_CC4IF; if ((TIM3->SR & TIM_SR_UIF) != 0) TIM3->SR &= ~TIM_SR_UIF; } #endif