9#include "system_stm32f4xx.h"
16static void _TIM_init(TIM_TypeDef *,
TIM_Config *);
32 if (interface == NULL)
33 return (
TIM_t){.interface = NULL};
36 TIM_t tim = {.interface = interface};
66static void _TIM_init(TIM_TypeDef *interface,
TIM_Config *config) {
71 interface->CR1 &= ~TIM_CR1_CONFIG_MASK;
73 (config->ARPE << TIM_CR1_ARPE_Pos)
74 | (config->DIR << TIM_CR1_DIR_Pos)
75 | (config->OPM << TIM_CR1_OPM_Pos)
76 | (config->URS << TIM_CR1_URS_Pos)
77 | (config->UDIS << TIM_CR1_UDIS_Pos)
82 interface->CR2 &= ~TIM_CR2_CONFIG_MASK;
83 interface->CR2 |= (config->CCDS << TIM_CR2_CCDS_Pos);
88 interface->DIER &= ~TIM_DIER_CONFIG_MASK;
90 ((config->CCDE[0] & 0x01) << TIM_DIER_CC1DE_Pos)
91 | ((config->CCDE[1] & 0x01) << TIM_DIER_CC2DE_Pos)
92 | ((config->CCDE[2] & 0x01) << TIM_DIER_CC3DE_Pos)
93 | ((config->CCDE[3] & 0x01) << TIM_DIER_CC4DE_Pos)
94 | (config->UDE << TIM_DIER_UDE_Pos)
95 | ((config->CCIE[0] & 0x01) << TIM_DIER_CC1IE_Pos)
96 | ((config->CCIE[1] & 0x01) << TIM_DIER_CC2IE_Pos)
97 | ((config->CCIE[2] & 0x01) << TIM_DIER_CC3IE_Pos)
98 | ((config->CCIE[3] & 0x01) << TIM_DIER_CC4IE_Pos)
99 | (config->UIE << TIM_DIER_UIE_Pos)
104 for (TIM_Channel i = 0; i < TIM_CHANNEL4; i++) {
105 volatile uint32_t *reg = (i > TIM_CHANNEL2) ? &interface->CCMR2 : &interface->CCMR1;
107 uint8_t channelConfig = (
109 | config->OC[i].FE << 2
110 | config->OC[i].PE << 3
111 | config->OC[i].M << 4
112 | config->OC[i].CE << 7
115 *reg |= channelConfig << (i % 2);
128uint32_t _TIM_getBaseCLock(TIM_TypeDef *interface) {
130 uint32_t sysclk = HSE_USED ? SYSCLK_HSE : SYSCLK_HSI;
131 uint8_t hpre = AHBPresc[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
135 if ((
unsigned long)interface >= APB2PERIPH_BASE) {
136 ppre = APBPresc[((RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos)];
138 ppre = APBPresc[((RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos)];
142 uint32_t pclk = sysclk / hpre / ppre;
146 return (ppre > 1) ? 2 * pclk : pclk;
196 uint32_t pclk = _TIM_getBaseCLock(tim->
interface);
197 float clkPeriod = 1.0f / pclk;
201 if (period < clkPeriod)
207 maxCount = 0xFFFFFFFF;
214 float maxPeriod = maxCount * clkPeriod;
218 tim->
interface->PSC = (uint16_t)(period / maxPeriod);
221 float timClk = (float)pclk / (tim->
interface->PSC + 1);
224 float arr = period * timClk;
227 tim->
interface->ARR = (uint32_t)(arr + 0.5f);
242 if (tim->
interface->SR & (TIM_SR_CC1IF << channel)) {
243 tim->
interface->SR &= ~(TIM_SR_CC1IF << channel);
262 if (duty > 100 || duty < 0)
265 volatile uint32_t *channelCCR = &(tim->
interface->CCR1) + (4 * channel);
266 *channelCCR = (((float)tim->
interface->ARR / 100) * duty);
284 if (config == NULL) {
285 config = &TIM_CONFIG_DEFAULT;
void(* updateConfig)(struct TIM *tim, TIM_Config *config)
TIM configuration update method.
TIM_Config config
Configuration parameters for the TIM peripheral.
void(* startCounter)(struct TIM *tim)
TIM configuration update method.
TIM_TypeDef * interface
Pointer to TIM interface struct.
bool TIM_setTimingPeriod(TIM_t *tim, float period)
void TIM_updateConfig(TIM_t *tim, TIM_Config *config)
Update TIM peripheral configuration.
bool TIM_pollUpdate(TIM_t *tim)
TIM_t TIM_init(TIM_TypeDef *interface, TIM_Config *config)
Initialiser for an SPI device interface.
bool TIM_setTimingPWM(TIM_t *tim, TIM_Channel channel, float duty)
bool TIM_pollCompare(TIM_t *tim, TIM_Channel channel)
void TIM_startCounter(TIM_t *tim)
TIM configuration struct.
Struct definition for TIM interface. Provides the interface for API consumers to interact with the TI...