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输出,无需受固定通道限制。
规格对比参考图:
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”为例,配置界面如下:
1.3.4 调用PWM驱动接口¶
通过RT-Thread接口完成PWM初始化与控制,核心流程如下:
参考代码:
// 查找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通道复用规则(避免冲突):
同一PWM的不同通道,可输出相同频率、不同占空比的波形(如马达和光感可共用同一PWM的不同通道);
同一PWM的不同通道若频率不同,需确保设备分时使用(如马达和蜂鸣器不同时工作),否则会相互干扰;
需持续工作且频率不同的设备(如背光),需单独分配PWM,不可复用。
1.4 PWM 停止后的电平控制¶
PWM停止是指PWM不再输出波形,而保持为低电平或高电平状态。
一般情况下,
rt_pwm_disable执行后,PWM通道处于高阻状态,电平无法立刻到低电平,波形如下:
若需实现 “停止后固定电平”(如下方波形),可通过配置占空比实现:
可通过配置占空比为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_set_level
备注
硬件支持实时修改占空比,无需先停止马达再调整,可提高占空比平滑性,避免蜂鸣器等器件切换时的噪声。
1.6 如何实现LCD背光使用PWM¶
LCD背光使用PWM的步骤如下:
1.6.1 修改LCD的Kconfig文件¶
打开文件\solution2_0\sdk\customer\boards\Kconfig_lcd,找到对应的LCD配置,添加支持PWM背光的代码:
1.6.2 修改Board的Kconfig文件¶
以eh_lb523为例,修改对应开发板下的Kconfig文件,配置背光PWM参数:
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,避免资源冲突,界面如下:
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,界面如下:
注意:
宏
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);


