Skip to content

概念先知道

  • 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_*(电机与逆变控制)。

操作步骤

1
硬件准备

PWM 通道 0(PWM_CH0)默认输出引脚为 GPIO24(io_sel=0 时 GPIO24~27 依次对应通道 0~3 的正向输出),board_pwm_gpio_init() 已把它配置为复用功能。建议用示波器或逻辑分析仪观察 GPIO24 的波形;也可以把 LED 经限流电阻接到 GPIO24,通过亮度感受占空比变化。

2
进入例程目录

BL616/BL618 使用 PWM v2 驱动,对应例程为 pwm_basic。在终端进入例程目录(前提:已按快速开始(Linux)Windows搭建好环境):

cd examples/peripherals/pwm_v2/pwm_basic
3
编译工程

执行编译命令。Ai-M62(BL616)与 Ai-M61(BL618)同属一个系列,统一填写引脚最少的 bl616 即可:

make CHIP=bl616 BOARD=bl616dk
4
烧录固件

用 USB 线连接开发板,按住 BOOT 键(Ai-M61-32S-Kit 为 IO2)不放、短按 EN/RST 进入下载模式,然后执行烧录(把串口号换成实际值):

make flash CHIP=bl616 COMX=/dev/ttyUSB0
5
运行验证

打开串口助手(波特率 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 选择输出方式
  • argPWM_IO_SEL_SINGLE_END 单端输出

返回值:成功返回 0;失败返回负值错误码

bflb_pwm_v2_init(pwm, config)

按配置初始化 PWM 时基。struct bflb_pwm_v2_config_s 中:

  • clk_source:时钟源,BFLB_SYSTEM_XCLK
  • clk_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_CH0
  • threshold_low:低阈值 100
  • threshold_high:高阈值 500

返回值:成功返回 0;失败返回负值错误码

bflb_pwm_v2_channel_positive_start(pwm, PWM_CH0)

启动通道 0 的正向输出。

参数

  • pwm:PWM 设备句柄
  • channel:通道号,PWM_CH0

返回值:成功返回 0;失败返回负值错误码

bflb_pwm_v2_start(pwm)

启动 PWM 外设,输出方波。必须先启动通道再启动 PWM。

参数

  • pwm:PWM 设备句柄

返回值:成功返回 0;失败返回负值错误码

完整代码

以下为 pwm_basic/main.c 完整源码,与官方示例(examples/peripherals/pwm_v2/pwm_basic)一致;点灯引脚已适配 Ai-M61/62-32S-Kit 板载 RGB 灯,默认折叠,点击展开:

📜 点击展开 pwm_basic/main.c 完整代码
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_startbflb_pwm_v2_start

频率或占空比不对

频率 = XCLK / clk_div / period;占空比 =(high - low)/ period。修改 periodclk_div、阈值即可调整,注意 BL616/BL618 的 XCLK 为 40MHz。

找不到 pwm_v2 例程

旧版 pwm_v1 只支持 BL602/BL702 等老芯片,BL616/BL618 必须使用 examples/peripherals/pwm_v2 下的例程。

相关最佳实践

遇到问题?

如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23