[原创] 【RTT&英飞凌PSoC6评估板(带触摸)】+ 使用PWM驱动蜂鸣器演奏音乐

qinyunti   2023-6-18 14:04 楼主

前言

前面我们测试了PWM和定时器,基于此我们可以进行一些有意思的小Demo开发了。这一篇我们使用PWM驱动蜂鸣器演奏音乐。

 

过程

PWM控制蜂鸣器播放音乐原理

使用PWM控制蜂鸣器发声,

频率对应声音的音调,修改PWM的频率即改变了声音的音调;

幅度对应声音的响度,修改PWM的占空比即改变了声音的大小。

 

以国际标准音A-la-440HZ为准:

do的频率为261.6HZ,

re的频率为293.6HZ,

mi的频率为329.6HZ,

fa的频率为349.2HZ,

sol的频率为392HZ,

la的频率为440HZ,

si的频率为493.8HZ。

 

根据计算相邻音阶的比值为1.12,即高音频率是相邻低音频率的2的1/12次方倍,比如do的频率为261.6HZ,则比它高半音的re的频率为261*2^(1/12)=293.6HZ。

 

这样类比下来,一个八度的音,这样一直乘下来,所得的结果刚好是2倍。

 

根据以上原理我们就可以进行do-re-mi的演奏了,结合演奏时间的控制,声音大小的控制,以及休止时间的控制,即可实现音乐的播放。

 

所以我们需要将音乐乐谱转化为上面的可控元素,频率,占空比,播放时间。

先介绍下简谱

这里找首简单的音乐”两只老虎”

image-20230618140415-1.png  

先看左上角的节拍说明:2/4拍子  4分音符一拍 每小节2拍

一分钟76拍。

 

image-20230618140415-2.png  

 

先定义如下音阶和频率的对应关系

#define DO  523

#define RE  587

#define MI  659

#define FA  698

#define _SO 392

#define SO  784

#define LA  880

#define SI  987

#define NO  523

#define DUTY0  0

 

定义节拍时间

#define METERS  76ul             // 拍数76 1分钟76拍 每拍60/76秒 2/4  4分音符一拍 每小节2拍

#define NOTE_4  (60000ul/METERS)  // 先定一拍对应的音符 4分音符  x1000转化为单位mS

#define NOTE_8  (NOTE_4/2ul)     // 8分音符 一个下划线

#define NOTE_16  (NOTE_8/2ul)    // 16分音符 二个下划线

 

定义音阶表,对应频率

const uint16_t beepfrep[] =

{

DO,RE,MI,DO,

            DO,RE,MI,DO,

            MI,FA,SO,NO,

            MI,FA,SO,NO,

            SO,LA,SO,FA,MI,DO,

            SO,LA,SO,FA,MI,DO,

            DO,_SO,DO,NO,

            DO,_SO,DO,NO

};

 

 

定义声音大小表,对应占空比

const uint16_t beepduty[] =

{           40,40,40,40,

            40,40,40,40,

            40,40,40,DUTY0,

            40,40,40,DUTY0,

            40,40,40,40,40,40,

            40,40,40,40,40,40,

            40,40,40,DUTY0,

            40,40,40,DUTY0,

};

 

 

定义节拍表,对应每个音阶的演奏时间

const uint32_t beeptime[]=

{

 NOTE_8,NOTE_8,NOTE_8,NOTE_8,

            NOTE_8,NOTE_8,NOTE_8,NOTE_8,

            NOTE_8,NOTE_8,NOTE_8,NOTE_8,

            NOTE_8,NOTE_8,NOTE_8,NOTE_8,

            NOTE_16,NOTE_16,NOTE_16,NOTE_16,NOTE_8,NOTE_8,

            NOTE_16,NOTE_16,NOTE_16,NOTE_16,NOTE_8,NOTE_8,

            NOTE_8,NOTE_8,NOTE_8,NOTE_16,

            NOTE_8,NOTE_8,NOTE_8,NOTE_16,

};

 

实现延时函数,这里没有考虑溢出

void mdelay(uint32_t t)

{

uint32_t ct = g_time_u32;

while((g_time_u32 - ct) < t);

}

 

 

实现演奏函数

void beep_play_music(const uint16_t* freq,const uint16_t* duty, const uint32_t* time, uint16_t len)

{

uint16_t i = 0;

for(i=0; i< len; i++)

{

pwm_setduty(freq, duty);

    mdelay(time);

}

}

 

 

测试

 beep_play_music(beepfrep, beepduty, beeptime, sizeof(beepfrep)/sizeof(beepfrep[0]));

 

使用蜂鸣器接到P11_1,可以听到播放效果

示波器可以但看到动态变化的频率

image-20230618140415-3.jpeg  

 

总结

以上介绍了PWM播放音乐的原理,进行了PWM控制蜂鸣器播放音乐的测试。后面再结合电容触摸,使用旋电容触摸作为输入,控制蜂鸣器输出不同的音乐片段,模拟”打碟器”,动次打次的Demo。

 

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复