#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)(); } /** * @brief Autorise les interruptions * @note * @param TIM_TypeDef Timer : indique le timer � utiliser par le chronom�tre, TIM1, TIM2, TIM3 ou TIM4 * @retval None */ void Timer_IT_enable(TIM_TypeDef * timer) { LL_TIM_EnableIT_UPDATE(timer); } /** * @brief Interdit les interruptions * @note * @param TIM_TypeDef Timer : indique le timer � utiliser par le chronom�tre, TIM1, TIM2, TIM3 ou TIM4 * @retval None */ void Timer_IT_disable(TIM_TypeDef * timer) { LL_TIM_DisableIT_UPDATE(timer); } /** * @brief Configure le Timer consid�r� en interruption sur d�bordement. * @note A ce stade, les interruptions ne sont pas valid�s (voir MyTimer_IT_Enable ) * @param TIM_TypeDef Timer : indique le timer � utiliser par le chronom�tre, TIM1, TIM2, TIM3 ou TIM4 * void (*IT_function) (void) : nom (adresse) de la fonction � lancer sur interruption * int Prio : priorit� associ�e � l'interruption * @retval None */ 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 d�bloquer 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 ***************************************************************************/ /** * @brief D�marre le timer consid�r� et active les interruptions * @note * @param TIM_TypeDef Timer : indique le timer � utiliser par le chronom�tre, TIM1, TIM2, TIM3 ou TIM4 * @retval None */ void Timer_start(TIM_TypeDef * timer) { LL_TIM_EnableCounter(timer); } /** * @brief Arr�t le timer consid�r� et d�sactive les interruptions * @note * @param TIM_TypeDef Timer : indique le timer � utiliser par le chronom�tre, TIM1, TIM2, TIM3 ou TIM4 * @retval None */ void Timer_stop(TIM_TypeDef * timer) { LL_TIM_DisableCounter(timer); } /** * @brief Active l'horloge et r�gle l'ARR et le PSC du timer vis�. * @note Fonction � lancer avant toute autre. Le timer n'est pas encore lanc� (voir Timer_start) * @param TIM_TypeDef Timer : indique le timer � utiliser par le chronom�tre, TIM1, TIM2, TIM3 ou TIM4 * int Arr : valeur � placer dans ARR * int Psc : valeur � placer dans PSC * @retval None */ 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 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 PWMi_getPeriod(TIM_TypeDef * TIMx) { return TIMx -> CCR1; } int PWMi_getDutyCycle(TIM_TypeDef * TIMx) { return TIMx -> CCR2; } /**************************************************************************** * 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) { Timer_conf(timer, 359, 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) { return LL_TIM_GetCounter(timer); } 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; }