projet_voilier/MyDrivers/Timer.c
2020-11-10 14:24:15 +01:00

281 lines
8.3 KiB
C
Raw Blame History

#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 <20> 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 <20> utiliser par le chronom<6F>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 <20> utiliser par le chronom<6F>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<69>r<EFBFBD> en interruption sur d<>bordement.
* @note A ce stade, les interruptions ne sont pas valid<69>s (voir MyTimer_IT_Enable )
* @param TIM_TypeDef Timer : indique le timer <20> utiliser par le chronom<6F>tre, TIM1, TIM2, TIM3 ou TIM4
* void (*IT_function) (void) : nom (adresse) de la fonction <20> lancer sur interruption
* int Prio : priorit<69> associ<63>e <20> 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<69>r<EFBFBD> et active les interruptions
* @note
* @param TIM_TypeDef Timer : indique le timer <20> utiliser par le chronom<6F>tre, TIM1, TIM2, TIM3 ou TIM4
* @retval None
*/
void Timer_start(TIM_TypeDef * timer)
{
LL_TIM_EnableCounter(timer);
}
/**
* @brief Arr<72>t le timer consid<69>r<EFBFBD> et d<>sactive les interruptions
* @note
* @param TIM_TypeDef Timer : indique le timer <20> utiliser par le chronom<6F>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<69>.
* @note Fonction <20> lancer avant toute autre. Le timer n'est pas encore lanc<6E> (voir Timer_start)
* @param TIM_TypeDef Timer : indique le timer <20> utiliser par le chronom<6F>tre, TIM1, TIM2, TIM3 ou TIM4
* int Arr : valeur <20> placer dans ARR
* int Psc : valeur <20> 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, uint32_t channels){
//Periode à recuperer dans TIMx_CCR1, duty cycle dans TIMx_CCR2
// 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);
//LL_TIM_CC_EnableChannel(TIMx, channels);
//LL_TIM_IC_Init
TIMx -> CCMR1 |= TIM_CCMR1_CC1S_0; //01
//TIM_CCMR1_IC1F_0; Potentiellement utile, à voir plus tard
TIMx -> CCER &= ~(TIM_CCER_CC1P); //0 = Rising edge
TIMx -> CCMR1 &= ~(TIM_CCMR1_IC1PSC);
TIMx -> CCMR1 |= TIM_CCMR1_CC2S_1;
TIMx -> CCER |= TIM_CCER_CC2P;
TIMx -> SMCR |= TIM_SMCR_TS_0 | TIM_SMCR_TS_2; //101
TIMx -> SMCR |= TIM_SMCR_SMS_2; //100
TIMx -> CCER |= TIM_CCER_CC1E;
TIMx -> CCER |= TIM_CCER_CC2E;
TIMx -> DIER |= TIM_DIER_CC1IE;
//TIM_DIER_CC1DE_Pos; Probablement pas utile
}
int get_input_period(TIM_TypeDef * TIMx) {
return TIMx -> CCR1;
}
int get_input_duty_cycle(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;
}