任务:使用PWM驱动蜂鸣器来播放简单音乐
分析:声音的特性可由三个要素来描述,即响度、音调和音色。音调主要与声波的频率有关
| 音调 | 频率 | 低 | L1 | 261.6 | L2 | 293.7 | L3 | 329.6 | L4 | 349.2 | L5 | 392 | L6 | 440 | L7 | 493.9 | 中 | M1 | 523.3 | M2 | 587.3 | M3 | 659.3 | M4 | 698.5 | M5 | 784 | M6 | 880 | M7 | 987.8 | 高 | H1 | 1045.5 | H2 | 1174.7 | H3 | 1318.5 | H4 | 1396.9 | H5 | 1568 | H6 | 1760 | H7 | 1975.5 |
两只老虎简谱:

如果数字下方有点,代表低音,如果数字上方有点,代表高音,否则默认中音。
音长:一般一节为4拍,如果相邻数字下面有连线,说明两个一起是一拍
实现代码片段如下:
#define PWM0_CLK_FREQ 164*1000 //20.97M / 128
#define L1 M1*2
#define L2 M2*2
#define L3 M3*2
#define L4 M4*2
#define L5 M5*2
#define L6 M6*2
#define L7 M7*2
#define M1 (PWM0_CLK_FREQ/523)
#define M2 (PWM0_CLK_FREQ/587)
#define M3 (PWM0_CLK_FREQ/659)
#define M4 (PWM0_CLK_FREQ/698)
#define M5 (PWM0_CLK_FREQ/784)
#define M6 (PWM0_CLK_FREQ/880)
#define M7 (PWM0_CLK_FREQ/988)
#define H1 M1/2
#define H2 M2/2
#define H3 M3/2
#define H4 M4/2
#define H5 M5/2
#define H6 M6/2
#define H7 M7/2
#define NN 0
static unsigned int During;
static unsigned int num;
struct Music_data {
unsigned int freq;
unsigned int During_time;
};
//两只老虎乐谱
static struct Music_data md[] = {
{M1, 0x2},
{M2, 0x2},
{M3, 0x2},
{M1, 0x2},
{M1, 0x2},
{M2, 0x2},
{M3, 0x2},
{M1, 0x2},
{M3, 0x2},
{M4, 0x2},
{M5, 0x4},
{M3, 0x2},
{M4, 0x2},
{M5, 0x4},
{M5, 0x1},
{M6, 0x1},
{M5, 0x1},
{M4, 0x1},
{M3, 0x2},
{M1, 0x2},
{M5, 0x1},
{M6, 0x1},
{M5, 0x1},
{M4, 0x1},
{M3, 0x2},
{M1, 0x2},
{M1, 0x2},
{L5, 0x2},
{M1, 0x4},
{M1, 0x2},
{L5, 0x2},
{M1, 0x4},
{0xff, 0x0},
};
void TPM0_init(void)
{
SIM_SOPT2 |= (1 << 24); //select TPM Clock source
SIM_SCGC5 |= (1 << 11); //enable portC Clock
SIM_SCGC6 |= (1 << 24); //enable TPM0 Clock
PORTC_PCR8 |= (3 << 8); //conifg portc_8 as TPM0_ch4
TPM0_SC |= (1 << 3) | 0x7; //CPWMS and CMOD and PS
TPM0_CNT = 0;
TPM0_MOD = 0; // period = (MOD + 0x0001)
TPM0_C4SC |= (1 << 5) | (1 << 3); //MSnB:MSnA ELSnB:ELSnA EPWM
TPM0_C4V = 0; //duty cycle
}
void TPM0_set(int period)
{
TPM0_MOD = period;
TPM0_C4V = period / 2;
}
void systick_init(void)
{
SYST_RVR = 2621250; //1/8s
SYST_CVR = 0;
SYST_CSR |= 0x7;
}
void __enable_irq(void)
{
asm("CPSIE i");
}
void SysTick_Handler(void)
{
int i;
if(During == 0)
{
if(md[num].freq == 0xff)
{
num = 0;
}
TPM0_set(md[num].freq);
During = md[num].During_time;
num++;
}
During--;
i = SYST_CSR;
}
int main(void)
{
int counter = 0;
TPM0_init();
systick_init();
__enable_irq();
for(;;) {
counter++;
}
return 0;
}
至此,该实验就玩完啦,别忘记点赞哦,欢迎大家留言讨论,谢谢! |