PWM应用笔记

1. PWM驱动说明

1.1 简介

PWM(脉冲宽度调制)应用场景广泛,思澈平台支持输出PWM的定时器类型包括 GPTIM(通用定时器)ATIM(高级定时器)LPTIM(低功耗定时器),其中GPTIM PWM因通用性强,优先推荐使用。

1.1.1 PWM列表及归属核

PWM名称

归属核心

PWM 2、PWM 3、PWM A1、PWM A2、PWM LPTIM1

HCPU

PWM 4、PWM 5、PWM 6、PWM LPTIM2、PWM LPTIM3

LCPU

备注

PWM 2~PWM 6: 与GPTIM存在固定对应关系

  • PWM 2对应GPTIM1、

  • PWM 3对应GPTIM2

  • PWM 6对应GPTIM5

1.2 PWM在52x/55x/56x/58x的差异

不同系列芯片的PWM特性存在两点核心差异,需根据具体型号针对性配置:

1.2.1 IO口灵活性差异

  • 55x/58x系列:输出PWM的IO口为固定分配,需参考芯片规格书确认具体IO对应的PWM通道,不可随意切换;

  • 52x/56x系列:灵活性更高,任何带有TIM(定时器)功能的IO,均可通过配置映射为任意一种PWM输出,无需受固定通道限制。

规格对比参考图:

../../_images/PWM_IO.png

1.2.2 HCPU 自动降频的影响

当系统宏 BSP_PM_FREQ_SCALING 开启时,HCPU(大核)会根据系统负载自动降低运行主频以节省功耗。此机制会间接影响 HCPU 管辖的 IO 输出的 PWM 频率——由于 PWM 时钟源与 HCPU 主频关联,主频降低时,PWM 频率会同步下降,可能导致依赖稳定频率的设备(如马达、背光)工作异常。

针对不同芯片系列,解决方案如下:

  • 55x/56x/58x 系列
    优先选择 LCPU(小核)的 IO 输出 PWM。LCPU 的 PWM 时钟源独立于 HCPU 主频,频率不受 HCPU 降频影响,可保证输出稳定。
    若因硬件限制必须使用 HCPU 的 IO,需关闭宏 BSP_PM_FREQ_SCALING(关闭自动降频),但此操作会导致亮屏等场景下功耗升高。

  • 52x 系列
    若使用 HCPU 的 IO 输出 PWM,建议优先选择 GPTIM2 对应的 PWM。GPTIM2 的时钟源设计特殊,不受系统主频变化影响,可在 HCPU 降频时保持 PWM 频率稳定。

1.3. PWM 使用步骤

PWM的使用需经过配置选型、硬件绑定、参数设置和驱动调用四个核心步骤,以下为详细说明:

1.3.2 配置 Pinmux(绑定 IO 与 PWM 通道)

Pinmux 配置的核心作用是建立物理 IO 引脚与目标 PWM 通道的硬件映射关系,告知芯片“哪个 IO 负责输出哪个 PWM 信号”。只有完成绑定,PWM 定时器产生的波形才能通过指定 IO 输出到外部设备(如马达、背光电路)。

  • 配置逻辑与示例 以“PA20 引脚使用 PWM2(对应 GPTIM2_CH1 通道)”为例,配置代码如下:

// 函数:HAL_PIN_Set(引脚标识, 功能别名, 上下拉配置, 功能使能)
HAL_PIN_Set(
    PAD_PA20,       // 物理 IO 引脚(如 PA20)
    GPTIM2_CH1,     // PWM 通道(PWM2 对应 GPTIM1,此处 GPTIM2_CH1 对应 PWM3,需按实际映射调整)
    PIN_NOPULL,     // 上下拉配置(PWM 输出一般无需上下拉,避免信号冲突)
    1               // 功能使能(1=启用该 IO 的 PWM 功能,0=禁用)
);

1.3.3 配置应用的PWM参数

在应用层配置PWM的通道、周期(频率)、占空比等参数,适配目标设备(如马达)。以“马达使用PA20作为PWM(GPTIM2)的通道1”为例,配置界面如下:

../../_images/PWM_MOTOR.png

1.3.4 调用PWM驱动接口

通过RT-Thread接口完成PWM初始化与控制,核心流程如下:

../../_images/PWM_USE_FLOW.png

参考代码:

// 查找PWM设备("pwm1"对应PWM2)
struct rt_device_pwm *pwm_device = (struct rt_device_pwm *)rt_device_find("pwm1");
// 设置参数(通道1,周期period,占空比pulse)
rt_pwm_set(pwm_device, 1, period, pulse);
// 使能输出
rt_pwm_enable(pwm_device, 1);
// (按需)禁用输出
// rt_pwm_disable(pwm_device, 1);

PWM通道复用规则(避免冲突):

  1. 同一PWM的不同通道,可输出相同频率、不同占空比的波形(如马达和光感可共用同一PWM的不同通道);

  2. 同一PWM的不同通道若频率不同,需确保设备分时使用(如马达和蜂鸣器不同时工作),否则会相互干扰;

  3. 需持续工作且频率不同的设备(如背光),需单独分配PWM,不可复用。

1.4 PWM 停止后的电平控制

PWM停止是指PWM不再输出波形,而保持为低电平或高电平状态。

  • 一般情况下,rt_pwm_disable执行后,PWM通道处于高阻状态,电平无法立刻到低电平,波形如下:

../../_images/PWM_stop0.png
  • 若需实现 “停止后固定电平”(如下方波形),可通过配置占空比实现:

../../_images/PWM_stop1.png

可通过配置占空比为0的方式实现。

备注

  • 配置占空比为0% → 输出低电平

  • 配置占空比为100% → 输出高电平

1.5 如何添加一个PWM马达

添加PWM马达的步骤如下:

1.5.2 配置pinmux及使能PWM设备

  • 配置马达对应的pinmux,绑定物理引脚与PWM通道;

  • 确保步骤5.1中配置的PWM设备已使能。

1.5.3 调用应用层接口

Solution封装了以下应用层接口:

接口函数

功能说明

motor_power_on

马达初始化(电源使能)

motor_start

马达开启(默认配置)

motor_stop

马达停止

app_motor_get_level

获取当前占空比

app_motor_set_level

设置占空比

一般使用流程:
motor_power_onmotor_startmotor_stop

修改占空比:
app_motor_set_level

备注

硬件支持实时修改占空比,无需先停止马达再调整,可提高占空比平滑性,避免蜂鸣器等器件切换时的噪声。

1.6 如何实现LCD背光使用PWM

LCD背光使用PWM的步骤如下:

1.6.1 修改LCD的Kconfig文件

打开文件\solution2_0\sdk\customer\boards\Kconfig_lcd,找到对应的LCD配置,添加支持PWM背光的代码:

../../_images/LCD_PWM_EN.png

1.6.2 修改Board的Kconfig文件

eh_lb523为例,修改对应开发板下的Kconfig文件,配置背光PWM参数:

../../_images/LCD_PWM_CONFIG.png

1.6.3 确认pinmux与PWM使能

  • 确保背光使用的PWM引脚已正确配置pinmux;

  • 确认PWM设备处于使能状态。

1.6.4 添加背光亮度控制代码

在LCD的背光接口中,增加使用PWM调整亮度的逻辑,参考代码:

void  xxx_SetBrightness(LCDC_HandleTypeDef *hlcdc, uint8_t br)
{
    rt_device_t device = rt_device_find("lcdlight");
    if (device)
    {
        rt_err_t err = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
        uint8_t val = br;
        rt_device_write(device, 0, &val, 1);
        rt_device_close(device);
    }
    else
    {
        LOG_E("Can't find device lcdlight!");
    }
    LOG_I("XXX_SetBrightness\r\n");
}

若LCD驱动运行在HCPU,而背光PWM使用LCPU的IO,需修改 drv_common.c 中的 HAL_RCC_MspInit() 函数,注释掉背光PWM对应的RCC_Module,避免资源冲突,界面如下:

../../_images/LCD_PWM_MSP_INIT.png

2. 如何在睡眠情况下输出PWM

睡眠状态下输出PWM,需依赖LCPU的LPTIM3(低功耗定时器),配置步骤如下:

2.2 配置 LPTIM3 对应的 Pinmux

LPTIM3 常用 IO 为 PB43~PB46,以 PB44 为例,配置代码如下:

// 1. 绑定PB44与LPTIM3_OUT,无上下拉,使能功能
HAL_PIN_Set(PAD_PB44, LPTIM3_OUT, PIN_NOPULL, 0);
// 2. 配置PB44的MUX选择LPTIM3输出
MODIFY_REG(hwp_lpsys_aon->DBGMUX, LPSYS_AON_DBGMUX_PB44_SEL_Msk,
           MAKE_REG_VAL(1, LPSYS_AON_DBGMUX_PB44_SEL_Msk, LPSYS_AON_DBGMUX_PB44_SEL_Pos));

2.3 使能睡眠输出宏

在 menuconfig 中勾选宏 PM_WAKEUP_PIN_AS_OUTPUT_IN_SLEEP,确保唤醒源 IO 在睡眠时可继续输出 PWM,界面如下:

../../_images/PWM_LPTIM3_SLEEP.png

注意

  • PM_WAKEUP_PIN_AS_OUTPUT_IN_SLEEP 对所有唤醒源IO生效,需确保其他PB唤醒IO在硬件上已固定上下拉(避免睡眠时漏电)。

2.4 调用 LPTIM3 PWM 接口

参考代码如下:

// 查找LPTIM3 PWM设备("pwmlp3"为LPTIM3的设备名)
struct rt_device_pwm *pwm_device = (struct rt_device_pwm *)rt_device_find("pwmlp3");
// 设置PWM参数(通道1,周期period,脉冲宽度pulse)
rt_pwm_set(pwm_device, 1, period, pulse);
// 使能PWM输出(睡眠时持续生效)
rt_pwm_enable(pwm_device, 1);