284 lines
5.9 KiB
C
284 lines
5.9 KiB
C
|
/*
|
||
|
* 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
|