概念先知道
- PWM(脉宽调制):用“极快地开关”模拟平均电压——开关频率叫频率,高电平时间占比叫占空比。
- 占空比:例程阈值 100~500、周期 1000,高电平占比 =(500-100)/1000 = 40%。占空比越大,LED 越亮、电机越快。
- 输出引脚:PWM 通道 0(PWM_CH0)默认输出在 GPIO24(io_sel=0 时 GPIO24~27 依次对应通道 0~3 正向输出),用示波器/逻辑分析仪观察最直观。
例程功能简介
本页对应博流官方 SDK 的 pwm_basic 例程(examples/peripherals/pwm_v2/pwm_basic),演示 PWM v2 驱动的基本输出功能:
- 时钟源 XCLK(40MHz)经 40 分频得到 1MHz,周期寄存器填
1000,输出频率 = 1MHz / 1000 = 1kHz; - 通道 0 阈值设为 100~500,高电平时间 =(500-100)/ 1000 = 40% 占空比;
- 例程使能通道 0 并启动 PWM 后,持续输出方波,串口每 2 秒打印一次运行信息。
- 同族例程(
examples/peripherals/pwm_v2/):pwm_all_channels(全通道输出)、pwm_config_channel(通道配置)、pwm_deadtime(死区)、pwm_int(中断)、pwm_6step/pwm_spwm/pwm_svpwm/pwm_foc_*(电机与逆变控制)。
操作步骤
PWM 通道 0(PWM_CH0)默认输出引脚为 GPIO24(io_sel=0 时 GPIO24~27 依次对应通道 0~3 的正向输出),board_pwm_gpio_init() 已把它配置为复用功能。建议用示波器或逻辑分析仪观察 GPIO24 的波形;也可以把 LED 经限流电阻接到 GPIO24,通过亮度感受占空比变化。
BL616/BL618 使用 PWM v2 驱动,对应例程为 pwm_basic。在终端进入例程目录(前提:已按快速开始(Linux)或Windows搭建好环境):
cd examples/peripherals/pwm_v2/pwm_basic执行编译命令。Ai-M62(BL616)与 Ai-M61(BL618)同属一个系列,统一填写引脚最少的 bl616 即可:
make CHIP=bl616 BOARD=bl616dk用 USB 线连接开发板,按住 BOOT 键(Ai-M61-32S-Kit 为 IO2)不放、短按 EN/RST 进入下载模式,然后执行烧录(把串口号换成实际值):
make flash CHIP=bl616 COMX=/dev/ttyUSB0打开串口助手(波特率 2000000),每 2 秒打印一次 pwm basic running。用示波器或逻辑分析仪测量 PWM 通道 0 引脚,应看到 1kHz、占空比 40% 的方波。
代码执行流程
例程从启动到运行的完整流程如下(图中的循环箭头表示反复执行):
例程调用的 API 介绍
bflb_device_get_by_name("pwm_v2_0")
获取 PWM v2 外设的设备句柄,BL616/BL618 上名称为 "pwm_v2_0"。
参数:
name:外设名称字符串
返回值:struct bflb_device_s * 设备句柄
bflb_pwm_v2_feature_control(pwm, PWM_CMD_IO_SEL, PWM_IO_SEL_SINGLE_END)
把 PWM 输出配置为单端模式(BL702L 之外的芯片都需要先调用)。
参数:
pwm:PWM 设备句柄cmd:命令,PWM_CMD_IO_SEL选择输出方式arg:PWM_IO_SEL_SINGLE_END单端输出
返回值:成功返回 0;失败返回负值错误码
bflb_pwm_v2_init(pwm, config)
按配置初始化 PWM 时基。struct bflb_pwm_v2_config_s 中:
clk_source:时钟源,BFLB_SYSTEM_XCLKclk_div:分频值,BL616/BL618 填40(1MHz)period:周期计数值,1000→ 1kHz
参数:
pwm:PWM 设备句柄config:配置结构体指针
返回值:成功返回 0;失败返回负值错误码
bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH0, 100, 500)
设置通道的高/低电平阈值,占空比 =(高阈值 - 低阈值)/ 周期 = 40%。
参数:
pwm:PWM 设备句柄channel:通道号,PWM_CH0threshold_low:低阈值100threshold_high:高阈值500
返回值:成功返回 0;失败返回负值错误码
bflb_pwm_v2_channel_positive_start(pwm, PWM_CH0)
启动通道 0 的正向输出。
参数:
pwm:PWM 设备句柄channel:通道号,PWM_CH0
返回值:成功返回 0;失败返回负值错误码
完整代码
以下为 pwm_basic/main.c 完整源码,与官方示例(examples/peripherals/pwm_v2/pwm_basic)一致;点灯引脚已适配 Ai-M61/62-32S-Kit 板载 RGB 灯,默认折叠,点击展开:
📜 点击展开 pwm_basic/main.c 完整代码
#include "bflb_mtimer.h"
#include "bflb_pwm_v2.h"
#include "bflb_clock.h"
#include "board.h"
struct bflb_device_s *pwm;
int main(void)
{
board_init();
board_pwm_gpio_init();
pwm = bflb_device_get_by_name("pwm_v2_0");
/* period = .XCLK / .clk_div / .period = 40MHz( 32MHZ for bl702l) / 40( 32 for bl702l) / 1000 = 1KHz */
struct bflb_pwm_v2_config_s cfg = {
.clk_source = BFLB_SYSTEM_XCLK,
#if defined(BL702L)
.clk_div = 32,
#else
.clk_div = 40,
#endif
.period = 1000,
};
#if !defined(BL702L)
bflb_pwm_v2_feature_control(pwm, PWM_CMD_IO_SEL, PWM_IO_SEL_SINGLE_END);
#endif
bflb_pwm_v2_init(pwm, &cfg);
bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH0, 100, 500); /* duty = (500-100)/1000 = 40% */
bflb_pwm_v2_channel_positive_start(pwm, PWM_CH0);
bflb_pwm_v2_start(pwm);
while (1) {
printf("pwm basic running\r\n");
bflb_mtimer_delay_ms(2000);
}
}FAQ
PWM 引脚没有波形
确认使用的是 PWM 通道 0 对应的引脚(由 board_pwm_gpio_init() 决定);确认调用顺序正确:先 bflb_pwm_v2_channel_positive_start 再 bflb_pwm_v2_start。
频率或占空比不对
频率 = XCLK / clk_div / period;占空比 =(high - low)/ period。修改 period、clk_div、阈值即可调整,注意 BL616/BL618 的 XCLK 为 40MHz。
找不到 pwm_v2 例程
旧版 pwm_v1 只支持 BL602/BL702 等老芯片,BL616/BL618 必须使用 examples/peripherals/pwm_v2 下的例程。
相关最佳实践
遇到问题?
如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

