凌乱的DSP笔记(3)-蜂鸣器播放音乐

时间:2024-02-20 15:31:27

1. 蜂鸣器介绍

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、 打印机、 复印机、 报警器、 电子玩具、 汽车电子设备、 电话机、 定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。

压电式蜂鸣器(无源蜂鸣器)主要由多谐振荡器、 压电蜂鸣片、 阻抗匹配器及共鸣箱、 外壳等组成。 多谐振荡器由晶体管或集成电路构成, 当接通电源后( 1.5~15V 直流工作电压),多谐振荡器起振,输出 1.5~5kHZ 的音频信号, 阻抗匹配器推动压电蜂鸣片发声。

电磁式蜂鸣器(有源蜂鸣器)由振荡器、 电磁线圈、 磁铁、 振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈, 使电磁线圈产生磁场, 振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

2. 硬件设计

image

image

ULN2003 是高压大电流达林顿晶体管阵列系列产品,具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统。

image

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数组。

image

然后根据十二平均律,从低音do的1918us翻转一次(260.7Hz),依次乘以${2^{1/12}}{\rm{ = }}1.059463$,得到数组tab。

之后进行循环播放。

4. 效果

https://www.bilibili.com/audio/au1470042?type=1?type=6