74 lines
1.9 KiB
C
74 lines
1.9 KiB
C
#include <libopencm3/stm32/gpio.h>
|
|
#include <libopencm3/stm32/timer.h>
|
|
|
|
#include "fan_ctrl_pwm.h"
|
|
|
|
#include "pinout.h"
|
|
|
|
void fan_ctrl_pwm_init(void)
|
|
{
|
|
// disable the DC/DC bypass until PWM control mode is actually enabled
|
|
gpio_clear(DCDC_PORT, DCDC_BYPASS_SWITCH_PIN);
|
|
gpio_mode_setup(DCDC_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, DCDC_BYPASS_SWITCH_PIN);
|
|
|
|
// *** TIM21 ***
|
|
// Configure channel 1 for PWM
|
|
// Ch1 = charge pump output
|
|
|
|
timer_set_mode(TIM21, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
|
|
|
|
// set up PWM channel
|
|
timer_set_oc_mode(TIM21, TIM_OC1, TIM_OCM_PWM1);
|
|
timer_enable_oc_output(TIM21, TIM_OC1);
|
|
timer_enable_oc_preload(TIM21, TIM_OC1);
|
|
timer_set_oc_polarity_high(TIM21, TIM_OC1);
|
|
|
|
// prescaler
|
|
timer_set_prescaler(TIM21, 21 - 1); // Timer runs at 100 kHz
|
|
|
|
// auto-reload value
|
|
timer_set_period(TIM21, 100 - 1); // overflow every 100 cycles = 1 kHz
|
|
|
|
// output compare value
|
|
timer_set_oc_value(TIM21, TIM_OC1, 0); // No PWM output by default
|
|
|
|
// only generate interrupt on overflow
|
|
timer_update_on_overflow(TIM21);
|
|
|
|
// enable main output
|
|
timer_enable_break_main_output(TIM21);
|
|
}
|
|
|
|
|
|
void fan_ctrl_pwm_enable(void)
|
|
{
|
|
// enable the DC/DC bypass (power the fan directly from the supply voltage)
|
|
gpio_set(DCDC_PORT, DCDC_BYPASS_SWITCH_PIN);
|
|
|
|
// Enable PWM output on the PWM GPIO
|
|
gpio_set_af(FAN_PORT, GPIO_AF0, FAN_PWM_PIN);
|
|
|
|
// start the PWM timer
|
|
timer_enable_counter(TIM21);
|
|
}
|
|
|
|
|
|
void fan_ctrl_pwm_disable(void)
|
|
{
|
|
// disable the DC/DC bypass again
|
|
gpio_clear(DCDC_PORT, DCDC_BYPASS_SWITCH_PIN);
|
|
|
|
// set PWM value to 0 and stop the counter
|
|
timer_set_oc_value(TIM21, TIM_OC1, 0);
|
|
timer_disable_counter(TIM21);
|
|
|
|
// configure the PWM GPIO as input so the fan runs full speed if powered
|
|
}
|
|
|
|
|
|
void fan_ctrl_pwm_set_duty(uint8_t percent)
|
|
{
|
|
// as the timer has 100 steps per cycle, we can directly use the percentage value
|
|
timer_set_oc_value(TIM21, TIM_OC1, percent);
|
|
}
|