@@ -87,7 +87,7 @@ HardwareTimer::HardwareTimer(TIM_TypeDef *instance)
8787
8888 /* Configure timer with some default values */
8989 _timerObj.handle .Init .Prescaler = 0 ;
90- _timerObj.handle .Init .Period = 0xFFFF ; // 16bit max value
90+ _timerObj.handle .Init .Period = MAX_RELOAD;
9191 _timerObj.handle .Init .CounterMode = TIM_COUNTERMODE_UP;
9292 _timerObj.handle .Init .ClockDivision = TIM_CLOCKDIVISION_DIV1;
9393#if defined(TIM_RCR_REP)
@@ -452,6 +452,7 @@ uint32_t HardwareTimer::getOverflow(TimerFormat_t format)
452452void HardwareTimer::setOverflow (uint32_t overflow, TimerFormat_t format)
453453{
454454 uint32_t ARR_RegisterValue;
455+ uint32_t PeriodTicks;
455456 uint32_t Prescalerfactor;
456457 uint32_t period_cyc;
457458 // Remark: Hardware register correspond to period count-1. Example ARR register value 9 means period of 10 timer cycle
@@ -460,20 +461,27 @@ void HardwareTimer::setOverflow(uint32_t overflow, TimerFormat_t format)
460461 period_cyc = overflow * (getTimerClkFreq () / 1000000 );
461462 Prescalerfactor = (period_cyc / 0x10000 ) + 1 ;
462463 LL_TIM_SetPrescaler (_timerObj.handle .Instance , Prescalerfactor - 1 );
463- ARR_RegisterValue = ( period_cyc / Prescalerfactor) - 1 ;
464+ PeriodTicks = period_cyc / Prescalerfactor;
464465 break ;
465466 case HERTZ_FORMAT:
466467 period_cyc = getTimerClkFreq () / overflow;
467468 Prescalerfactor = (period_cyc / 0x10000 ) + 1 ;
468469 LL_TIM_SetPrescaler (_timerObj.handle .Instance , Prescalerfactor - 1 );
469- ARR_RegisterValue = ( period_cyc / Prescalerfactor) - 1 ;
470+ PeriodTicks = period_cyc / Prescalerfactor;
470471 break ;
471472 case TICK_FORMAT:
472473 default :
473- ARR_RegisterValue = overflow - 1 ;
474+ PeriodTicks = overflow;
474475 break ;
475476 }
476477
478+ if (PeriodTicks > 0 ) {
479+ // The register specifies the maximum value, so the period is really one tick longer
480+ ARR_RegisterValue = PeriodTicks - 1 ;
481+ } else {
482+ // But do not underflow in case a zero period was given somehow.
483+ ARR_RegisterValue = 0 ;
484+ }
477485 __HAL_TIM_SET_AUTORELOAD (&_timerObj.handle , ARR_RegisterValue);
478486}
479487
@@ -520,14 +528,14 @@ void HardwareTimer::setCount(uint32_t counter, TimerFormat_t format)
520528 uint32_t Prescalerfactor = LL_TIM_GetPrescaler (_timerObj.handle .Instance ) + 1 ;
521529 switch (format) {
522530 case MICROSEC_FORMAT:
523- CNT_RegisterValue = ((counter * (getTimerClkFreq () / 1000000 )) / Prescalerfactor) - 1 ;
531+ CNT_RegisterValue = ((counter * (getTimerClkFreq () / 1000000 )) / Prescalerfactor);
524532 break ;
525533 case HERTZ_FORMAT:
526- CNT_RegisterValue = (uint32_t )(( getTimerClkFreq () / (counter * Prescalerfactor)) - 1 );
534+ CNT_RegisterValue = (uint32_t )(getTimerClkFreq () / (counter * Prescalerfactor));
527535 break ;
528536 case TICK_FORMAT:
529537 default :
530- CNT_RegisterValue = counter - 1 ;
538+ CNT_RegisterValue = counter;
531539 break ;
532540 }
533541 __HAL_TIM_SET_COUNTER (&(_timerObj.handle ), CNT_RegisterValue);
@@ -699,11 +707,12 @@ void HardwareTimer::setCaptureCompare(uint32_t channel, uint32_t compare, TimerC
699707
700708 switch (format) {
701709 case MICROSEC_COMPARE_FORMAT:
702- CCR_RegisterValue = ((compare * (getTimerClkFreq () / 1000000 )) / Prescalerfactor) - 1 ;
710+ CCR_RegisterValue = ((compare * (getTimerClkFreq () / 1000000 )) / Prescalerfactor);
703711 break ;
704712 case HERTZ_COMPARE_FORMAT:
705- CCR_RegisterValue = ( getTimerClkFreq () / (compare * Prescalerfactor)) - 1 ;
713+ CCR_RegisterValue = getTimerClkFreq () / (compare * Prescalerfactor);
706714 break ;
715+ // As per Reference Manual PWM reach 100% with CCRx value strictly greater than ARR (So ARR+1 in our case)
707716 case PERCENT_COMPARE_FORMAT:
708717 CCR_RegisterValue = ((__HAL_TIM_GET_AUTORELOAD (&(_timerObj.handle )) + 1 ) * compare) / 100 ;
709718 break ;
@@ -727,10 +736,17 @@ void HardwareTimer::setCaptureCompare(uint32_t channel, uint32_t compare, TimerC
727736 break ;
728737 case TICK_COMPARE_FORMAT:
729738 default :
730- CCR_RegisterValue = compare - 1 ;
739+ CCR_RegisterValue = compare;
731740 break ;
732741 }
733742
743+ // Special case when ARR is set to the max value, it is not possible to set CCRx to ARR+1 to reach 100%
744+ // Then set CCRx to max value. PWM is then 1/0xFFFF = 99.998..%
745+ if ((__HAL_TIM_GET_AUTORELOAD (&(_timerObj.handle )) == MAX_RELOAD)
746+ && (CCR_RegisterValue == MAX_RELOAD + 1 )) {
747+ CCR_RegisterValue = MAX_RELOAD;
748+ }
749+
734750 __HAL_TIM_SET_COMPARE (&(_timerObj.handle ), timChannel, CCR_RegisterValue);
735751}
736752
0 commit comments