205 lines
6.4 KiB
C++
Executable File
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
|