用单片机的蜂鸣,实现简单小星星
我们在设置板子的时候要翻转
翻转IO口是因为使用了步进电机的多余的芯片管脚
我们翻转之后还想让它保持一段时间
就是先翻转500次 Delay(1)之后 就是最小的单位每隔1ms 周期就是2ms 频率就是500HZ
蜂鸣器播放音乐
我们首先在前面到现在必须明白一个道理 就是我们的蜂鸣器发声是因为蜂鸣器的
我们可以不停的反转的电平,而且随着电平翻转频率的变化,它的音调也会变化,依据此原理可以用蜂鸣器来播放音乐。我们可以控制电平的时序,传递合适的周期以便于控制音调的高低。
我们可以这么想 ,就像一个鼓,我们如果不敲动,那么就不会发声。我们必须给他一个扰动 也就是翻转 。就像是我们控制
举例
void Timer0_Routine() interrupt 1
{
TL0 = 64580%256; //设置定时初值
TH0 = 64580%256; //设置定时初值
Buzzer=!Buzzer; //蜂鸣器的频率
}
当我们在实现音乐控制的时候还会出现一个问题就是我们的数组前两个数字是一样的那该怎么办
这样听声音就会有一种顿挫感
unsigned char Music[]={12,12,19,19,21,21,19,17,17,16,16,14,14,12};
例如这是最经典的小星星的一段
我们最好在中间插入一点东西使得能够听出不一样的感觉
FreqSelect=Music[MusicSelect];
MusicSelect++;
Delay(500);
TR0=0;
Delay(5);
TR0=1;
做到这里我们会发现还有问题 我们看乐谱的时候就会发现有些音他是延长 而又有些音是两个音的组合成一个
那么在这里我们是否再提供一个数组用来确定
这时候我们想到上面的music 是一维数组的形式 我们可以将其改写为二维数组的形式
but 用一个数组也行 最好是二维更加清晰一点吧
FreqSelect=Music[MusicSelect];
MusicSelect++;
Delay(125*Music[MusicSelect]);
MusicSelect++;
TR0=0;
Delay(5);
TR0=1;
}
另外 我们拿到乐谱并不能很好的取一个基准 有很多16分 8分 4分频 我们按照男人的思维 用数学的逻辑 取最小的记为1 哪个最小就用哪个
unsigned char Music[]={
12,4,
12,4,
19,4,
19,4,
21,4,
21,4,
19,4+4,
17,4,
17,4,
16,4,
16,4,
14,4,
14,4,
12,4+4
};
unsigned char FreqSelect,MusicSelect;
void main()
{
Timer0Init();
while(1)
{
FreqSelect=Music[MusicSelect];
MusicSelect++;
Delay(125*Music[MusicSelect]);
MusicSelect++;
TR0=0;
Delay(5);
TR0=1;
}
}
新修改的代码
还有乐谱中会出现休止符 休止符 就是不弹奏的意思
我们再开头插入一个0 为什么再开头不再结尾 其实你插入在哪里都可以 开头最好做好识别一点吧
另外作为一个数组 难免会出现越界的行为 声音走了 那么我们需要在特定位置增加一个判断确定声音是否越界
ok好了下面是小星星的完整代码
main.c
#include <REGX52.H>
#include "Delay.h"
#include"Timer0.h"
sbit Buzzer=P2^5;
#define SPEED 500 //我们以4分音符为基准
unsigned int FreqTable[]={
0,
63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64524,
64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,
65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283
};
unsigned char Music[]={
13,4,
13,4,
20,4,
20,4,
22,4,
22,4,
20,4+4,
0,4,
18,4,
18,4,
16,4,
16,4,
15,4,
15,4,
13,4+4,
0xFF
};
unsigned char FreqSelect,MusicSelect;
void main()
{
Timer0Init();
while(1)
{
if(Music[MusicSelect]!=0xFF)
{
FreqSelect=Music[MusicSelect];
MusicSelect++;
Delay(SPEED/4*Music[MusicSelect]);
MusicSelect++;
TR0=0;
Delay(5);
TR0=1;
}
else
{
TR0=0;
while(1);
}
}
}
void Timer0_Routine() interrupt 1
{
if(FreqTable[FreqSelect])
{
TL0 = FreqTable[FreqSelect]%256; //设置定时初值
TH0 = FreqTable[FreqSelect]/256; //设置定时初值
Buzzer=!Buzzer; //蜂鸣器的频率
}
}
Delay.h
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
Delay.c
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
Timer0.c
#include <REGX52.H>
/**
* @brief 定时器0初始化,1毫秒@12.000MHz
* @param 无
* @retval 无
*/
void Timer0Init(void)
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
PT0=0;
}
Timer0.h
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0Init(void);
#endif