摘要
在 NUCLEO-H563ZI 上,LPTIM 更新事件经 GPDMA 块请求(BREQ=1)一次写完 PWM 相关寄存器,无需 CPU。其他支持 LPTIM BREQ 的产品可裁着用。
引言
要在 STM32H563(或任何支持该功能的控制器)上用 LPTIM 做 GPDMA 硬件块请求,可看本文。搭建时用的软件版本:
- STM32CubeIDE 2.1.0
- STM32CubeMX 6.17.0
- STM32CubeH5 1.5.1
1. 定义硬件块请求功能
LPTIM 更新事件 DMA 请求是一种 GPDMA 块请求:一次硬件触发里,把与 PWM 相关的定时器寄存器更新完。使能后,DMA 最多对低功耗定时器做三次单次写:目标最多是 LPTIMx_CCR1、LPTIMx_CCR2、LPTIMx_RCR 里的两个,最后必须写 LPTIMx_ARR 来更新 PWM 周期。
这套机制靠 LPTIM 与 GPDMA 之间的专用硬件请求连接。所选 GPDMA 通道通常配成 BREQ = 1、SWREQ = 0。这时请求按块处理:一次 LPTIM 更新事件就能触发完整寄存器更新序列,不用 CPU 插手。
要走基于块的传输,用带 2D 能力的 GPDMA 通道。CxBR1 定义块重复计数与方向,CxBR2 定义步进寄存器序列时的源/目的地址偏移。
BREQ 与 SWREQ 简要说明
- BREQ = 0:硬件请求按突发(burst)级处理
- BREQ = 1:硬件请求按块(block)级处理
因此,对 LPTIM HRWBREQ,BREQ = 1 表示外设请求在**完整块传输**结束时消耗一次,而非每个突发一次。
- SWREQ = 1:通道由软件请求启动(存储器到存储器)
- SWREQ = 0:不处于软件请求模式,硬件请求路径有效
对本用例,SWREQ 必须为 0,以便 LPTIM 硬件事件驱动 GPDMA 传输。
2. 开发
本工程目标:在通道 2 上出 LPTIM PWM,起始周期 100 µs、占空比 50%。一秒后,用 LPTIM 硬件块请求先改 CCR2、再改 ARR,把周期变成 1 ms 并保持 50% 占空比,用来演示 PWM 变化。
2.1 工程配置
在 STM32CubeMX 中通过 [File -> New -> STM32 Project] 新建工程。使用 [Board Selector] 选择 [Nucleo-H563]。
创建完成后,使能 LPTIM1(counts internal trigger mode),并启用第二通道,CH2 I/O 用法为 output。
在 “Parameter Settings” 中选择 Prescaler Div128;将 “Period” 设为 99;将 “Pulse Value” 设为 50。
- 在 system core 下的 GPDMA1 中,使能 Channel 6 为 “Standard Request Mode”
- Request Configuration:Request = LPTIM1_UE
- Channel Configuration:Direction 设为 Peripheral to Memory(CubeMX 界面选项;实际 DMA 启动从内存 NewValues 写向 LPTIM 寄存器)
- Source Data Setting:Source Address Increment After Transfer = Enabled;Data Width = Half Word
- Destination Data Setting:Destination Address Increment After Transfer = Enabled;Data Width = Half Word
- 最后使能 2D Addressing
时钟配置中确保 LPTIM1 为 128 MHz,以与所选预分频对齐。
命名工程并生成代码。
本例用直接寄存器访问说明各行作用。在 `main.c` 中加入:
```c
/* USER CODE BEGIN PV */
static uint16_t NewValues[2] = {500, 999};
/* USER CODE END PV */
```
```c
/* USER CODE BEGIN 2 */
/* Start PWM on LPTIM channel 2 with interrupt support */
HAL_LPTIM_PWM_Start_IT(&hlptim1, LPTIM_CHANNEL_2);
/* wait 1 second before applying the DMA update to visualize the changes */
HAL_Delay(1000);
/* configure GPDMA CBR1: clear selected bits; set DDEC = 1 (destination decrements by programmed offset) */
MODIFY_REG(GPDMA1_Channel6->CBR1,
DMA_CBR1_DDEC | DMA_CBR1_SDEC |
DMA_CBR1_BRDDEC | DMA_CBR1_BRSDEC |
DMA_CBR1_BRC,
DMA_CBR1_DDEC);
/* configure CTR3: destination address offset; here backward step */
MODIFY_REG(GPDMA1_Channel6->CTR3, DMA_CTR3_DAO | DMA_CTR3_SAO,
(0x1EU << DMA_CTR3_DAO_Pos));
/* Start DMA: source NewValues; destination LPTIM1 CCR2; length 4 transfers */
if (HAL_DMA_Start(&handle_GPDMA1_Channel6,
(uint32_t)NewValues,
(uint32_t)&LPTIM1->CCR2,
4U) != HAL_OK)
{
Error_Handler();
}
/* Enable LPTIM update-event DMA request */
__HAL_LPTIM_ENABLE_DMA(&hlptim1, LPTIM_DMA_UPDATE);
/* USER CODE END 2 */
```
3. 结果
用逻辑分析仪或示波器观察时,CCR 与 ARR 在同一次同步 DMA 事件中变化。本例可观察来自 PG14 的信号。
打开 memory map 视图可见:在调用
```c
__HAL_LPTIM_ENABLE_DMA(&hlptim1, LPTIM_DMA_UPDATE);
```
之前,LPTIM1_CCR2(地址 0x44004434)与 LPTIM1_ARR(地址 0x44004418)分别保持 0x63 与 0x32,对应十进制 99 与 50。
> **脚注(寄存器与 CubeMX 字段对应):** CubeMX Parameter Settings 中 “Period”=99、“Pulse Value”=50;Results 内存转储显示 LPTIM1_CCR2=0x63(99)、LPTIM1_ARR=0x32(50)。引用时应按 **ARR = Period、CCR = Pulse** 理解,勿盲目对调源站 Results 中的寄存器名与 UI 字段。
调用上述宏之后:LPTIM1_CCR2 为 0x1F4(500),LPTIM1_ARR 为 0x3E7(999)。
结论
到这里,在 STM32H563 上用 LPTIM 做 GPDMA 硬件块请求所需信息已经齐了。
来源:https://community.st.com/stm32-mcus-60/how-to-implement-the-gpdma-hardware-block-request-feature-using-lptim-in-stm32h563-168812
参数以意法半导体官方最新资料为准。
49
