目录
一、了解一下延时函数
二、准备音频数据表
三、了解一下蜂鸣器
四、音乐奏响原理
(1)了解一个音调中的更加细致的小声音
(2)发出一个音调的声音
五、按键发出声音
一、了解一下延时函数
1s=1000ms=1000000us
如果是1us,就把1ms中的SysTick_Config(SystemCoreClock/1000); 改为 SysTick_Config(SystemCoreClock/1000000);
void SysTick_Delay_Us( __IO uint32_t us) //_IO指静态 volatile uint32_t
{uint32_t i; SysTick_Config(SystemCoreClock/1000000); //SystemCoreClock 是一个宏,大小为 72000000for (i=0; i<us; i++){// 当计数器的值减小到 0 的时候,CRTL 寄存器的位 16 会置 1 while ( !((SysTick->CTRL)&(1<<16)) ); }// 关闭 SysTick 定时器 SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}
二、准备音频数据表
uc16 tone[] = {247,262,294,330,349,392,440,494,523,587,659,698,784,1000};//音频数据表
//小燕子
u8 music[]={3,5,8,6,5,13,//音调
3,5,6,8,5,13,
8,10,9,8,9,8,6,8,5,13,
3,5,6,5,6,8,9,5,6,13,
3,2,1,2,13,
2,2,3,5,5,8,2,3,5,13};
u8 time[] ={2,2,2,2,6,4,//时间
2,2,2,2,6,4,
6,2,4,4,2,2,2,2,6,4,
6,2,4,2,2,4,2,2,6,4,
2,2,4,6,4,
4,2,2,4,4,4,2,2,6,4};
知识补充:
u16
表示无符号16位整数,即数据类型的取值范围在0到65535之间,以十六进制、十进制或其他进制表示都可以。u8
表示无符号8位整数,即数据类型的取值范围在0到255之间,同样可以以十六进制、十进制或其他进制表示。
三、了解一下蜂鸣器
看一下对应的蜂鸣器的原理图。有一个3V3的外部电源,应该有源蜂鸣器
蜂鸣器的初始化
蜂鸣器的开关
通过下面的三幅图可以看出,蜂鸣器的开关与gpio端电平信号的高低有关
四、音乐奏响原理
(1)了解一个音调中的更加细致的小声音
void Sound(u16 frq)
{u32 time;if(frq != 1000)//if(frq != 1000):条件判断语句,判断音调的频率是否不等于 1000 Hz。{
// time = 500000/((u32)frq);time = 100000/((u32)frq);//根据音调的频率计算延时时间。通常情况下,频率越高,延时时间越短,声音越高。
// PBeep = 1;Buzzer_On();//打开蜂鸣器--根据自己的硬件情况调整,通常就是控制蜂鸣器的gpio引脚置1delay_us(time);
// PBeep = 0;Buzzer_Off();//关闭蜂鸣器--根据自己的硬件情况调整,通常就是控制蜂鸣器的gpio引脚置0delay_us(time);}elsedelay_us(1000);//time = 100000/((u32)frq);:根据音调的频率计算延时时间。通常情况下,频率越高,延时时间越短,声音越高。
}
打开和关闭麦克风相同的时间
(2)发出一个音调的声音
u32 yanshi;u16 i,e;yanshi = 4;//10; 4; 2//实际播放的音调和持续时间会受到延时因子yanshi的影响,通过调节yanshi的值可以控制播放速度。for(i=0;i<sizeof(music)/sizeof(music[0]);i++){for(e=0;e<((u16)time[i])*tone[music[i]]/yanshi;e++){//在内部循环中,计算发声的次数,通过 (u16)time[i] * tone[music[i]] / yanshi 来确定。//这里将音符持续时间乘以音符对应的频率,再除以延时因子 yanshi,得到需要发声的次数。Sound((u32)tone[music[i]]);} }
持续多个Sound播放出来这样听起来就像一个音调
yanshi越大,循环的次数越少,发声的次数越少,声音越慢
五、按键发出声音
#include "stm32f10x.h"
#include "bsp_beep.h"
#include "bsp_key.h" void SysTick_Delay_us( __IO uint32_t us) ; /*** @brief 主函数* @param 无 * @retval 无*/void Sound(u16 frq)
{u32 time;if(frq != 1000)//if(frq != 1000):条件判断语句,判断音调的频率是否不等于 1000 Hz。{
// time = 500000/((u32)frq);time = 100000/((u32)frq);//根据音调的频率计算延时时间。通常情况下,频率越高,延时时间越短,声音越高。
// PBeep = 1;BEEP( ON );//打开蜂鸣器--根据自己的硬件情况调整,通常就是控制蜂鸣器的gpio引脚置1SysTick_Delay_us(time);
// PBeep = 0;BEEP( OFF );//关闭蜂鸣器--根据自己的硬件情况调整,通常就是控制蜂鸣器的gpio引脚置0SysTick_Delay_us(time);}elseSysTick_Delay_us(1000);//time = 100000/((u32)frq);:根据音调的频率计算延时时间。通常情况下,频率越高,延时时间越短,声音越高。
}int main(void)
{ /* BEEP GPIO 初始化 */BEEP_GPIO_Config(); Key_GPIO_Config();while(1) { u32 yanshi;u16 e;yanshi = 4;//10; 4; 2if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON ){for(e=0;e<(u16)(2*262/yanshi);e++){//在内部循环中,计算发声的次数,通过 (u16)time[i] * tone[music[i]] / yanshi 来确定。//这里将音符持续时间乘以音符对应的频率,再除以延时因子 yanshi,得到需要发声的次数。Sound(262);} } if( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON ){for(e=0;e<(u16)(2*294/yanshi);e++){//在内部循环中,计算发声的次数,通过 (u16)time[i] * tone[music[i]] / yanshi 来确定。//这里将音符持续时间乘以音符对应的频率,再除以延时因子 yanshi,得到需要发声的次数。Sound(294);}} }
}void SysTick_Delay_us( __IO uint32_t us)
{uint32_t i;SysTick_Config(SystemCoreClock/1000000); for (i=0; i<us; i++){ // 当计数器的值减小到 0 的时候,CRTL 寄存器的位 16 会置 1 // 当置 1 时,读取该位会清 0 while ( !((SysTick->CTRL)&(1<<16)) ); }SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}
/*********************************************END OF FILE**********************/