static void tim_setup() { //Some explanation: HCLK=72MHz //APB1-Prescaler is 2 -> 36MHz //Timer clock source is ABP1*2 because APB1 prescaler > 1 //So clock source is 72MHz (again) //We want the timer to run at 1MHz = 72MHz/72 //Prescaler is div-1 => 71 timer_set_prescaler(REV_CNT_TIMER, 71); timer_set_period(REV_CNT_TIMER, MAX_CNT); timer_update_on_overflow(REV_CNT_TIMER); timer_direction_up(REV_CNT_TIMER); /*timer_ic_enable(REV_CNT_TIMER, REV_CNT_IC); timer_ic_set_filter(REV_CNT_TIMER, REV_CNT_IC, TIM_IC_DTF_DIV_32_N_6); timer_ic_set_prescaler(REV_CNT_TIMER, REV_CNT_IC, TIM_IC_PSC_OFF); timer_ic_set_input(REV_CNT_TIMER, REV_CNT_IC, TIM_IC_IN_TI2);*/ /* Reset counter on input pulse. Filter constant must be larger than that of the capture input So that the counter value is first saved, then reset */ TIM_SMCR(REV_CNT_TIMER) = TIM_SMCR_SMS_RM | TIM_SMCR_TS_ETRF | TIM_SMCR_ETP | TIM_SMCR_ETF_DTS_DIV_32_N_8; /* Save timer value on input pulse with smaller filter constant */ TIM_CCMR2(REV_CNT_TIMER) = REV_CNT_CCMR2 | TIM_CCMR2_IC3F_DTF_DIV_32_N_6; TIM_CCER(REV_CNT_TIMER) |= REV_CNT_CCER; //1 << (1 + 4 * REV_CNT_IC); //timer_enable_irq(REV_CNT_TIMER, TIM_DIER_CC3IE); //timer_set_dma_on_compare_event(REV_CNT_TIMER); timer_generate_event(REV_CNT_TIMER, TIM_EGR_UG); timer_enable_counter(REV_CNT_TIMER); }
void timer_disable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id) { switch (oc_id) { case TIM_OC1: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1PE; break; case TIM_OC2: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2PE; break; case TIM_OC3: TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3PE; break; case TIM_OC4: TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4PE; break; case TIM_OC1N: case TIM_OC2N: case TIM_OC3N: /* Ignoring as this option applies to the whole channel. */ break; } }
void timer_set_oc_slow_mode(u32 timer_peripheral, enum tim_oc_id oc_id) { switch (oc_id) { case TIM_OC1: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1FE; break; case TIM_OC2: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2FE; break; case TIM_OC3: TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3FE; break; case TIM_OC4: TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4FE; break; case TIM_OC1N: case TIM_OC2N: case TIM_OC3N: /* Ignoring as this option applies to the whole channel. */ break; } }
void timer_set_oc_fast_mode(u32 timer_peripheral, enum tim_oc_id oc_id) { switch (oc_id) { case TIM_OC1: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1FE; break; case TIM_OC2: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2FE; break; case TIM_OC3: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3FE; break; case TIM_OC4: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4FE; break; case TIM_OC1N: case TIM_OC2N: case TIM_OC3N: /* Ignoring as fast enable only applies to the whole channel. */ break; } }
void timer_disable_oc_clear(u32 timer_peripheral, enum tim_oc_id oc_id) { switch (oc_id) { case TIM_OC1: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1CE; break; case TIM_OC2: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2CE; break; case TIM_OC3: TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3CE; break; case TIM_OC4: TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4CE; break; case TIM_OC1N: case TIM_OC2N: case TIM_OC3N: /* Ignoring as fast enable only applies to the whole channel. */ break; } }
void timer_set_oc_mode(u32 timer_peripheral, enum tim_oc_id oc_id, enum tim_oc_mode oc_mode) { switch (oc_id) { case TIM_OC1: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC1S_MASK; TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_CC1S_OUT; TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1M_MASK; switch (oc_mode) { case TIM_OCM_FROZEN: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FROZEN; break; case TIM_OCM_ACTIVE: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_ACTIVE; break; case TIM_OCM_INACTIVE: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_INACTIVE; break; case TIM_OCM_TOGGLE: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_TOGGLE; break; case TIM_OCM_FORCE_LOW: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FORCE_LOW; break; case TIM_OCM_FORCE_HIGH: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FORCE_HIGH; break; case TIM_OCM_PWM1: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_PWM1; break; case TIM_OCM_PWM2: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_PWM2; break; } break; case TIM_OC2: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC2S_MASK; TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_CC2S_OUT; TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2M_MASK; switch (oc_mode) { case TIM_OCM_FROZEN: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FROZEN; break; case TIM_OCM_ACTIVE: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_ACTIVE; break; case TIM_OCM_INACTIVE: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_INACTIVE; break; case TIM_OCM_TOGGLE: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_TOGGLE; break; case TIM_OCM_FORCE_LOW: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FORCE_LOW; break; case TIM_OCM_FORCE_HIGH: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FORCE_HIGH; break; case TIM_OCM_PWM1: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_PWM1; break; case TIM_OCM_PWM2: TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_PWM2; break; } break; case TIM_OC3: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR2_CC3S_MASK; TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_CC3S_OUT; TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3M_MASK; switch (oc_mode) { case TIM_OCM_FROZEN: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FROZEN; break; case TIM_OCM_ACTIVE: TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_OC3M_ACTIVE; break; case TIM_OCM_INACTIVE: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_INACTIVE; break; case TIM_OCM_TOGGLE: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_TOGGLE; break; case TIM_OCM_FORCE_LOW: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FORCE_LOW; break; case TIM_OCM_FORCE_HIGH: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FORCE_HIGH; break; case TIM_OCM_PWM1: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_PWM1; break; case TIM_OCM_PWM2: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_PWM2; break; } break; case TIM_OC4: TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR2_CC4S_MASK; TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_CC4S_OUT; TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4M_MASK; switch (oc_mode) { case TIM_OCM_FROZEN: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FROZEN; break; case TIM_OCM_ACTIVE: TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_OC4M_ACTIVE; break; case TIM_OCM_INACTIVE: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_INACTIVE; break; case TIM_OCM_TOGGLE: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_TOGGLE; break; case TIM_OCM_FORCE_LOW: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FORCE_LOW; break; case TIM_OCM_FORCE_HIGH: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FORCE_HIGH; break; case TIM_OCM_PWM1: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_PWM1; break; case TIM_OCM_PWM2: TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_PWM2; break; } break; case TIM_OC1N: case TIM_OC2N: case TIM_OC3N: /* Ignoring as this option applies to the whole channel. */ break; } }
bool Pwm_stm32::init(void) { bool success = true; /* Enable peripheral port & TIM clock. */ //rcc_periph_clock_enable(RCC_GPIOx); rcc_periph_clock_enable(pwm_config_.rcc_timer_config); gpio_mode_setup(pwm_config_.gpio_config.port, GPIO_MODE_AF, GPIO_PUPD_NONE, pwm_config_.gpio_config.pin); gpio_set_af(pwm_config_.gpio_config.port, pwm_config_.gpio_config.alt_fct, pwm_config_.gpio_config.pin); gpio_set_output_options(pwm_config_.gpio_config.port, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, pwm_config_.gpio_config.port); //WARNING Common to all channels of that TIMER //select prescaler TIM_PSC(pwm_config_.timer_config) = prescaler_; //select the output period TIM_ARR(pwm_config_.timer_config) = period_; //enable the autoreload TIM_CR1(pwm_config_.timer_config) |= TIM_CR1_ARPE; //select counting mode (edge-aligned) TIM_CR1(pwm_config_.timer_config) |= TIM_CR1_CMS_EDGE; //counting up TIM_CR1(pwm_config_.timer_config) |= TIM_CR1_DIR_UP; //enable counter TIM_CR1(pwm_config_.timer_config) |= TIM_CR1_CEN; //CHANNEL SPECIFIC if (pwm_config_.channel_config == PWM_STM32_CHANNEL_1) { //Disable channel1 TIM_CCER(pwm_config_.timer_config) &= (uint16_t)~TIM_CCER_CC1E; //Reset output compare TIM_CCMR1(pwm_config_.timer_config) &= (uint16_t)~TIM_CCMR1_OC1M_MASK; TIM_CCMR1(pwm_config_.timer_config) &= (uint16_t)~TIM_CCMR1_CC1S_MASK; //Select output mode TIM_CCMR1(pwm_config_.timer_config) |= TIM_CCMR1_CC1S_OUT; //select polarity low TIM_CCER(pwm_config_.timer_config) |= TIM_CCER_CC1NP; //select PWM mode 1 TIM_CCMR1(pwm_config_.timer_config) |= TIM_CCMR1_OC1M_PWM1; //select duty cycle TIM_CCR1(pwm_config_.timer_config) = duty_cyle_; //set the preload bit TIM_CCMR1(pwm_config_.timer_config) |= TIM_CCMR1_OC1PE; //enable capture/compare TIM_CCER(pwm_config_.timer_config) |= TIM_CCER_CC1E; } else if (pwm_config_.channel_config == PWM_STM32_CHANNEL_2) { //Disable channel2 TIM_CCER(pwm_config_.timer_config) &= (uint16_t)~TIM_CCER_CC2E; //Reset output compare TIM_CCMR1(pwm_config_.timer_config) &= (uint16_t)~TIM_CCMR1_OC2M_MASK; TIM_CCMR1(pwm_config_.timer_config) &= (uint16_t)~TIM_CCMR1_CC2S_MASK; //Select output mode TIM_CCMR1(pwm_config_.timer_config) |= TIM_CCMR1_CC2S_OUT; //select polarity low TIM_CCER(pwm_config_.timer_config) |= TIM_CCER_CC2NP; //select PWM mode 1 TIM_CCMR1(pwm_config_.timer_config) |= TIM_CCMR1_OC2M_PWM1; //select duty cycle TIM_CCR2(pwm_config_.timer_config) = duty_cyle_; //set the preload bit TIM_CCMR1(pwm_config_.timer_config) |= TIM_CCMR1_OC2PE; //enable capture/compare TIM_CCER(pwm_config_.timer_config) |= TIM_CCER_CC2E; } else if (pwm_config_.channel_config == PWM_STM32_CHANNEL_3) { //Disable channel3 TIM_CCER(pwm_config_.timer_config) &= (uint16_t)~TIM_CCER_CC3E; //Reset output compare TIM_CCMR2(pwm_config_.timer_config) &= (uint16_t)~TIM_CCMR2_OC3M_MASK; TIM_CCMR2(pwm_config_.timer_config) &= (uint16_t)~TIM_CCMR2_CC3S_MASK; //Select output mode TIM_CCMR2(pwm_config_.timer_config) |= TIM_CCMR2_CC3S_OUT; //select polarity low TIM_CCER(pwm_config_.timer_config) |= TIM_CCER_CC3NP; //select PWM mode 1 TIM_CCMR2(pwm_config_.timer_config) |= TIM_CCMR2_OC3M_PWM1; //select duty cycle TIM_CCR3(pwm_config_.timer_config) = duty_cyle_; //set the preload bit TIM_CCMR2(pwm_config_.timer_config) |= TIM_CCMR2_OC3PE; //enable capture/compare TIM_CCER(pwm_config_.timer_config) |= TIM_CCER_CC3E; } else if (pwm_config_.channel_config == PWM_STM32_CHANNEL_4) { //Disable channel4 TIM_CCER(pwm_config_.timer_config) &= (uint16_t)~TIM_CCER_CC4E; //Reset output compare TIM_CCMR2(pwm_config_.timer_config) &= (uint16_t)~TIM_CCMR2_OC4M_MASK; TIM_CCMR2(pwm_config_.timer_config) &= (uint16_t)~TIM_CCMR2_CC4S_MASK; //Select output mode TIM_CCMR2(pwm_config_.timer_config) |= TIM_CCMR2_CC4S_OUT; //select polarity low TIM_CCER(pwm_config_.timer_config) |= (1 << 15); //TODO TIM_CCER_CC4NP does not exist in libopencm3 library //select PWM mode 1 TIM_CCMR2(pwm_config_.timer_config) |= TIM_CCMR2_OC4M_PWM1; //select duty cycle TIM_CCR4(pwm_config_.timer_config) = duty_cyle_; //set the preload bit TIM_CCMR2(pwm_config_.timer_config) |= TIM_CCMR2_OC4PE; //enable capture/compare TIM_CCER(pwm_config_.timer_config) |= TIM_CCER_CC4E; } return success; }