123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- #include "Timer.h"
- #include "stm32f1xx_ll_bus.h" // Pour l'activation des horloges
- #include "stm32f1xx_ll_tim.h" // Pour les timers
-
-
- /****************************************************************************
- * INTERRUPTIONS
- ***************************************************************************/
-
-
- // variable pointeur de fonction permettant de m�moriser le callback � appeler depuis
- // le handler d'IT
- void (*it_callback_TIM1)(void);
- void (*it_callback_TIM2)(void);
- void (*it_callback_TIM3)(void);
- void (*it_callback_TIM4)(void);
-
-
- void TIM1_UP_IRQHandler(void)
- {
- // rabaisser le flag d'IT
- LL_TIM_ClearFlag_UPDATE(TIM1);
- (*it_callback_TIM1)();
- }
-
- void TIM2_IRQHandler(void)
- {
- // rabaisser le flag d'IT
- LL_TIM_ClearFlag_UPDATE(TIM2);
- (*it_callback_TIM2)();
- }
-
- void TIM3_IRQHandler(void)
- {
- // rabaisser le flag d'IT
- LL_TIM_ClearFlag_UPDATE(TIM3);
- (*it_callback_TIM3)();
- }
-
- void TIM4_IRQHandler(void)
- {
- // rabaisser le flag d'IT
- LL_TIM_ClearFlag_UPDATE(TIM4);
- (*it_callback_TIM4)();
- }
-
-
- void Timer_IT_enable(TIM_TypeDef * timer)
- {
- LL_TIM_EnableIT_UPDATE(timer);
- }
-
-
- void Timer_IT_disable(TIM_TypeDef * timer)
- {
- LL_TIM_DisableIT_UPDATE(timer);
- }
-
-
- void Timer_IT_conf(TIM_TypeDef * timer, void (*it_callback) (void), int prio)
- {
- // affectation de la fonction
- if (timer == TIM1) it_callback_TIM1 = it_callback;
- else if (timer == TIM2) it_callback_TIM2 = it_callback;
- else if (timer == TIM3) it_callback_TIM3 = it_callback;
- else it_callback_TIM4 = it_callback;
-
-
- // Blocage IT (il faudra la debloquer voir fct suivante)
- LL_TIM_DisableIT_UPDATE(timer);
-
- // validation du canal NVIC
- IRQn_Type TIM_irq;
-
- if (timer == TIM1) TIM_irq = TIM1_UP_IRQn;
- else if (timer == TIM2) TIM_irq = TIM2_IRQn;
- else if (timer == TIM3) TIM_irq = TIM3_IRQn;
- else TIM_irq = TIM4_IRQn;
-
- NVIC_SetPriority(TIM_irq, prio);
- NVIC_EnableIRQ(TIM_irq);
-
-
- }
-
- /****************************************************************************
- * TIMER
- ***************************************************************************/
-
- void Timer_start(TIM_TypeDef * timer)
- {
- LL_TIM_EnableCounter(timer);
- }
-
- void Timer_stop(TIM_TypeDef * timer)
- {
- LL_TIM_DisableCounter(timer);
- }
-
-
- void Timer_conf(TIM_TypeDef * timer, int arr, int psc)
- {
- LL_TIM_InitTypeDef init_struct;
-
- // Validation horloge locale
- if (timer == TIM1) LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
- else if (timer == TIM2) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
- else if (timer == TIM3) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
- else LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4);
-
- // chargement structure Arr, Psc, Up Count
- init_struct.Autoreload = arr;
- init_struct.Prescaler = psc;
- init_struct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
- init_struct.CounterMode = LL_TIM_COUNTERMODE_UP;
- init_struct.RepetitionCounter = 0;
-
- LL_TIM_Init(timer,&init_struct);
-
- // Blocage interruptions
- Timer_IT_disable(timer);
-
- // Blocage Timer
- Timer_stop(timer);
- }
-
- /****************************************************************************
- * PWM INPUT
- ***************************************************************************/
-
- void Timer_pwmi_conf(TIM_TypeDef * TIMx, int channel)
- {
- // Periode à recuperer dans TIMx_CCR1, duty cycle dans TIMx_CCR2. Seul les 2 premiers channels peuvent être utilisés (cf 315).
-
- // Validation horloge locale
- if (TIMx == TIM1) LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
- else if (TIMx == TIM2) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
- else if (TIMx == TIM3) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
- else LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4);
-
-
- if (channel == 1) {
-
- TIMx->CCMR1 |= TIM_CCMR1_CC1S_0;
- TIMx->CCMR1 |= TIM_CCMR1_CC2S_1;
-
- // TIM_CCMR1_IC1F_0; Potentiellement utile, à voir plus tard
-
- // On met le channel principal en rising edge, le secondaire en falling edge
- TIMx->CCER &= ~TIM_CCER_CC1P;
- TIMx->CCER |= TIM_CCER_CC2P;
-
- TIMx->SMCR |= TIM_SMCR_TS_0 | TIM_SMCR_TS_2; //101
- TIMx->SMCR |= TIM_SMCR_SMS_2; //100
- }
-
- else {
- TIMx->CCMR1 |= TIM_CCMR1_CC1S_1;
- TIMx->CCMR1 |= TIM_CCMR1_CC2S_0;
-
- TIMx->CCER |= TIM_CCER_CC1P;
- TIMx->CCER &= ~TIM_CCER_CC2P;
-
- TIMx->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; //110
- TIMx->SMCR |= TIM_SMCR_SMS_2; //100
- }
-
- // On met les prescalers à 0, on veut compter chaque transition
- TIMx -> CCMR1 &= ~TIM_CCMR1_IC1PSC;
- TIMx -> CCMR1 &= ~TIM_CCMR1_IC2PSC;
-
- TIMx -> CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E;
-
- // TIMx -> DIER |= TIM_DIER_CC1IE; gestion des interrupts, probablement pas utile
- // TIM_DIER_CC1DE_Pos; Probablement pas utile
- }
-
- int Timer_pwmi_getPeriod(TIM_TypeDef * TIMx)
- {
- return TIMx->CCR1;
- }
-
- float Timer_pwmi_getDutyCycle(TIM_TypeDef * TIMx) {
- const float arr = (float)LL_TIM_GetAutoReload(TIMx);
- float duty_cycle = (float)TIMx->CCR2 / arr;
- return duty_cycle;
- }
-
- /****************************************************************************
- * PWM OUTPUT
- ***************************************************************************/
-
- int getArrFromFreq(float freq)
- {
- return (72000 / freq) - 1;
- }
-
- void Timer_pwmo_conf(TIM_TypeDef * timer, int channel, float freq, float dutyCycle)
- {
- const int arr = getArrFromFreq(freq);
- Timer_conf(timer, arr, 1000);
- LL_TIM_OC_InitTypeDef init_struct;
- LL_TIM_OC_StructInit(&init_struct);
-
- init_struct.OCMode = LL_TIM_OCMODE_PWM1;
- init_struct.OCState = LL_TIM_OCSTATE_ENABLE;
- init_struct.CompareValue= dutyCycle * arr;
-
- LL_TIM_OC_Init(timer, channel, &init_struct);
- }
-
- void Timer_pwmo_setFreq(TIM_TypeDef * timer, float freq)
- {
- const int arr = getArrFromFreq(freq);
- LL_TIM_SetAutoReload(timer, arr);
- }
-
- void Timer_pwmo_setDutyCycle(TIM_TypeDef * timer, int channel, float dutyCycle)
- {
- const int arr = LL_TIM_GetAutoReload(timer);
- int compare = dutyCycle * arr;
- if (channel == LL_TIM_CHANNEL_CH1) LL_TIM_OC_SetCompareCH1(timer, compare);
- else if (channel == LL_TIM_CHANNEL_CH2) LL_TIM_OC_SetCompareCH2(timer, compare);
- else if (channel == LL_TIM_CHANNEL_CH3) LL_TIM_OC_SetCompareCH3(timer, compare);
- else LL_TIM_OC_SetCompareCH4(timer, compare);
- }
-
- float Timer_pwmo_getDutyCycle(TIM_TypeDef * timer, int channel)
- {
- int compare = 0;
- const int arr = LL_TIM_GetAutoReload(timer);
- if (channel == LL_TIM_CHANNEL_CH1) compare = LL_TIM_OC_GetCompareCH1(timer);
- else if (channel == LL_TIM_CHANNEL_CH2) compare = LL_TIM_OC_GetCompareCH2(timer);
- else if (channel == LL_TIM_CHANNEL_CH3) compare = LL_TIM_OC_GetCompareCH3(timer);
- else compare = LL_TIM_OC_GetCompareCH4(timer);
- return ((float) compare) / ((float) arr);
- }
-
- /****************************************************************************
- * ENCODER
- ***************************************************************************/
-
- void Timer_encoder_conf(TIM_TypeDef * timer)
- {
- // L'encodeur compte 2 tours quand on en fait qu'un, donc on divise l'angle
- // par deux avant de le renvoyer. Il faut donc un autoreload de 360 * 2 = 720
- Timer_conf(timer, 719, 0);
- LL_TIM_ENCODER_InitTypeDef init_struct;
- LL_TIM_ENCODER_StructInit(&init_struct);
-
- init_struct.EncoderMode = LL_TIM_ENCODERMODE_X2_TI1;
-
- LL_TIM_ENCODER_Init(timer, &init_struct);
- }
-
- int Timer_encoder_getAngle(TIM_TypeDef * timer)
- {
- // L'encodeur compte 2 tours quand on en fait qu'un, donc on divise l'angle
- // par deux avant de le renvoyer
- return LL_TIM_GetCounter(timer)/2;
- }
-
- enum CounterDirection Timer_encoder_getDirection(TIM_TypeDef * timer)
- {
- const int dir = LL_TIM_GetDirection(timer);
- if (dir == LL_TIM_COUNTERDIRECTION_UP)
- return CLOCKWISE;
- else
- return COUNTER_CLOCKWISE;
- }
|