凌乱的DSP笔记(3)-蜂鸣器播放音乐
1. 蜂鸣器介绍
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、 打印机、 复印机、 报警器、 电子玩具、 汽车电子设备、 电话机、 定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
压电式蜂鸣器(无源蜂鸣器)主要由多谐振荡器、 压电蜂鸣片、 阻抗匹配器及共鸣箱、 外壳等组成。 多谐振荡器由晶体管或集成电路构成, 当接通电源后( 1.5~15V 直流工作电压),多谐振荡器起振,输出 1.5~5kHZ 的音频信号, 阻抗匹配器推动压电蜂鸣片发声。
电磁式蜂鸣器(有源蜂鸣器)由振荡器、 电磁线圈、 磁铁、 振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈, 使电磁线圈产生磁场, 振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
2. 硬件设计
ULN2003 是高压大电流达林顿晶体管阵列系列产品,具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统。
3. 软件设计
3.1 beep
首先仿照LED建立beep.c和beep.h。
/* * beep.c * * Created on: 2020-4-6 * Author: lenovo */ #include "beep.h" /******************************************************************************* * 函 数 名 : BEEP_Init * 函数功能 : 蜂鸣器初始化 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void BEEP_Init(void) { EALLOW; SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟 //BEEP端口配置 GpioCtrlRegs.GPAMUX1.bit.GPIO6=0; GpioCtrlRegs.GPADIR.bit.GPIO6=1; GpioCtrlRegs.GPAPUD.bit.GPIO6=0; EDIS; GpioDataRegs.GPACLEAR.bit.GPIO6=1; }
/* * beep.h * * Created on: 2020-4-6 * Author: lenovo */ #ifndef BEEP_H_ #define BEEP_H_ #include "DSP2833x_Device.h" // DSP2833x 头文件 #include "DSP2833x_Examples.h" // DSP2833x 例子相关头文件 #define BEEP_ON (GpioDataRegs.GPASET.bit.GPIO6=1) #define BEEP_OFF (GpioDataRegs.GPACLEAR.bit.GPIO6=1) #define BEEP_TOGGLE (GpioDataRegs.GPATOGGLE.bit.GPIO6=1) void BEEP_Init(void); #endif /* BEEP_H_ */ #define L1 0 #define L2 2 #define L3 4 #define L4 5 #define L5 7 #define L6 9 #define L7 11 #define M1 12 #define M2 14 #define M3 16 #define M4 17 #define M5 19 #define M6 21 #define M7 23 #define H1 24 #define H2 26 #define H3 28 #define H4 29 #define H5 31 #define H6 33 #define H7 35
音调按照十二平均律进行计算,方法在下面给出。
3.2 main.c
/* * main.c * * Created on: 2020年4月6日 * Author: lenovo */ #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Examples.h" // DSP2833x Examples Include File #include "beep.h" int tune[]= //根据简谱列出各频率 { M3,M3,M3,M2,M3,M5,M5,M5, M6,M6,M6,M5,M3,M6,M5,M5, H1,H1,H1,M6,H2,H1,M5,M5, M6,M6,M6,H1,M6,M5,M3,M2, M3,M3,M3,M2,M3,M5,M5,M5, M6,M6,M6,M5,M3,M5,M6,M5, H1,H1,M6,H2,H1,M5,M5, M6,M6,M6,M5,M6,H3,H2, H2,M5,H1,H2, H3,H2,H1,M7,H1,M7,M6,M5, M6,0,0,H1,H2, H3,H2,H1,M7,H1,M7,M3,M5, M6,0,M6,M5, M6,H1,H1,0,H1,H2, H3,H1,H2,H1,H1,M6,M6, H4,H3,H2,H1,H4,H4,H3,H2,H1, H2,H3,H2,H1, H1,H1,H2,H3,H1, H6,H5,H3,H2,H1,M6, 0,M5,H1,H3,H5,H6,H3,H3,H2,H1, M6,H1,H1,H2,H1,H1 }; float beat[]= //根据简谱列出各节拍 { 0.25,0.25,0.25,0.25,0.5,0.25,0.25,2, 0.25,0.25,0.25,0.25,0.5,0.25,0.25,2, 0.25,0.25,0.25,0.25,0.5,0.25,0.25,2, 0.25,0.25,0.25,0.25,0.25,0.5,0.25,2, 0.25,0.25,0.25,0.25,0.5,0.25,0.25,2, 0.25,0.25,0.25,0.25,0.5,0.25,0.25,2, 0.25,0.5,0.25,0.5,0.25,0.25,2, 0.25,0.25,0.25,0.25,0.5,0.5,2, 0.5,0.5,0.5,0.5, 0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5, 2,1,0.5,0.25,0.25, 0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5, 3,0.5,0.25,0.25, 0.5,0.5,1,0.5,1,0.5, 0.5,0.5,0.5,0.5,1.5,0.25,0.25, 0.5,0.5,0.5,0.25,0.25,0.5,0.5,0.5,0.5, 3,0.5,0.25,0.25, 1,0.5,0.5,1.5,0.5, 0.5,0.5,0.25,0.25,0.5,2, 0.5,0.5,0.5,0.5,0.5,0.25,0.25,0.25,0.25,0.5, 0.5,0.5,0.25,0.5,0.25,2 }; /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { //不同音调的延时时长 double tab[36]={1918}; double rate=1.059463;//2^(1/12) int n; for(n=1;n<36;n++) { tab[n]=tab[n-1]/rate; } InitSysCtrl(); BEEP_Init(); int len;//音符个数 len=sizeof(tune)/sizeof(tune[0]); while(1) { int i,j; for(i=0;i<len;i++) { if(tune[i]==0) { DELAY_US(beat[i]*800000); } else { for(j=0;j<beat[i]*800000/tab[tune[i]];j++) { BEEP_TOGGLE; DELAY_US(tab[tune[i]]); } DELAY_US(25000);//音符之间间隔0.025s } } DELAY_US(2000000);//播放结束延时2s } }
首先,将“我只在乎你”简谱转换为音调tune和时长beat数组。
然后根据十二平均律,从低音do的1918us翻转一次(260.7Hz),依次乘以${2^{1/12}}{\rm{ = }}1.059463$,得到数组tab。
之后进行循环播放。