@@ -87,7 +87,7 @@ HardwareTimer::HardwareTimer(TIM_TypeDef *instance)
87
87
88
88
/* Configure timer with some default values */
89
89
_timerObj.handle .Init .Prescaler = 0 ;
90
- _timerObj.handle .Init .Period = 0xFFFF ; // 16bit max value
90
+ _timerObj.handle .Init .Period = MAX_RELOAD;
91
91
_timerObj.handle .Init .CounterMode = TIM_COUNTERMODE_UP;
92
92
_timerObj.handle .Init .ClockDivision = TIM_CLOCKDIVISION_DIV1;
93
93
#if defined(TIM_RCR_REP)
@@ -452,6 +452,7 @@ uint32_t HardwareTimer::getOverflow(TimerFormat_t format)
452
452
void HardwareTimer::setOverflow (uint32_t overflow, TimerFormat_t format)
453
453
{
454
454
uint32_t ARR_RegisterValue;
455
+ uint32_t PeriodTicks;
455
456
uint32_t Prescalerfactor;
456
457
uint32_t period_cyc;
457
458
// 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)
460
461
period_cyc = overflow * (getTimerClkFreq () / 1000000 );
461
462
Prescalerfactor = (period_cyc / 0x10000 ) + 1 ;
462
463
LL_TIM_SetPrescaler (_timerObj.handle .Instance , Prescalerfactor - 1 );
463
- ARR_RegisterValue = ( period_cyc / Prescalerfactor) - 1 ;
464
+ PeriodTicks = period_cyc / Prescalerfactor;
464
465
break ;
465
466
case HERTZ_FORMAT:
466
467
period_cyc = getTimerClkFreq () / overflow;
467
468
Prescalerfactor = (period_cyc / 0x10000 ) + 1 ;
468
469
LL_TIM_SetPrescaler (_timerObj.handle .Instance , Prescalerfactor - 1 );
469
- ARR_RegisterValue = ( period_cyc / Prescalerfactor) - 1 ;
470
+ PeriodTicks = period_cyc / Prescalerfactor;
470
471
break ;
471
472
case TICK_FORMAT:
472
473
default :
473
- ARR_RegisterValue = overflow - 1 ;
474
+ PeriodTicks = overflow;
474
475
break ;
475
476
}
476
477
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
+ }
477
485
__HAL_TIM_SET_AUTORELOAD (&_timerObj.handle , ARR_RegisterValue);
478
486
}
479
487
@@ -520,14 +528,14 @@ void HardwareTimer::setCount(uint32_t counter, TimerFormat_t format)
520
528
uint32_t Prescalerfactor = LL_TIM_GetPrescaler (_timerObj.handle .Instance ) + 1 ;
521
529
switch (format) {
522
530
case MICROSEC_FORMAT:
523
- CNT_RegisterValue = ((counter * (getTimerClkFreq () / 1000000 )) / Prescalerfactor) - 1 ;
531
+ CNT_RegisterValue = ((counter * (getTimerClkFreq () / 1000000 )) / Prescalerfactor);
524
532
break ;
525
533
case HERTZ_FORMAT:
526
- CNT_RegisterValue = (uint32_t )(( getTimerClkFreq () / (counter * Prescalerfactor)) - 1 );
534
+ CNT_RegisterValue = (uint32_t )(getTimerClkFreq () / (counter * Prescalerfactor));
527
535
break ;
528
536
case TICK_FORMAT:
529
537
default :
530
- CNT_RegisterValue = counter - 1 ;
538
+ CNT_RegisterValue = counter;
531
539
break ;
532
540
}
533
541
__HAL_TIM_SET_COUNTER (&(_timerObj.handle ), CNT_RegisterValue);
@@ -699,11 +707,12 @@ void HardwareTimer::setCaptureCompare(uint32_t channel, uint32_t compare, TimerC
699
707
700
708
switch (format) {
701
709
case MICROSEC_COMPARE_FORMAT:
702
- CCR_RegisterValue = ((compare * (getTimerClkFreq () / 1000000 )) / Prescalerfactor) - 1 ;
710
+ CCR_RegisterValue = ((compare * (getTimerClkFreq () / 1000000 )) / Prescalerfactor);
703
711
break ;
704
712
case HERTZ_COMPARE_FORMAT:
705
- CCR_RegisterValue = ( getTimerClkFreq () / (compare * Prescalerfactor)) - 1 ;
713
+ CCR_RegisterValue = getTimerClkFreq () / (compare * Prescalerfactor);
706
714
break ;
715
+ // As per Reference Manual PWM reach 100% with CCRx value strictly greater than ARR (So ARR+1 in our case)
707
716
case PERCENT_COMPARE_FORMAT:
708
717
CCR_RegisterValue = ((__HAL_TIM_GET_AUTORELOAD (&(_timerObj.handle )) + 1 ) * compare) / 100 ;
709
718
break ;
@@ -727,10 +736,17 @@ void HardwareTimer::setCaptureCompare(uint32_t channel, uint32_t compare, TimerC
727
736
break ;
728
737
case TICK_COMPARE_FORMAT:
729
738
default :
730
- CCR_RegisterValue = compare - 1 ;
739
+ CCR_RegisterValue = compare;
731
740
break ;
732
741
}
733
742
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
+
734
750
__HAL_TIM_SET_COMPARE (&(_timerObj.handle ), timChannel, CCR_RegisterValue);
735
751
}
736
752
0 commit comments