PWM输出
1. 本节介绍
📝本节您将学习如何通过将GPIO引脚复用为PWM功能并输出PWM信号;实现输出PWM信号及控制板载LED的亮度。
🏆学习目标
1️⃣如何将GPIO引脚配置为PWM模式,通过排针中的部分引脚来输出PWM信号,控制其频率和占空比。
2️⃣如何通过PWM驱动板载的LED灯,实现控制LED灯的亮度。
2. PWM介绍
PWM(Pulse Width Modulation,脉宽调制)是一种在嵌入式系统中常用的技术,它可以用来 模拟信号
,控制设备的功率输出 或者 实现对设备的精确控制。
PWM信号是一种类似于方波的信号,具有 固定的频率
,但脉冲宽度(占空比)可以调整。在一定频率下,我们可以通过调整这个占空比来改变它的有效电压,在一定程度上可以实现D/A转换(数字量转模拟量)。
脉宽调制说明(点击展开)
脉冲宽度调制(PWM)是一种通过改变脉冲的宽度(脉宽/占空比)来控制电信号平均功率的技术。在PWM中,脉冲的频率一般保持恒定,但脉冲的宽度(有效电平的时间)根据需要的模拟信号变化,从而实现对电机速度、LED调光和温度控制等的精确控制。
举个例子
想象你有一个 LED 和一个开关,你以肉眼看不清的速度,快速反复地开关一次,这样 LED 灯就会亮一半时间,暗一半时间。如果你快速地进行这个操作,对于观察者来说, LED 就像是以半亮度持续亮着。这就是 PWM 的基本原理。
如果你把大部分时间保持开关为关闭状态,那么 LED 会显得更暗;相反,如果你把开关大部分时间保持为打开状态,LED 会显得更亮。这就是 PWM 调节占空比来控制亮度的过程。
3. RP2350的PWM介绍
RP2350一共有12个PWM,但是我们的型号是RP2350A,只有8个PWM。每一个 PWM 支持两个通道,所以在RP2350A上我们可以使用 16 个通道的PWM。
RP2350的每一个引脚都支持PWM功能,所以无需考虑引脚问题。
![]() | ![]() |
---|---|
PWM参数列表
- 16位计数器
- 8.4位的分频器(8位整数4位小数)
- 每一个PWM有两个独立通道,每一个通道支持0 ~ 100%的占空比
- 支持电平边缘检测功能,用于测量输入信号的频率
- 支持电平维持检测功能,用于测量输入信号的占空比
- 可随时配置的PWM计数值(即使PWM正在运行也可修改参数)
- 支持PWM通道的中断请求和DMA请求
PWM的实现方式
PWM是基于计数器的运行来实现的。该计数器默认为向上计数,即从0开始计算,直到计数值的最大值。(该最大值为65536,因为是16位的计数器)。
我们一共要设置两个参数,
最大值
和比较值
。PWM硬件外设不断的将设置的比较值 与 当前运行的计数器数值进行比较,当计数器的当前值低于比较值,则PWM输出为高电平;
当计数器的当前值高于比较值,则PWM输出为低电平;
PWM的输出周期 T 由计数器的最高值 和 计数器计数的速度决定的。
而PWM的输出电压默认为IOVDD,即3.3V。(有时候你用万用表去测量PWM信号发现并不是3.3V是因为万用表的采集精度是不够的,在PWM的高频率下,万用表采集是数据是不可靠的)
![]() |
---|
4. PWM在Mpy的使用方式
使用machine.PWM
在MicroPython中,使用 machine.PWM
模块可以方便地操作RP2350的PWM功能。使用时需要导入该模块。
from machine import PWM
构造函数
machine.PWM(dest, \*, freq, duty_u16, duty_ns)
参数说明
dest:
输出 PWM 的实体,通常是 machine.Pin 对象,简单来说就是要设置的引脚号。freq:
用于设置 PWM 周期的频率(以 Hz 为单位),整数。duty_u16:
以计数器角度设置占空比(%)为 duty_u16 / 65535。例如要设置50%的占空比,则填入32768。duty_ns:
以时间角度设置占空比,以纳秒为单位设置。
注意,一个PWM有两个通道,两个通道的PWM频率是同时调整的,不能单独设置。
示例:
from machine import PWM, Pin
# 设置GPIO25为PWM功能 频率50Hz 占空比8192/65535=0.125=12.5%
pwm = PWM(Pin(25), freq=50, duty_u16=8192)
2
3
方法总结
重新初始化配置
PWM.init(*, freq, duty_u16, duty_ns)
使用给定的参数初始化 PWM
对象。其他跟 PWM 构造函数基本一致.
禁止PWM输出
PWM.deinit()
禁用 PWM 输出。使用后需要重新创建 PWM 对象。
获取或设置 PWM 频率
PWM.freq([value])
获取或设置 PWM 输出的当前频率。
不带参数 value 时返回以 Hz 为单位的频率。使用单个值参数value 将频率设置为该值(以 Hz 为单位)。如果设置的范围超过最大值则会报错ValueError
。
获取或设置 PWM 输出的当前占空比
PWM.duty_u16([value])
获取或设置 PWM 输出的当前占空比。( 0 到 65535 范围内的无符号 16 位值)
没有参数时返回当前占空比值。
value 使用单个值参数,占空比则设置为该值,实际占空比请以 value / 65535 进行计算。
获取或设置 PWM 输出的当前脉冲宽度
PWM.duty_ns([value])
获取或设置 PWM 输出的当前脉冲宽度,以纳秒为单位。
不带参数返回以纳秒为单位的脉冲宽度。
使用单个值参数,脉冲宽度设置为该值。
5. PWM输出实验
🏆学习目标
1️⃣如何将GPIO引脚配置为PWM模式,通过排针中的部分引脚来输出PWM信号,控制其频率和占空比。
2️⃣如何通过PWM驱动板载的LED灯,实现控制LED灯的亮度。
代码验证
将GPIO0引脚配置为PWM模式,控制其频率为 50 Hz 和 50% 占空比。
from machine import Pin, PWM
# 将GPIO0引脚配置为PWM输出
pwm = PWM(Pin(0))
# 设置PWM频率为50 Hz
pwm.freq(50)
# 设置占空比为50%
pwm.duty_u16(32768) # 65535的50%是32768
2
3
4
5
6
7
8
9
10
效果:
![]() | ![]() |
---|---|
通过PWM驱动板载的LED灯,实现控制LED灯的亮度。
from machine import Pin, PWM
import time
# 将GPIO25引脚配置为PWM输出 频率为1000 Hz
led = PWM(Pin(25), freq=1000)
while(True):
# 呼吸灯渐亮过程
for i in range(1000):
# 设置LED亮度,占空比范围为0到65535,因此需要将i放大
led.duty_u16(i * 65)
time.sleep_ms(1) # 延迟以控制亮度变化速度
# 呼吸灯渐暗过程
for i in range(1000, 0, -1):
# 设置LED亮度
led.duty_u16(i * 65)
time.sleep_ms(1) # 延迟以控制亮度变化速度
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
效果: