This repository has been archived on 2024-05-28. You can view files and clone it, but cannot push or open issues or pull requests.
2023-11-14 16:25:09 -05:00

205 lines
6.4 KiB
C++
Executable File

#ifndef STM32U5XX_HAL_TIM_HPP
#define STM32U5XX_HAL_TIM_HPP
#include "global_variable.h"
#include "queue.hpp"
#include "reg_nvic.h"
#include "reg_rcc.h"
#include "reg_tim.h"
#include "reg_uart.h"
#include "stm32u5xx.h"
/**
* @brief timer CMS counter mode selection
*
* 00: EdgeAlignMode: The counter counts up or down depending on the direction
* bit (DIR).
*
* 01: Center-aligned mode 1: The counter counts up and down alternatively.
* Output compare interrupt flags of channels configured in output (CCxS=00 in
* TIMx_CCMRx register) are set only when the counter is counting down.
*
* 10: Center-aligned mode 2: The counter counts up and down alternatively.
* Output compare interrupt flags of channels configured in output (CCxS=00 in
* TIMx_CCMRx register) are set only when the counter is counting up.
*
* 11: Center-aligned mode 3. The counter counts up and down alternatively.
* Output compare interrupt flags of channels configured in output (CCxS=00 in
* TIMx_CCMRx register) are set both when the counter is counting up or down.
*/
typedef enum {
EdgeAlignMode, CenterAlign1, CenterAlign2, CenterAlign3
} CMS;
/**
* @brief timer direction
*
* 0: Counter used as upcounter
* 1: Counter used as downcounter
*/
typedef enum {
UpCounting, DownCounting
} timer_dir_e;
typedef enum {
CH1, CH2, CH3, CH4
} timer_channel_e;
class Tim {
private:
TIM_TypeDef *instance;
reg_tim_t *reg;
uint32_t clk;
uint32_t irq;
public:
Tim() = default;
void setup(TIM_TypeDef *tim) {
instance = tim;
reg = (reg_tim_t *) tim;
}
/**
* @brief default initialization of timer
* @note this function initialize timer in default mode with following settings:
* - timer clock enable
* - timer counter direction: up counting
* - timer alignment mode: edge alignment (the counter register from 0 to ARR total ARR+1 counts)
* - timer prescaler: 0
* - timer repetition counter: 0 (RCR)
* - timer auto-reload preload enable
* - timer interrupt disabled
*/
void init_default() {
rcc_enable_timer_clock(instance); // enable clock
reg->cr1.cen = 0; // disable counter
reg->cr1.dir = UpCounting; // UpCounting
reg->cr1.cms = EdgeAlignMode; // EdgeAlignMode
reg->psc.psc = 0; // set prescaler
reg->rcr.rep = 0; // set repeat counter -- no repetition
reg->cr1.arpe = 1; // enable auto-reload preload
reg->dier.uie = 0; // disable interrupt
reg->egr.ug = 1; // generate update event to reload the registers immediately
reg->cr1.cen = 1; // enable counter
}
/**
* @brief set pwm mode for timer
* @note this function set timer in pwm mode with following settings:
* - timer clock enable
* - pwm mode 1
* @warning This function will change auto-reload register (ARR) and compare register (CCR1)
* The value of low + high not allow great than uint16_t.
*
* @note By default the system clock is 160 MHz, and clock prescaler is 1, so the timer clock is 160 MHz.
* @example
* if you want to set pwm frequency to 10 kHz, with 50% duty cycle, you should set low to 80k and high to 800k.
* `set_pwm(timer1, CH1, 8000, 8000);`
* if you want to set pwm frequency to 20 MHz, with 50% duty cycle, you should set low to 4 and high to 4.
* `set_pwm(timer1, CH1, 4, 4);`
*
*/
void set_pwm(timer_channel_e ch, uint16_t low, uint16_t high) {
CLEAR_BIT(instance->CR1, TIM_CR1_CEN); // disable counter
switch (ch) {
case CH1:
reg->ccmr1.out.cc1s = 0; // set cc1 channel to output
reg->ccmr1.out.oc1pe = 0; // disable compare preload.
reg->ccmr1.out.oc1m = 0b0110; // set pwm mode 1
reg->ccr1.ccr1 = low; // set low value
reg->arr.arr = low + high - 1; // set high value
break;
default:
break;
}
SET_BIT(instance->CR1, TIM_CR1_CEN); // enable counter
}
/**
* @brief set pwm duty cycle
* @note this function set pwm duty cycle by setting compare register
*
* @param tim timer
* @param ch channel
* @param duty_cycle duty cycle, range from 0 to 1
*/
void timer_set_pwm_duty_cycle(timer_channel_e ch, float duty_cycle) {
uint32_t high = (uint16_t) (duty_cycle * (float) (instance->ARR + 1));
uint32_t low = instance->ARR + 1 - high;
set_pwm(ch, low, high);
};
/**
* @brief enable timer channel output
* @param tim
* @param ch
* @note before calling this function, there is not output from the timer channel
* @warning Before calling this function, port should be setup
*/
void enable_output(timer_channel_e ch) {
switch (ch) {
case CH1:
reg->ccer.cc1e = 1;
reg->bdtr.moe = 1;
break;
default:
break;
}
}
/********************************************************************/
/* bellow code are deprecated, will be removed in the future */
/********************************************************************/
/**
* @brief timer initialization
* @param tim timer to initialize
* @param dir direction of the timer
* @param alignMode alignment mode of the timer.
*/
void tim_init(timer_dir_e dir, CMS alignMode) {
// enable clock
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
// enable interrupt
// set counter direction
instance->CR1 |= dir << TIM_CR1_DIR_Pos;
// set align mode
instance->CR1 |= alignMode << TIM_CR1_CMS_Pos;
// set prescaler
instance->PSC = 0;
// set repeat counter
instance->RCR = 0;
// set update generate
instance->EGR |= TIM_EGR_UG;
// auto-reload preload enable
instance->CR1 |= TIM_CR1_ARPE;
// enable timer counter
instance->ARR = 0x9;
instance->RCR = 0x9;
instance->CCR1 = 0x5;
instance->CR1 = 0x81;
// tim->CR1 |= TIM_CR1_CEN;
}
void tim_set_output(TIM_TypeDef *tim) {
tim->CCER |= TIM_CCER_CC1E;
}
void tim_out_enable(bool ena) {
// tim->BDTR |= TIM_BDTR_AOE;
// tim->BDTR |= TIM_BDTR_MOE;
instance->BDTR = 0x0200A000;
}
};
#endif // STM32U5XX_HAL_TIM_HPP