pwm: Increase timer resolution

This commit is contained in:
Daniel Fekete 2017-06-20 06:28:43 +02:00
parent cc7a09c696
commit f551dd732b
1 changed files with 18 additions and 14 deletions

View File

@ -25,7 +25,11 @@
TIM_HandleTypeDef *handle; TIM_HandleTypeDef *handle;
static uint32_t counter; static uint32_t counter;
static uint32_t period; static uint32_t waitCycles;
const uint32_t TIMER_MAX_CYCLES = UINT16_MAX;
const uint32_t PWM_FREQUENCY_HZ = 1000;
extern void pinMode(uint8_t, uint8_t); extern void pinMode(uint8_t, uint8_t);
@ -40,8 +44,8 @@ void pwm_callback();
typedef struct { typedef struct {
GPIO_TypeDef *port; GPIO_TypeDef *port;
uint32_t pin_mask; uint32_t pin_mask;
uint16_t frequency; uint32_t frequency;
uint16_t duty_cycle; uint32_t duty_cycle;
} stm32_pwm_type; } stm32_pwm_type;
static stm32_pwm_type pwm_config[sizeof(variant_pin_list) / sizeof(variant_pin_list[0])]; static stm32_pwm_type pwm_config[sizeof(variant_pin_list) / sizeof(variant_pin_list[0])];
@ -72,10 +76,10 @@ void analogWrite(uint8_t pin, int value) {
handle->Instance = TIM3; handle->Instance = TIM3;
#endif #endif
handle->Init.Prescaler = 999; handle->Init.Prescaler = 0;
handle->Init.CounterMode = TIM_COUNTERMODE_UP; handle->Init.CounterMode = TIM_COUNTERMODE_UP;
period = 256; waitCycles = TIMER_MAX_CYCLES;
handle->Init.Period = period; handle->Init.Period = waitCycles;
handle->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; handle->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(handle); HAL_TIM_Base_Init(handle);
@ -93,8 +97,8 @@ void analogWrite(uint8_t pin, int value) {
pwm_config[i].port = variant_pin_list[pin].port; pwm_config[i].port = variant_pin_list[pin].port;
pwm_config[i].pin_mask = variant_pin_list[pin].pin_mask; pwm_config[i].pin_mask = variant_pin_list[pin].pin_mask;
pwm_config[i].frequency = 255; pwm_config[i].frequency = HAL_RCC_GetPCLK2Freq() / PWM_FREQUENCY_HZ;
pwm_config[i].duty_cycle = value; pwm_config[i].duty_cycle = pwm_config[i].frequency * value / 256;
break; break;
} }
} }
@ -128,14 +132,14 @@ void pwm_callback() {
if(__HAL_TIM_GET_IT_SOURCE(handle, TIM_IT_UPDATE) !=RESET) { if(__HAL_TIM_GET_IT_SOURCE(handle, TIM_IT_UPDATE) !=RESET) {
__HAL_TIM_CLEAR_IT(handle, TIM_IT_UPDATE); __HAL_TIM_CLEAR_IT(handle, TIM_IT_UPDATE);
counter += period; counter += waitCycles;
period = 256; waitCycles = TIMER_MAX_CYCLES;
for(size_t i=0; i<sizeof(pwm_config); i++) { for(size_t i=0; i<sizeof(pwm_config); i++) {
if (pwm_config[i].port != NULL) { if (pwm_config[i].port != NULL) {
if (pwm_config[i].duty_cycle > counter % pwm_config[i].frequency) { if (pwm_config[i].duty_cycle > counter % pwm_config[i].frequency) {
pwm_config[i].port->BSRR = pwm_config[i].pin_mask; pwm_config[i].port->BSRR = pwm_config[i].pin_mask;
period = min(period, pwm_config[i].duty_cycle - (counter % pwm_config[i].frequency)); waitCycles = min(waitCycles, pwm_config[i].duty_cycle - (counter % pwm_config[i].frequency));
} else { } else {
pwm_config[i].port->BSRR = pwm_config[i].pin_mask << 16; pwm_config[i].port->BSRR = pwm_config[i].pin_mask << 16;
period = min(period, 256 - counter % pwm_config[i].frequency); period = min(period, 256 - counter % pwm_config[i].frequency);
@ -145,10 +149,10 @@ void pwm_callback() {
} }
} }
if (!period) { if (!waitCycles || waitCycles > TIMER_MAX_CYCLES) {
period = 256; waitCycles = TIMER_MAX_CYCLES;
} }
__HAL_TIM_SET_AUTORELOAD(handle, period); __HAL_TIM_SET_AUTORELOAD(handle, waitCycles);
} }
} }
} }