ST意法半导体
直播中

yqdedli

8年用户 885经验值
擅长:控制/MCU
私信 关注
[问答]

还有什么比仅使用HAL输出一个正定时器脉冲更简单的呢?

我开发嵌入式软件开关 15 年,STM32 5 年。我对 WB55 微控制器上的计时器应用程序有一个非常简单的目标,过去 2 天我一直在努力,但收效甚微,所以我问社区是否缺少一些简单的东西。
我正在尝试在 STM32WB55 上使用定时器 16 和定时器 17,以便每个软件调用输出一个脉冲。这是一个非常典型的伺服 PWM 控制应用,其中每 20 毫秒需要一个 1.0 毫秒到 2.0 毫秒的正脉冲。我正在使用我自己的硬实时调度程序来驱动控制回路,当软件计算出所需的脉冲持续时间时,我想在计算完成后以最小延迟输出脉冲。这意味着我不想使用连续定时器 PWM 并动态调整脉冲宽度,因为如果我的软件调度漂移与 PWM 周期不同步,则在更新脉冲之前可能会有长达 20 毫秒的延迟持续时间传到伺服系统。相反,我只是希望我的软件在确定所需的脉冲持续时间后立即命令一个脉冲,
我正在使用 MXCube 和 HAL。如果需要,我会去找 LL 驱动程序,但这意味着在我的应用程序的其他地方重新编写工作代码,所以这是最后的手段。此外,还有什么比仅使用 HAL 输出一个正定时器脉冲更简单的呢?
我最直接的尝试是在单脉冲模式下使用 PWM 模式 1,将所需的脉冲持续时间设置为 1.5 毫秒,并将自动重载值设置为 4 毫秒,这超过了 3 毫秒的最大可能脉冲宽度。问题是定时器输出以 1.5 毫秒的脉冲开始时很好,但是当 ARR 到期时,输出再次变高。

然后信号保持高电平,直到我使用带有 HAL_tiM_PWM_Stop 命令的软件进入。我一直无法找到任何防止信号在 ARR 周期结束时变高的寄存器设置。
如果我尝试在信号低但 ARR 到期之前发送 HAL_TIM_PWM_Stop 命令,那么出于某种原因,接下来的几次尝试重新启动定时器都没有效果。
我也尝试过使用输出比较模式选择一个脉冲,但出于某种原因,每次系统复位它只适用于一个脉冲。我深入研究了定时器寄存器以比较它们在初始成功脉冲和下一个失败脉冲命令之间的差异,并且在成功脉冲打开后的那一刻,当失败命令没有打开时,所有 Timer16 寄存器的寄存器值都是相同的. BDTR->MOE 对它们都打开,依此类推,但在第一种情况下,输出变高,而在所有后续情况下,输出保持平坦。我不知道如何解决这个问题。
我能够得到我想要的最接近的是使用 PWM 模式 2 并反转输出极性,这样定时器输出开始时为低电平,然后打开一个 ARR - CCR 持续时间的脉冲,CCR 为潜伏。要在每个软件周期更新脉冲,我需要每次都更改 ARR 和 CCR,并且在脉冲消失之前我将至少有一个不需要的延迟计时器计数。如果需要,我会回到这个,但它似乎不必要地低效。   
我错过了什么?在此先感谢您的帮助。



回帖(1)

林霆景

2022-12-2 15:29:34
> 我错过了什么?
阅读 RM 中的 TIM 章节。
PWM 模式意味着每个周期有两次转换,都在时间上提前:一次在 CNT 匹配 CCR,另一个在 CNT 匹配 ARR。
具有反相输出的 PWM 模式 1 和 PWM 模式 2 实际上是相同的,只要它是单输出定时器通道,所以你不会有任何变化。
当你读到“单脉冲模式”时,你的想法是,当你“启动”定时器时,它的输出将自动变为 1,当 CNT 匹配 CCR 时,它会归零。这是那些在没有真正阅读手册的情况下使用 CubeMX 的人的常见误解。一种脉冲模式(即设置 TIMx_CR1.OPM)不会改变输出的行为方式——这就是我在上面写的以及 RM 中非常清楚地描述的内容——只是 CNT 在达到 ARR 和零时自动停止。
所以,如果你*想*在计数器开始时有一个转换,你必须以某种方式进行转换。那么,问问自己,“开始”到底是什么?它可能正在设置 TIMx_CR1.CEN,不是吗?无论如何,那是软件。所以你也可以做额外的步骤。手动将输出设置为给定电平的一种方法是将给定通道设置为强制高电平,然后再次将 PWM 设置回原位。是的,如果可以中断此过程,那可能会导致精度损失。
或者只是简单地接受从“开始”开始的一个周期延迟。我不明白为什么您需要更改两个值来更改脉冲长度:您只需要设置 ARR,将 CCR 保留为 1。您希望为此关闭 ARR 预加载 (TIMx_CR1.ARPE=0)。
或者保持 ARR 不变,仅更改 CCR 并接受脉冲的后沿有规律地间隔开的事实,而不是前沿。你的伺服很可能不在乎。
或者不要强迫你的调度想法,运行正常的连续PWM并在该定时器的更新中断中执行占空比(即下一个CCR值)计算。一定要设置 CCR 预加载,这样你就有了一个完整的定时器周期来计算下一个周期。
> 我正在使用 MXCube 和 HAL。如果需要,我会去找 LL 驱动程序,但这意味着重写工作
> 在我的应用程序的其他地方编写代码,所以这是最后的手段。此外,有什么比仅仅更简单的呢?
> 使用 HAL 输出一个正定时器脉冲?
直接使用寄存器。足够简单,直接映射到手册。有什么能比完全按照手册描述运行的程序更简单呢?
举报

更多回帖

发帖
×
20
完善资料,
赚取积分