
目录1.蜂鸣器的分类 驱动方式与电路设计的差异2.如何使用PWM控制无源蜂鸣器2.1.STM32平台硬件定时器PWM2.2.hi3516dv300平台操作系统Linux3.播放《Do-Re-Mi》示例1.蜂鸣器的分类蜂鸣器分为有源蜂鸣器和无源蜂鸣器核心区别在于其内部是否集成了震荡源这里的“源”指的不是电源而是产生固定频率信号的电路。有源蜂鸣器内部自带震荡电路。你只需给它接通直流电源额定电压它就会立即发出固定频率的声音。可以把它理解为一个“自带乐谱的演奏者”通电即演。无源蜂鸣器内部没有震荡源仅包含发声元件如电磁线圈或压电陶瓷片。如果只给它通直流电它不会发声或者只能发出轻微的“咔哒”声。必须由外部电路提供一个方波信号频率通常在2K5K Hz之间来驱动它它才能根据方波的频率发出对应的声音。它就像一个“需要外部乐谱的乐器”。 驱动方式与电路设计的差异这一根本区别直接导致了它们在电路控制和程序编写上的不同。特性有源蜂鸣器无源蜂鸣器驱动信号直流电平高/地电平方波信号PWM脉冲控制复杂度简单。程序只需控制一个IO扣输出高/低电平即可复杂。程序需要通过PWM或定时器产生特定频率的方波发声频率固定由内部震荡电路决定可变由外部驱动方波的频率决定音调控制无法控制音调可以控制通过改变方波频率可以实现“Do Re Mi”等不同音阶2.如何使用PWM控制无源蜂鸣器使用 PWM 控制无源蜂鸣器核心在于理解PWM 的频率决定音调而占空比影响音量。PWM脉冲宽度调制信号的本质就是一个方波。频率决定音调PitchPWM的频率直接对应声音的高低。例如输出523Hz的方波蜂鸣器就发出“Do”音输出587Hz则发出“Re”音。人耳可听的频率范围大约在20Hz 到 20kHz之间而常用乐音主要集中在262Hz中央C到 1047Hz高音C附近。占空比影响音量VolumePWM信号在一个周期内高电平所占的比例就是占空比。通常将占空比设置为50%可以获得最大音量输出。2.1.STM32平台硬件定时器PWM对于STM32通常需要配置一个通用定时器如TIM3的PWM输出通道来产生精确的方波。核心步骤是配置预分频器Prescaler和自动重装载寄存器ARR来设定PWM的频率并设置捕获/比较寄存器CCR来设定占空比。以标准库或 HAL 库的典型配置逻辑为例要产生 1kHz、50% 占空比的 PWM假设系统时钟 72MHz预分频PSC和ARR共同决定频率频率 系统时钟 /PSC1*ARR1CCR决定占空比占空比 CCR /ARR1通过动态修改 ARR或PSC的值就可以改变输出频率从而演奏不同音符。2.2.hi3516dv300平台操作系统Linux在 Hi3516DV300 上PWM 控制的关键参数是周期 (Period)和占空比 (Duty Cycle)。频率决定音调PWM 的频率决定了蜂鸣器发声的音高。例如周期为1ms对应1kHz的频率。通过动态改变周期就能演奏不同音符。占空比影响音量通常设置为50%可获得最大音量。Hi3516DV300 的 PWM 支持精细的占空比调节。核心流程是打开PWM设备 → 配置参数周期、占空比等 → 使能PWM → (可选) 禁用并关闭。通过操作寄存器设置PWM从而控制蜂鸣器①配置引脚复用将GPIO6_6复用为PWM0himm 0x111F0024 0x601②初始化PWM0的时钟源PWM时钟选择3MHz打开时钟PWM0的时钟源寄存器设置寄存器值③设置PWM0的周期输出523Hz频率发出“Do”音占空比为50%周期 系统时钟 / 频率 3MHz / 523Hz 5736.1376673040152963671128107075取整5736十六进制为0x0001668。高电平配置为5736周期数×50%占空比2868十六进制为0x0000B34。himm 0x12070000 0x0001668④设置占空比himm 0x12070004 0x0000B34⑤使能PWM0并设置为连续输出模式himm 0x1207000C 0x53.播放《Do-Re-Mi》示例寄存器配置shell脚本#!/bin/sh # 1. 配置 GPIO 复用 himm 0x111F0024 0x601 # 2. 稍微延时等待硬件稳定视情况可选 usleep 10000 # 等待 10ms # Hi3516DV300 PWM1 寄存器直控播放《Do-Re-Mi》片段 # 默认 PWM 时钟3MHz # --- PWM1 寄存器地址 --- PWM1_BASE0x12070000 PWM1_CFG0$((PWM1_BASE 0x00)) # 周期寄存器 PWM1_CFG1$((PWM1_BASE 0x04)) # 占空比寄存器 PWM1_CTRL$((PWM1_BASE 0x0C)) # 控制寄存器 # --- 中音频率表 (Hz) --- NOTE_DO523 NOTE_RE587 NOTE_MI659 NOTE_FA698 NOTE_SO784 NOTE_LA880 NOTE_SI988 NOTE_REST0 # 休止符 PWM_CLK3000000 # 3MHz # --- 核心播放函数 --- # 参数1: 频率 (Hz) # 参数2: 持续时间 (毫秒) play_note() { freq$1 duration_ms$2 if [ $freq -eq 0 ]; then # 休止符关闭 PWM 输出 himm $PWM1_CTRL 0x0 else # 计算周期拍数: 3,000,000 / freq period$((PWM_CLK / freq)) # 50% 占空比 duty$((period / 2)) # 写入周期与占空比 himm $PWM1_CFG0 $period himm $PWM1_CFG1 $duty # 使能 PWM1并设置为连续输出模式 (bit01, bit21) himm $PWM1_CTRL 0x5 fi # 延时指定时长 (毫秒)利用 sleep 的小数点功能 sleep $(awk BEGIN{print $duration_ms/1000}) } # --- 停止 PWM --- stop_pwm() { himm $PWM1_CTRL 0x0 } # --- 旋律数据: 音符 时值(ms) --- # 旋律片段源自《Do-Re-Mi》经典段落: Do Re Mi, Do Re Mi... melody $NOTE_DO 300 $NOTE_RE 300 $NOTE_MI 300 $NOTE_DO 300 $NOTE_RE 300 $NOTE_MI 300 $NOTE_MI 150 $NOTE_FA 150 $NOTE_SO 300 $NOTE_MI 150 $NOTE_FA 150 $NOTE_SO 300 $NOTE_SO 150 $NOTE_LA 150 $NOTE_SI 150 $NOTE_DO 450 $NOTE_REST 200 # --- 主播放循环 --- echo 开始播放 Do-Re-Mi... stop_pwm # 确保初始状态为关闭 # 将旋律字符串按行读入每两行组成 (音符, 时值) set -- $melody while [ $# -gt 0 ]; do freq$1 duration$2 shift 2 play_note $freq $duration done stop_pwm echo 播放结束。