有源蜂鸣器 无源蜂鸣器(定时器实现PWM播放音乐)
<p><strong>有源蜂鸣器:由于本身存在信号源,因此通电就响。</strong></p><p><strong>无源蜂鸣器:由于本身无信号源,因此给不同频率的方波信号,可发出不同音调的声音。</strong></p>
<p><img src="data/attachment/forum/202505/03/000719qfcvfwaabqbqjff6.png" alt="image.png" title="image.png" /></p>
<h2>有源蜂鸣器</h2>
<p><strong>有源蜂鸣器的驱动十分简单,只要通电就能响,但是只能以固定的音调发声。</strong></p>
<p><strong>案例以1ms为时基,设置蜂鸣器发声的时间即可。</strong></p>
<p><img src="data/attachment/forum/202505/03/000728ymu1ma4ro5uapmwi.png" alt="image.png" title="image.png" /></p>
<p><strong>演示视频:</strong></p>
<video controls="controls" src="forum.php?mod=attachment&aid=96999"></video>
<h2>无源蜂鸣器</h2>
<p><strong>由于有源蜂鸣器只能以特定的频率发声,只含有一种声调,因此想要使用蜂鸣器播放音乐,只能使用无源蜂鸣器,通过给定不同频率的方波信号,控制蜂鸣器发出不同的声调,再结合乐谱,即可播放音乐。</strong></p>
<p><strong>推荐使用带PWM功能的进行控制,【火烛】使用普通引脚进行控制,因此使用定时器配合生成PWM方波信号。</strong></p>
<h3>音度--音调 与 频率之间的关系(不含黑键)</h3>
<p><strong>通过查阅一些资料,可以得到以下对照表</strong></p>
<p><img src="data/attachment/forum/202505/03/001035yd2cn3f5m0053230.png" alt="image.png" title="image.png" /></p>
<h3>如何实现任意频率的方波信号输出</h3>
<pre><code class="language-c">// 先使用定时器11 设置一个10us的时基
Timer11_Init(0, TIM_CLOCK_1T, 10, TIM_us); // 10us定时
// 再编写一个方波处理函数,通过设置beep_Passive_Frequency(频率Hz),自动输出对应频率的方波信号
// 可能不太精准,但也能用
/**
* @name BEEP_Passive_Deal
* @brief 无源蜂鸣器处理函数 本例程使用10us
* @version 版本:v1.0
* @date 日期:2025-05-01
* @author 作者:四汐
* @note 注释:f=1(s)/T=1000(ms)/T --> T=1000(ms)/f
* 20Hz = 1000(ms)/T --> T=50
* 40Hz :T=25
* 定时器1ms 最大频率为1kHz, 定时器10us 最大 100kHz, 定时器100us 最大 10kHz, 定时器1us 最大 1MHz, 1000000 us = 1s
*/
void BEEP_Passive_Deal(void)
{
// 10us 100kHz 1,000,000us = 1s 100,000 T = 1s
static float T_cycle = 0;
T_cycle += 1.0;
if (beep_Passive_Frequency == 0)
{
T_cycle = 0.0;
BEEP_OFF();
}
else if (T_cycle >= ( Toggle_time/beep_Passive_Frequency) )
{
T_cycle = 0.0;
BEEP_Toggle();
}
}
</code></pre>
<h3>了解简谱</h3>
<p><strong>这里以《两只老虎》为例 (本人对乐理并不精通,仅粗略了解一些)</strong></p>
<p><img src="data/attachment/forum/202505/03/001115d2ifmfgbcmm4jgee.png" alt="image.png" title="image.png" /></p>
<p><strong>可以看到左上角有一个 2/4,这个代表每个节拍(“|“区分节拍)进行了2分节,</strong></p>
<p><strong>比如一首60BPM(1分钟有60个节拍,即一节拍占时1秒)的曲子,一个节拍内应含有2个音符,每个音符为0.5秒,比如曲中“眼睛”对应的音符</strong></p>
<p><strong>而带有一个下划线的音符,会再进行一次2分,即4分音符,每个音符占0.25秒。</strong></p>
<p><strong>例如:两只老虎 12 31,对应0.25-0.25 0.25-0.25,即1秒</strong></p>
<p><strong>例如:跑得快 34 5,对应0.25-0.25 0.5,即1秒</strong></p>
<p><strong>了解完每个音符对应的时间(时值),再了解一下数字代表的音调是什么</strong></p>
<p><strong>0-7分别代表着:休止,do,re,mi,fa,so,la,si。</strong></p>
<p><strong>除了音调,还有音度,一般的中央C为4度,那么3度就是低音,2度就是倍低音,4度就是高音,5度就是倍高音。而数字下面带一个点,就说明该音调为低音音调。</strong></p>
<h2>如何播放音乐</h2>
<p><strong>了解完这些,对简单的曲谱 ,可以创建一个乐谱数组</strong></p>
<p><img src="data/attachment/forum/202505/03/001124l9jqnccno3nqx3cb.png" alt="image.png" title="image.png" /></p>
<p><strong>在固定的周期内输出对应的音调,也能勉强听得出来曲调</strong></p>
<p><img src="data/attachment/forum/202505/03/001132qkn4ren8dlnauak7.png" alt="image.png" title="image.png" /></p>
<p><strong>那么,对于复杂一点的乐谱,这个函数貌似就无法满足了。</strong></p>
<p><strong>不仅需要处理音调、音度,还需要处理每一个音调的时值,才能使音乐更有韵律</strong></p>
<p><strong>对此,我简单写了一段曲谱,并编写了对应的处理函数</strong></p>
<p><img src="data/attachment/forum/202505/03/001143sc7nyrz9n5esq77s.png" alt="image.png" title="image.png" /></p>
<p><img src="data/attachment/forum/202505/03/001154vrlj3ocyc8okls8o.png" alt="image.png" title="image.png" /></p>
<p><strong>大家可以猜猜看是什么曲子,难度可能有点大(全损音质哈哈哈),但还是能够听得出来的嘿嘿。</strong></p>
<p><strong>演示视频:</strong></p>
<video controls="controls" src="forum.php?mod=attachment&aid=97006"></video>
以下为针对蜂鸣器技术原理及音乐播放实现的专业分析:
一、蜂鸣器类型特性与驱动原理
1. 有源蜂鸣器
工作原理
有源蜂鸣器内置振荡电路,仅需直流电压驱动即可发声。其固定频率由内部振荡器决定,通常在2kHz~5kHz范围内,无法通过外部信号调整音调。
驱动方法
直接连接至GPIO引脚,通过电平控制启停:
c
// 初始化GPIO为推挽输出模式
BEEPActiveGPIOInit();
// 启动蜂鸣(持续发声)
BEEPActiveON();
// 关闭蜂鸣
BEEPActiveOFF();
应用场景
适用于报警提示、状态指示等单一音调场景,开发复杂度低。
2. 无源蜂鸣器
工作原理
无源蜂鸣器等效为电磁线圈结构,需外部输入方波信号驱动。其发声频率完全由输入信号决定,通过改变方波频率可实现多音调控制。
音乐播放实现
需结合乐谱频率映射与定时器PWM输出,核心步骤如下:
二、无源蜂鸣器的音乐驱动实现
1. 音调-频率映射
标准音调频率对照表(以C大调为例):
| 音符 | C4 | D4 | E4 | F4 | G4 | A4 | B4 | C5 |
|------|----|----|----|----|----|----|----|----|
| 频率(Hz) | 262 | 294 | 330 | 349 | 392 | 440 | 494 | 523 |
2. 定时器配置
使用高精度定时器生成基础时基,通过中断动态调整输出频率:
c
// 定时器初始化(10μs时基)
void TimerInit(void) {
TimerSetPrescaler(TIMx, 0); // 1T模式
TimerSetAutoReload(TIMx, 10); // 10μs周期
TimerEnableInterrupt(TIMx); // 开启中断
TimerStart(TIMx);
}
// 中断服务函数
void TIMxIRQHandler(void) {
static uint16t count = 0;
if(count++ >= halfperiod) { // halfperiod = 1/(2f10e-6)
BEEPToggle(); // 翻转电平
count = 0;
}
TimerClearFlag(TIMx);
}
3. 频率动态控制
通过预设频率值计算半周期参数:
c
void BEEPSetFrequency(uint16t freq) {
if(freq == 0) {
BEEPOFF(); // 静音处理
} else {
halfperiod = 500000 / freq; // 10μs时基下的半周期计算
}
}
4. 乐谱驱动实现
将乐谱编码为频率-时长序列:
```c
// 示例:《小星星》片段
const uint16t melodyfreq[] = {262, 262, 392, 392, 440, 440, 392};
const uint8t melodyduration[] = {4, 4, 4, 4, 4, 4, 8}; // 单位:节拍
void PlayMusic(void) {
for(int i=0; i
[本文内容由国芯人工智能辅助生成,仅供参考] 用蜂鸣器奏乐
页:
[1]