没有合适的资源?快使用搜索试试~ 我知道了~
首页51单片机定时器中断写MIDI音乐(按键可切换音乐)
Author: Manba Cople 专业:IOT 说明:记录和输出学习内容 文章目录前言定时器音乐播放音乐库总结和展望 前言 程序思路:该程序是利用51单片机的定时器中断,另外根据音符的频率计算每个音符定时时长从而输出不同音符对应的PWM波驱动蜂鸣器播放音乐。 使用工具:Keil4,protues8;程序具体代码和仿真原理图都已打包放到《基于51单片机的MIDI音乐(可切换)》资源, 完整资源链接:51单片机MIDI音乐播放器完整工程. 定时器 采用13位非自动重装初值模式TMOD=0x00;初值duty由音乐播放函数调用是计算: duty=460830/music[i];其中4608
资源详情
资源评论
资源推荐

51单片机定时器中断写单片机定时器中断写MIDI音乐音乐(按键可切换音乐按键可切换音乐)
Author: Manba Cople
专业:IOT
说明:记录和输出学习内容
文章目录文章目录前言定时器音乐播放音乐库总结和展望
前言前言
程序思路:该程序是利用51单片机的定时器中断,另外根据音符的频率计算每个音符定时时长从而输出不同音符对应的PWM波驱动蜂鸣器播放音乐。
使用工具:Keil4,protues8;程序具体代码和仿真原理图都已打包放到《基于51单片机的MIDI音乐(可切换)》资源,
完整资源链接:51单片机MIDI音乐播放器完整工程.
定时器定时器
采用13位非自动重装初值模式TMOD=0x00;初值duty由音乐播放函数调用是计算:
duty=460830/music[i];其中460830的由来是:460830=10^6/2/1.085
完整计算计数初值的思路:
duty=(1/fren)*10^6/2/机器周期(本文用的11.0592MHz机器周期为:1.085us)
代码如下:
/******************定时器******************/
void Init_Timer0() //定时器初始化函数
{
TMOD=0x00; //13位非自动
TH0=(8192-duty)/32;
TL0=(8192-duty)%32;
TF0=0;
ET0=1;
IT0 = 1; //设置中断
EX0 = 1;
EA=1;
}
void Serve_Timer0() interrupt 1
{
TH0=(8192-duty)/32;
TL0=(8192-duty)%32; //重装初值
sound=!sound; //计数值到时输出电平发生反转
}
/******************************************/
音乐播放音乐播放
在音乐播放中,不断读入乐谱数组,首先根据乐谱的音阶确定定时器输出的PWM波,其次音乐的每个音符之间有拍子,
即每个音符要输出一定的时间,一般乐谱会标出J=...,单位是每分钟多少拍,因此本文用:t=60*1000/J/2 实现,其中t为
每半拍的时间(可根据自己的乐谱改)。另外,本文 实现三首曲子的切换功能,借助state_INT变量记录开关状态实现。
代码如下:(仅写实现一首,其他代码相同)
/*************音乐播放函数*****************/
void MusicPlayer()
{
unsigned char i=0,j=1,p,t;
while(music[i]!=0xff&state_INT==0)
{
t=60*1000/150/2;
duty=460830/music[i];
TR0=1; //启动定时器T0
for(p=0;p<music[j];p++) //控制节拍数
Delay_ms(t); //延时半个节拍单位
TR0=0; //关闭定时器T0
i+=2; //播放下一个音符
j+=2;
}
}
/******************************************/
音乐库音乐库
音乐库数组,本文格式是:{音阶,拍子,音阶,拍子,...},即在给出音阶的同时就给出对应的拍子, 音阶和拍子的转换思路
如下(本人不是很懂音乐,纯属个人见解):
音阶分为高音、中音、低音,在乐谱中根据音阶的标记可知道,数字头上有标记为高音,数字上下没有标记的为中音,数字下部有标记的为低音
拍子的大致计算总结:单个数字数字下加下划线表示该音阶拍子是1/2节拍;数字加双下划线就是1/4节拍;数字后加点,该点是1/2节拍,加上前
面数字也就是3/2节拍;同理,数字加下划线并且后面加点就是一个节拍,数字后面加横线就是二倍节拍
依据上述总结计算《我和我的祖国》(J=150)乐谱+代码如下:

















安全验证
文档复制为VIP权益,开通VIP直接复制

评论0