目录
1.蜂鸣器的分类
🔌 驱动方式与电路设计的差异
2.如何使用PWM控制无源蜂鸣器
2.1.STM32平台:硬件定时器PWM
2.2.hi3516dv300平台:操作系统Linux
3.播放《Do-Re-Mi》示例
1.蜂鸣器的分类
蜂鸣器分为有源蜂鸣器和无源蜂鸣器,核心区别在于其内部是否集成了震荡源,这里的“源”指的不是电源,而是产生固定频率信号的电路。
有源蜂鸣器:内部自带震荡电路。你只需给它接通直流电源(额定电压),它就会立即发出固定频率的声音。可以把它理解为一个“自带乐谱的演奏者”,通电即演。
无源蜂鸣器:内部没有震荡源,仅包含发声元件(如电磁线圈或压电陶瓷片)。如果只给它通直流电,它不会发声,或者只能发出轻微的“咔哒”声。必须由外部电路提供一个方波信号(频率通常在2K~5K Hz之间)来驱动它,它才能根据方波的频率发出对应的声音。它就像一个“需要外部乐谱的乐器”。
🔌 驱动方式与电路设计的差异
这一根本区别,直接导致了它们在电路控制和程序编写上的不同。
| 特性 | 有源蜂鸣器 | 无源蜂鸣器 |
| 驱动信号 | 直流电平(高/地电平) | 方波信号(PWM脉冲) |
| 控制复杂度 | 简单。程序只需控制一个IO扣输出高/低电平即可 | 复杂。程序需要通过PWM或定时器产生特定频率的方波 |
| 发声频率 | 固定,由内部震荡电路决定 | 可变,由外部驱动方波的频率决定 |
| 音调控制 | 无法控制音调 | 可以控制,通过改变方波频率,可以实现“Do Re Mi”等不同音阶 |
2.如何使用PWM控制无源蜂鸣器
使用 PWM 控制无源蜂鸣器,核心在于理解PWM 的频率决定音调,而占空比影响音量。PWM(脉冲宽度调制)信号的本质就是一个方波。
频率决定音调(Pitch):PWM的频率直接对应声音的高低。例如,输出523Hz的方波,蜂鸣器就发出“Do”音;输出587Hz则发出“Re”音。人耳可听的频率范围大约在20Hz 到 20kHz之间,而常用乐音主要集中在262Hz(中央C)到 1047Hz(高音C)附近。
占空比影响音量(Volume):PWM信号在一个周期内高电平所占的比例就是占空比。通常将占空比设置为50%可以获得最大音量输出。
2.1.STM32平台:硬件定时器PWM
对于STM32,通常需要配置一个通用定时器(如TIM3)的PWM输出通道来产生精确的方波。核心步骤是配置预分频器(Prescaler)和自动重装载寄存器(ARR)来设定PWM的频率,并设置捕获/比较寄存器(CCR)来设定占空比。
以标准库或 HAL 库的典型配置逻辑为例,要产生 1kHz、50% 占空比的 PWM(假设系统时钟 72MHz):
预分频(PSC)和ARR共同决定频率:频率 = 系统时钟 /((PSC+1)*(ARR+1))
CCR决定占空比:占空比 = CCR /(ARR+1)
通过动态修改 ARR(或PSC)的值,就可以改变输出频率,从而演奏不同音符。
2.2.hi3516dv300平台:操作系统Linux
在 Hi3516DV300 上,PWM 控制的关键参数是周期 (Period)和占空比 (Duty Cycle)。
频率决定音调:PWM 的频率决定了蜂鸣器发声的音高。例如,周期为1ms对应1kHz的频率。通过动态改变周期,就能演奏不同音符。
占空比影响音量:通常设置为50%可获得最大音量。Hi3516DV300 的 PWM 支持精细的占空比调节。
核心流程是:打开PWM设备 → 配置参数(周期、占空比等) → 使能PWM → (可选) 禁用并关闭。
通过操作寄存器设置PWM从而控制蜂鸣器
①配置引脚复用(将GPIO6_6复用为PWM0)
himm 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_BASE=0x12070000 PWM1_CFG0=$((PWM1_BASE + 0x00)) # 周期寄存器 PWM1_CFG1=$((PWM1_BASE + 0x04)) # 占空比寄存器 PWM1_CTRL=$((PWM1_BASE + 0x0C)) # 控制寄存器 # --- 中音频率表 (Hz) --- NOTE_DO=523 NOTE_RE=587 NOTE_MI=659 NOTE_FA=698 NOTE_SO=784 NOTE_LA=880 NOTE_SI=988 NOTE_REST=0 # 休止符 PWM_CLK=3000000 # 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,并设置为连续输出模式 (bit0=1, bit2=1) 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 "播放结束。"