STM32 HRTIM PWM 仅在主比较 > 70ns 时工作
STM32 HRTIM PWM only work when master compare is > 70ns
STM32G474
STM32CubeIDE 1.7.0
我需要实现四个不同的 PWM 通道,它们可以以 5 度的间隔移动(例如 A = 0°,B = 5°,C = 10°,D = 180°)。 PWM 输出占空比为 50%。重要的只是通道之间的转换。
实施:
计时大师
- HRTIM 输入时钟:170 MHz
- 主定时器PWM频率:1.6 MHz
- 预分频比:HRTIM 时钟乘以 32 -> fHRCK = 5.44E9 Hz
- 期间:HRTIM_INPUT_CLOCK * 32 / TIMM_PWM_FREQ = 3400
- 主定时器有四个比较 masterCompareN= period/360*shift
计时器 A 到 D
- 预分频比:HRTIM 时钟乘以 32 -> fHRCK = 5.44E9 Hz
- 每个定时器有一个比较= (masterCompareN + (period/2)) % period
主定时器比较事件将触发相应定时器(例如 A)输出为高电平,定时器 (A) 比较事件会将输出 (A) 设置为低电平。
如果所有偏移均为 8°/70ns,则输出符合预期。低于此阈值(例如 A 移动 5°)有时没有输出。似乎 A 的比较不起作用。
A(红色)2°
B(蓝色)5°
C(绿色)7°
D(黄色)10°
// static void MX_HRTIM1_Init(void)
// Master Timer
LL_HRTIM_TIM_SetPrescaler(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_PRESCALERRATIO_MUL32);
LL_HRTIM_TIM_SetCounterMode(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_MODE_CONTINUOUS);
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_PERIOD);
LL_HRTIM_TIM_SetRepetition(HRTIM1, LL_HRTIM_TIMER_MASTER, 0x00);
LL_HRTIM_TIM_DisableHalfMode(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_SetInterleavedMode(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_INTERLEAVED_MODE_DISABLED);
LL_HRTIM_TIM_DisableStartOnSync(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_DisableResetOnSync(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_SetDACTrig(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_DACTRIG_NONE);
LL_HRTIM_TIM_DisablePreload(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_SetUpdateGating(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_UPDATEGATING_INDEPENDENT);
LL_HRTIM_TIM_SetUpdateTrig(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_UPDATETRIG_NONE);
LL_HRTIM_TIM_SetBurstModeOption(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_BURSTMODE_MAINTAINCLOCK);
LL_HRTIM_ForceUpdate(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_Compare1);
LL_HRTIM_TIM_SetCompare2(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_Compare2);
LL_HRTIM_TIM_SetCompare3(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_Compare3);
LL_HRTIM_TIM_SetCompare4(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_Compare4);
// Timer A
LL_HRTIM_TIM_SetPrescaler(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_PRESCALERRATIO_MUL32);
LL_HRTIM_TIM_SetCounterMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_MODE_CONTINUOUS);
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_A, TIMM_PERIOD);
LL_HRTIM_TIM_SetRepetition(HRTIM1, LL_HRTIM_TIMER_A, 0x00);
LL_HRTIM_TIM_SetUpdateGating(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_UPDATEGATING_INDEPENDENT);
LL_HRTIM_TIM_SetCountingMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_COUNTING_MODE_UP);
LL_HRTIM_TIM_SetComp1Mode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_GTCMP1_GREATER);
LL_HRTIM_TIM_SetDACTrig(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_DACTRIG_NONE);
LL_HRTIM_TIM_DisableHalfMode(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_SetInterleavedMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_INTERLEAVED_MODE_DISABLED);
LL_HRTIM_TIM_DisableStartOnSync(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_DisableResetOnSync(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_DisablePreload(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_DisableResyncUpdate(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_SetUpdateTrig(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_UPDATETRIG_NONE|LL_HRTIM_UPDATETRIG_NONE);
LL_HRTIM_TIM_SetResetTrig(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_RESETTRIG_NONE);
LL_HRTIM_TIM_DisablePushPullMode(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_DisableDeadTime(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_SetBurstModeOption(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_BURSTMODE_MAINTAINCLOCK);
LL_HRTIM_ForceUpdate(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_A, TIMA_Compare1);
LL_HRTIM_OUT_SetPolarity(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_POSITIVE_POLARITY);
LL_HRTIM_OUT_SetOutputSetSrc(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUTPUTSET_MASTERCMP1);
LL_HRTIM_OUT_SetOutputResetSrc(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUTPUTRESET_TIMCMP1);
LL_HRTIM_OUT_SetIdleMode(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_NO_IDLE);
LL_HRTIM_OUT_SetIdleLevel(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_IDLELEVEL_INACTIVE);
LL_HRTIM_OUT_SetFaultState(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_FAULTSTATE_NO_ACTION);
LL_HRTIM_OUT_SetChopperMode(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_CHOPPERMODE_DISABLED);
// Timer B
// Timer C
// Timer D
2021-10-15
Added __disable_irq() to see if the problem is related to reload some register in the timers. Doesn't seem to be the case.
2021-10-15
LL_HRTIM_TIM_SetCompare1() function indicates that the compare value must be above or equal to 3 periods of the fHRTIM clock. fHRTIM is 170 MHz -> 5.88 ns. 3 x 5.88 ns = 17.65 ns
This seems to be the case... 10° (which works) I can measure a delta of about 12+ ns (when the 0° occasionally works)
更新了上面的问题,我想我找到了问题。
查看LL_HRTIM_TIM_SetCompare1()
函数的代码,说明比较值必须大于或等于fHRTIM
时钟的3个周期。
fHRTIM is 170 MHz -> 5.88 ns. 3 x 5.88 ns = 17.65 ns
这似乎是这种情况...10°(有效)我可以测量大约 12+ ns 的增量时间(当 0° 偶尔有效时)
/**
* @brief Set the compare value of the compare unit 1.
* @rmtoll MCMP1R MCMP1 LL_HRTIM_TIM_SetCompare1\n
* CMP1xR CMP1x LL_HRTIM_TIM_SetCompare1
* @param HRTIMx High Resolution Timer instance
* @param Timer This parameter can be one of the following values:
* @arg @ref LL_HRTIM_TIMER_MASTER
* @arg @ref LL_HRTIM_TIMER_A
* @arg @ref LL_HRTIM_TIMER_B
* @arg @ref LL_HRTIM_TIMER_C
* @arg @ref LL_HRTIM_TIMER_D
* @arg @ref LL_HRTIM_TIMER_E
* @arg @ref LL_HRTIM_TIMER_F
* @param CompareValue Compare value must be above or equal to 3
* periods of the fHRTIM clock, that is 0x60 if CKPSC[2:0] = 0,
* 0x30 if CKPSC[2:0] = 1, 0x18 if CKPSC[2:0] = 2,...
* @retval None
*/
__STATIC_INLINE void LL_HRTIM_TIM_SetCompare1(HRTIM_TypeDef *HRTIMx, uint32_t Timer, uint32_t CompareValue)
STM32G474
STM32CubeIDE 1.7.0
我需要实现四个不同的 PWM 通道,它们可以以 5 度的间隔移动(例如 A = 0°,B = 5°,C = 10°,D = 180°)。 PWM 输出占空比为 50%。重要的只是通道之间的转换。
实施:
计时大师
- HRTIM 输入时钟:170 MHz
- 主定时器PWM频率:1.6 MHz
- 预分频比:HRTIM 时钟乘以 32 -> fHRCK = 5.44E9 Hz
- 期间:HRTIM_INPUT_CLOCK * 32 / TIMM_PWM_FREQ = 3400
- 主定时器有四个比较 masterCompareN= period/360*shift
计时器 A 到 D
- 预分频比:HRTIM 时钟乘以 32 -> fHRCK = 5.44E9 Hz
- 每个定时器有一个比较= (masterCompareN + (period/2)) % period
主定时器比较事件将触发相应定时器(例如 A)输出为高电平,定时器 (A) 比较事件会将输出 (A) 设置为低电平。
如果所有偏移均为 8°/70ns,则输出符合预期。低于此阈值(例如 A 移动 5°)有时没有输出。似乎 A 的比较不起作用。
A(红色)2° B(蓝色)5° C(绿色)7° D(黄色)10°
// static void MX_HRTIM1_Init(void)
// Master Timer
LL_HRTIM_TIM_SetPrescaler(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_PRESCALERRATIO_MUL32);
LL_HRTIM_TIM_SetCounterMode(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_MODE_CONTINUOUS);
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_PERIOD);
LL_HRTIM_TIM_SetRepetition(HRTIM1, LL_HRTIM_TIMER_MASTER, 0x00);
LL_HRTIM_TIM_DisableHalfMode(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_SetInterleavedMode(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_INTERLEAVED_MODE_DISABLED);
LL_HRTIM_TIM_DisableStartOnSync(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_DisableResetOnSync(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_SetDACTrig(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_DACTRIG_NONE);
LL_HRTIM_TIM_DisablePreload(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_SetUpdateGating(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_UPDATEGATING_INDEPENDENT);
LL_HRTIM_TIM_SetUpdateTrig(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_UPDATETRIG_NONE);
LL_HRTIM_TIM_SetBurstModeOption(HRTIM1, LL_HRTIM_TIMER_MASTER, LL_HRTIM_BURSTMODE_MAINTAINCLOCK);
LL_HRTIM_ForceUpdate(HRTIM1, LL_HRTIM_TIMER_MASTER);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_Compare1);
LL_HRTIM_TIM_SetCompare2(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_Compare2);
LL_HRTIM_TIM_SetCompare3(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_Compare3);
LL_HRTIM_TIM_SetCompare4(HRTIM1, LL_HRTIM_TIMER_MASTER, TIMM_Compare4);
// Timer A
LL_HRTIM_TIM_SetPrescaler(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_PRESCALERRATIO_MUL32);
LL_HRTIM_TIM_SetCounterMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_MODE_CONTINUOUS);
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_A, TIMM_PERIOD);
LL_HRTIM_TIM_SetRepetition(HRTIM1, LL_HRTIM_TIMER_A, 0x00);
LL_HRTIM_TIM_SetUpdateGating(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_UPDATEGATING_INDEPENDENT);
LL_HRTIM_TIM_SetCountingMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_COUNTING_MODE_UP);
LL_HRTIM_TIM_SetComp1Mode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_GTCMP1_GREATER);
LL_HRTIM_TIM_SetDACTrig(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_DACTRIG_NONE);
LL_HRTIM_TIM_DisableHalfMode(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_SetInterleavedMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_INTERLEAVED_MODE_DISABLED);
LL_HRTIM_TIM_DisableStartOnSync(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_DisableResetOnSync(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_DisablePreload(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_DisableResyncUpdate(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_SetUpdateTrig(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_UPDATETRIG_NONE|LL_HRTIM_UPDATETRIG_NONE);
LL_HRTIM_TIM_SetResetTrig(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_RESETTRIG_NONE);
LL_HRTIM_TIM_DisablePushPullMode(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_DisableDeadTime(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_SetBurstModeOption(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_BURSTMODE_MAINTAINCLOCK);
LL_HRTIM_ForceUpdate(HRTIM1, LL_HRTIM_TIMER_A);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_A, TIMA_Compare1);
LL_HRTIM_OUT_SetPolarity(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_POSITIVE_POLARITY);
LL_HRTIM_OUT_SetOutputSetSrc(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUTPUTSET_MASTERCMP1);
LL_HRTIM_OUT_SetOutputResetSrc(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUTPUTRESET_TIMCMP1);
LL_HRTIM_OUT_SetIdleMode(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_NO_IDLE);
LL_HRTIM_OUT_SetIdleLevel(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_IDLELEVEL_INACTIVE);
LL_HRTIM_OUT_SetFaultState(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_FAULTSTATE_NO_ACTION);
LL_HRTIM_OUT_SetChopperMode(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_CHOPPERMODE_DISABLED);
// Timer B
// Timer C
// Timer D
2021-10-15 Added __disable_irq() to see if the problem is related to reload some register in the timers. Doesn't seem to be the case.
2021-10-15 LL_HRTIM_TIM_SetCompare1() function indicates that the compare value must be above or equal to 3 periods of the fHRTIM clock. fHRTIM is 170 MHz -> 5.88 ns. 3 x 5.88 ns = 17.65 ns This seems to be the case... 10° (which works) I can measure a delta of about 12+ ns (when the 0° occasionally works)
更新了上面的问题,我想我找到了问题。
查看LL_HRTIM_TIM_SetCompare1()
函数的代码,说明比较值必须大于或等于fHRTIM
时钟的3个周期。
fHRTIM is 170 MHz -> 5.88 ns. 3 x 5.88 ns = 17.65 ns
这似乎是这种情况...10°(有效)我可以测量大约 12+ ns 的增量时间(当 0° 偶尔有效时)
/**
* @brief Set the compare value of the compare unit 1.
* @rmtoll MCMP1R MCMP1 LL_HRTIM_TIM_SetCompare1\n
* CMP1xR CMP1x LL_HRTIM_TIM_SetCompare1
* @param HRTIMx High Resolution Timer instance
* @param Timer This parameter can be one of the following values:
* @arg @ref LL_HRTIM_TIMER_MASTER
* @arg @ref LL_HRTIM_TIMER_A
* @arg @ref LL_HRTIM_TIMER_B
* @arg @ref LL_HRTIM_TIMER_C
* @arg @ref LL_HRTIM_TIMER_D
* @arg @ref LL_HRTIM_TIMER_E
* @arg @ref LL_HRTIM_TIMER_F
* @param CompareValue Compare value must be above or equal to 3
* periods of the fHRTIM clock, that is 0x60 if CKPSC[2:0] = 0,
* 0x30 if CKPSC[2:0] = 1, 0x18 if CKPSC[2:0] = 2,...
* @retval None
*/
__STATIC_INLINE void LL_HRTIM_TIM_SetCompare1(HRTIM_TypeDef *HRTIMx, uint32_t Timer, uint32_t CompareValue)