基于小智派-LZ3863星闪开发版:OpenHarmony PWM 外设开发 — 蜂鸣器控制
1、实验简介
参考网址:https://gitee.com/Lockzhiner-Electronics/lz3863/tree/master/apps/b2_buzzer_pwm
1.1、实验目的
本实验旨在帮助学习者掌握 OpenHarmony 轻量系统中 PWM(脉宽调制) 外设的基本使用方法。通过本实验,你将学会:
- 理解 PWM 的工作原理及占空比、频率等核心概念;
- 将 GPIO 引脚复用为 PWM 输出功能;
- 使用 IoT Hardware 接口初始化 PWM 并输出指定频率与占空比的信号;
- 结合 RTOS 线程与
osDelay()控制蜂鸣器鸣响时长; - 完成案例代码的编译、烧录与现象观察。
1.2、实验内容
本案例在 LZ3863-星闪开发板上,通过 GPIO11 引脚输出 PWM3 信号,驱动板载蜂鸣器发声。
| 项目 | 说明 |
|---|---|
| 控制引脚 | GPIO11(IOT_IO_NAME_GPIO_11) |
| 引脚功能 | 复用为 PWM3 输出(IOT_IO_FUNC_GPIO_11_PWM3_OUT) |
| PWM 端口 | PWM3(端口号 3) |
| 输出频率 | 2000 Hz |
| 输出占空比 | 50%(鸣响时) |
| 鸣响时长 | 约 1000 ms(osDelay(100),1 tick = 10 ms) |
| 任务名称 | buzzer_pwm_main |
程序将蜂鸣器控制逻辑封装在独立的 RTOS 线程中:上电后蜂鸣器鸣响约 1 秒,随后停止输出。
1.3、实验环境
| 项目 | 说明 |
|---|---|
| 硬件 | LZ3863-星闪开发板、USB 数据线 |
| 软件 | OpenHarmony v5.1.0 源码、hb 编译工具 |
| 调试工具 | 串口助手(波特率 115200,可选,用于查看调试日志) |
| 案例路径 | applications/sample/wifi-iot/app/b2_buzzer_pwm/ |
2、基础知识
2.1、什么是 PWM
PWM(Pulse Width Modulation,脉宽调制) 是一种通过快速切换数字信号高低电平,模拟模拟量输出的技术。在固定周期内,高电平持续时间占整个周期的比例称为 占空比(Duty Cycle),切换频率称为 频率(Frequency)。
PWM 的两个核心参数:
| 参数 | 说明 | 本实验取值 |
|---|---|---|
| 频率(freq) | 每秒 PWM 周期数,单位 Hz | 2000 Hz |
| 占空比(duty) | 高电平时间占周期的百分比,范围 1~99 | 50% |
对于蜂鸣器等有源/无源发声器件,合适的频率和占空比可使其产生清晰可闻的声音。本实验使用 2000 Hz、50% 占空比的方波驱动蜂鸣器。
2.2、引脚复用(Mux)
与 GPIO 实验类似,WS63 芯片的 IO 引脚支持多种功能复用。使用 PWM 前,必须通过 IoSetFunc() 将引脚配置为对应的 PWM 输出模式,而非普通 GPIO 模式。
本实验使用:
#define PWM_GPIO IOT_IO_NAME_GPIO_11 // PWM 引脚号
#define PWM_GPIO_FUNC IOT_IO_FUNC_GPIO_11_PWM3_OUT // 复用为 PWM3 输出
#define PWM_PORT 3 // PWM 端口号
注意:GPIO 引脚与 PWM 端口的对应关系需查阅 WS63 芯片手册及开发板原理图。本案例使用 GPIO11 对应 PWM3 端口。
2.3、蜂鸣器驱动原理
蜂鸣器是一种电声转换器件,接入 PWM 信号后,其内部振荡电路或压电片随方波频率振动而发声。频率越高,音调越高;占空比影响有效驱动功率,进而影响音量。
开发板已将蜂鸣器与驱动电路连接至 GPIO11(PWM3),用户只需通过 PWM API 输出指定频率和占空比的信号即可控制发声。将占空比设为 0 或调用 IoTPwmStop() 可停止发声。
2.4、核心 API 介绍
2.4.1、头文件
#include <stdio.h>
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "iot_pwm.h"
#include "ohos_init.h"
2.4.2、PWM 常用 API
| API 名称 | 功能说明 |
|---|---|
IoTGpioInit |
初始化指定 GPIO 引脚 |
IoSetFunc |
设置引脚复用功能(如 PWM 输出) |
IoTPwmInit |
初始化指定 PWM 端口 |
IoTPwmDeinit |
解除 PWM 端口初始化 |
IoTPwmStart |
启动 PWM 输出(指定占空比与频率) |
IoTPwmStop |
停止 PWM 输出 |
2.4.3、IoTPwmInit — 初始化 PWM 端口
unsigned int IoTPwmInit(unsigned int port);
| 参数 | 说明 |
|---|---|
port |
PWM 端口号,本实验为 3(PWM3) |
返回值:IOT_SUCCESS 表示成功,IOT_FAILURE 表示失败。
2.4.4、IoTPwmStart — 启动 PWM 输出
unsigned int IoTPwmStart(unsigned int port, unsigned short duty, unsigned int freq);
| 参数 | 说明 |
|---|---|
port |
PWM 端口号 |
duty |
占空比,取值范围 1~99;设为 0 可等效停止输出 |
freq |
输出频率,单位 Hz |
2.4.5、IoTPwmStop — 停止 PWM 输出
unsigned int IoTPwmStop(unsigned int port);
| 参数 | 说明 |
|---|---|
port |
PWM 端口号 |
本案例通过 IoTPwmStart(PWM_PORT, 0, FREQUENCY) 将占空比设为 0 来停止蜂鸣器,效果与调用 IoTPwmStop() 类似。
2.4.6、osDelay — 线程延时
osStatus_t osDelay(uint32_t ticks);
本系统默认 1 tick = 10 ms,因此 osDelay(100) ≈ 延时 1000 ms(1 秒)。蜂鸣器在鸣响后延时 1 秒再关闭输出。
2.4.7、APP_FEATURE_INIT — 应用入口注册
APP_FEATURE_INIT(buzzer_pwm_example);
该宏将 buzzer_pwm_example 注册为应用特性初始化函数,系统启动完成后自动调用,无需手动修改 main() 函数。
3、程序设计
3.1、程序架构
本案例文件目录结构:
b2_buzzer_pwm/
├── buzzer_pwm_example.c # 主程序源码
├── BUILD.gn # GN 编译配置
├── README_zh.md # 案例简要说明
└── 实验手册.md # 本实验手册
本案例采用 两层任务结构:
系统启动
│
▼
buzzer_pwm_example() ← APP_FEATURE_INIT 注册,系统启动时自动执行
│
▼
buzzer_pwm_main() ← 蜂鸣器 PWM 控制任务
├── IoTGpioInit() ← 初始化 GPIO
├── IoSetFunc() ← 配置引脚复用为 PWM3
├── IoTPwmInit() ← 初始化 PWM 端口
├── IoTPwmStart(50%, 2kHz) ← 启动蜂鸣器鸣响
├── osDelay(100) ← 延时约 1 秒
└── IoTPwmStart(0%, 2kHz) ← 停止蜂鸣器输出
3.2、源文件说明
| 文件 | 说明 |
|---|---|
buzzer_pwm_example.c |
主程序源码,包含蜂鸣器 PWM 控制逻辑 |
BUILD.gn |
GN 编译配置文件,定义静态库 buzzer_pwm_example |
3.3、关键代码分析
(1)宏定义 — 引脚与 PWM 配置
#define PWM_GPIO IOT_IO_NAME_GPIO_11 // GPIO 引脚(需支持 PWM 功能)
#define PWM_GPIO_FUNC IOT_IO_FUNC_GPIO_11_PWM3_OUT // 引脚功能配置为 PWM3
#define PWM_PORT 3 // PWM 端口号
#define FREQUENCY 2000 // PWM 频率:2000 Hz
(2)蜂鸣器控制任务 — buzzer_pwm_main
buzzer_pwm_main 是核心工作线程,完成 GPIO 与 PWM 初始化后,输出 50% 占空比、2000 Hz 的 PWM 信号驱动蜂鸣器,延时约 1 秒后关闭:
void buzzer_pwm_main(void *arg)
{
(void)arg;
// 初始化 GPIO
IoTGpioInit(PWM_GPIO);
// 设置 GPIO 复用功能为 PWM
(void)IoSetFunc(PWM_GPIO, PWM_GPIO_FUNC);
// 初始化 PWM 端口
if (IoTPwmInit(PWM_PORT) != 0)
{
printf("[PWM] IoTPwmInit failed!\n");
return;
}
printf("[PWM] buezer test started.\n");
IoTPwmStart(PWM_PORT, 50, FREQUENCY); // 50% 占空比,2000 Hz,蜂鸣器开始鸣响
osDelay(100); // 延时约 1000 ms
IoTPwmStart(PWM_PORT, 0, FREQUENCY); // 占空比设为 0,停止鸣响
}
(3)应用启动入口 — buzzer_pwm_example
系统启动后,通过 APP_FEATURE_INIT 宏自动调用此函数,创建蜂鸣器控制线程:
static void buzzer_pwm_example(void)
{
osThreadAttr_t attr = {0};
attr.name = "buzzer_pwm_main";
attr.stack_size = 2048;
attr.priority = osPriorityNormal;
if (osThreadNew(buzzer_pwm_main, NULL, &attr) == NULL)
{
printf("[BuzzerTest] Failed to create buzzer_pwm_main thread!\n");
}
}
APP_FEATURE_INIT(buzzer_pwm_example);
3.4、程序执行流程
4、编译步骤
4.1、确认案例目录
确认案例已位于 OpenHarmony 源码目录下:
applications/sample/wifi-iot/app/b2_buzzer_pwm/
├── buzzer_pwm_example.c
├── BUILD.gn
└── 实验手册.md
若从外部复制,请将 b2_buzzer_pwm 目录放到上述 app/ 路径下。
4.2、修改 BUILD.gn(注册编译组件)
编辑 applications/sample/wifi-iot/app/BUILD.gn,在 features 列表中添加本案例:
lite_component("app") {
features = [
"startup",
"b2_buzzer_pwm:buzzer_pwm_example", // 添加此行
]
}
4.3、修改 SDK 配置文件
步骤 1:编辑 device/soc/hisilicon/ws63v100/sdk/build/config/target_config/ws63/config.py
找到 'ws63-liteos-app' 配置段,在其 'ram_component' 列表中添加:
"buzzer_pwm_example"
步骤 2:编辑 device/soc/hisilicon/ws63v100/sdk/libs_url/ws63/cmake/ohos.cmake
找到 "ws63-liteos-app" 对应的 set(COMPONENT_LIST 部分,添加:
"buzzer_pwm_example"
4.4、执行编译
在 OpenHarmony 源码根目录下执行:
rm -rf out
hb set -root .
# 通过上下方向键选择 ws63 对应的编译分支(如 nearlink_dk_3863 / ws63-liteos-app)
hb build -f
编译成功后,固件输出路径通常在 out/ws63/ 目录下。
4.5、烧录固件
使用开发板配套的烧录工具,将编译生成的固件烧写到 LZ3863-星闪开发板。具体烧录步骤请参考开发板用户手册。
5、运行结果
5.1、串口配置(可选)
若需查看调试日志,可打开串口助手:
| 参数 | 值 |
|---|---|
| 波特率 | 115200 |
| 数据位 | 8 |
| 停止位 | 1 |
| 校验位 | 无 |
5.2、预期现象
烧录并复位开发板后,可观察到:
- 开发板 蜂鸣器鸣响约 1 秒 后自动停止;
- 鸣响频率稳定,音调适中(2000 Hz);
- 每次上电或复位仅鸣响一次,不会重复。
5.3、结果分析
| 现象 | 说明 |
|---|---|
| 蜂鸣器鸣响约 1 秒 | IoTPwmStart(50, 2000) 输出有效 PWM 信号,osDelay(100) 保持约 1000 ms |
| 鸣响后自动停止 | IoTPwmStart(0, 2000) 将占空比设为 0,PWM 无有效驱动 |
| 串口输出启动日志 | PWM 初始化成功后打印 [PWM] buezer test started. |
| 仅鸣响一次 | 任务执行完毕后退出循环,不会重复触发 |
若 PWM 初始化失败,串口可能输出:
[PWM] IoTPwmInit failed!
若任务创建失败,串口可能输出:
[BuzzerTest] Failed to create buzzer_pwm_main thread!
5.4、常见问题排查
| 问题 | 可能原因 | 解决方法 |
|---|---|---|
| 蜂鸣器完全无声 | 案例未加入编译或烧录了错误固件 | 核对 4.2、4.3 节三处配置,重新编译烧录 |
| 蜂鸣器持续鸣响不停止 | osDelay 未执行或占空比未清零 |
检查任务是否正常运行,确认 IoTPwmStart(0, ...) 被调用 |
| 串口报 IoTPwmInit failed | 引脚复用或 PWM 端口配置错误 | 确认 PWM_GPIO、PWM_GPIO_FUNC、PWM_PORT 与硬件一致 |
| 音调异常或音量微弱 | 频率或占空比不合适 | 尝试调整 FREQUENCY(如 1000~4000 Hz)或占空比(30~70%) |
编译报错找不到 buzzer_pwm_example |
BUILD.gn 或 config.py 未正确修改 | 逐步核对 4.2、4.3 节的配置项 |
| 引脚无响应 | 引脚复用功能未正确设置 | 确认 IoSetFunc() 在 IoTPwmInit() 之前调用 |
6、实验扩展
完成基本实验后,可尝试以下扩展练习:
- 修改鸣响时长:将
osDelay(100)改为osDelay(50)(约 500 ms)或osDelay(200)(约 2 s),观察蜂鸣器发声时间变化; - 调整音调:修改
FREQUENCY为 1000 Hz 或 4000 Hz,感受不同频率下的音调高低; - 改变占空比:将占空比从 50 改为 30 或 70,观察音量变化;
- 使用 IoTPwmStop:将
IoTPwmStart(PWM_PORT, 0, FREQUENCY)替换为IoTPwmStop(PWM_PORT),对比停止方式; - 周期性鸣响:在
buzzer_pwm_main中加入循环,实现"嘀—嘀—嘀"间歇鸣响效果; - 结合其他案例:配合
b3_adc_key按键案例,实现按键触发蜂鸣器报警。
更多推荐



所有评论(0)