PWM 实战

本篇目标:理解 PWM 是什么,并用手头的 sysfs 接口输出一个可调占空比的方波。典型用途:调 LCD 背光亮度、控速风扇/电机、蜂鸣器发声。


什么是 PWM

PWM(脉冲宽度调制)= 让一个引脚高速地在高/低之间翻转,并通过改变”高电平持续时间占整个周期的比例”(占空比)来等效控制”平均电压/功率”。

  • 周期 period:一个完整高低循环的时间(纳秒 ns)。频率 = 1/period。
  • 占空比 duty_cycle:高电平持续的时间(ns)。占空比 = duty_cycle / period。
  • 例:period=1000ns(1MHz),duty=500ns → 50% 占空比,平均电压约为一半。

背光就是靠改占空比来调亮度的:占空比越大越亮。


板子的 PWM 资源

ypt153evb 的使用了多个 pwm 控制器。出厂设备树里:

  • pwm2_7,对应引脚 PD23,专门用于背光,配置为 pwms = <&pwm2 7 25000 1>(周期 25000ns = 40kHz)。
  • pwmcs0_4, 对应引脚 PB13,作为 cpu 调频接口
  • pwmcs0_0, 对应引脚 PB8,未使用,排针区域引出

ypt153evb 可用的 PWM 控制器 pwmcs0(寄存器基址 0x20a0000)。有 8 个通道 pwmcs0_0 ~ pwmcs0_7


第一步:配置设备树

device/config/chips/t153/configs/t153_nand_base/linux-5.10-origin/board.dts 下找到 pwmcs0_0 启用并配置 PB8 引脚

pwmcs0_0_pins_active: pwmcs0_0@0 {
        pins = "PB8";
        function = "pwm0_0";
        drive-strength = <20>;
    };

    pwmcs0_0_pins_sleep: pwmcs0_0@1 {
        pins = "PB8";
        function = "gpio_in";
        bias-pull-down;
    };
...
&pwmcs0_0 {
    pinctrl-names = "active", "sleep";
    pinctrl-0 = <&pwmcs0_0_pins_active>;
    pinctrl-1 = <&pwmcs0_0_pins_sleep>;
    status = "okay";
};

重新编译内核并烧录(见底层篇《系统编译》)。

第二步:找到 PWM 控制器

# ls /sys/class/pwm/
pwmchip0   pwmchip16  pwmchip8

每个 pwmchipN 代表一个 PWM 控制器。先确认它有多少通道:

# cat /sys/class/pwm/pwmchip0/npwm
8

第三步:导出通道并输出

以控制背光通道 0(PB8)为例:

# 1. 导出通道 0(首次使用才需要,导出后会在 pwmchip0 下出现 pwm0 目录)
echo 0 > /sys/class/pwm/pwmchip0/export
cd /sys/class/pwm/pwmchip0/pwm0

# 2. 设置周期,单位是纳秒
echo 1000000 > period

# 3. 设置占空比,单位是纳秒,必须 <= period
echo 500000 > duty_cycle

# 4. 使能输出
echo 1 > enable

连接示波器检查 PB8 的 pwm 输出

pwm0 目录下常用文件:

文件 含义
period 周期(ns),写时须 ≥ duty_cycle
duty_cycle 占空比(ns),须 ≤ period
enable 1=输出,0=关闭
polarity 极性(normal/inversed),一般不动

写 period 和 duty_cycle 的顺序:先写 period,再写 duty_cycle,且 duty_cycle 不能超过 period,否则写会报参数错误。


排障

现象 处理
/sys/class/pwm/ 为空 内核未启用 pwm;确认设备树 &pwmcs status=okay
export 后没有 pwmX 目录 通道号超出 npwm 范围;确认 cat npwm
写 duty_cycle 报 Invalid argument duty_cycle > period;先设 period 再设 duty

下一篇

附:真实设备树片段(PWM / 背光)

来自基础层 board-base.dtsi 的真实节点,印证上面的资源说明:

backlight0: backlight0 {
    compatible = "pwm-backlight";
    status = "okay";
    default-brightness-level = <180>;
    enable-gpios = <&pio PD 22 GPIO_ACTIVE_HIGH>;
    pwms = <&pwm2 7 25000 1>;     // 通道7,周期25000ns(40kHz),极性1
};

&pwm2 { status = "okay"; };        // PWM 控制器(14 通道)
&pwm2_7 {
    pinctrl-0 = <&pwm2_7_pins_active>;
    pinctrl-1 = <&pwm2_7_pins_sleep>;
    status = "okay";
};
pwm2_7_pins_active: pwm2_7@0 { pins = "PD23"; function = "pwm2_7"; };

《UART 串口实战》:除了调试串口,板子还有 ttyAS2 用户串口,怎么接线、用 microcom 收发、做回环测试。

作者:Mai  创建时间:2026-10-20 16:47
最后编辑:陈柏林  更新时间:2026-11-05 14:56
上一篇:
下一篇: