当前位置:网站首页>STC-B学习板蜂鸣器播放音乐
STC-B学习板蜂鸣器播放音乐
2022-07-06 09:24:00 【芜湖韩金轮】
功能:单片机烧录好程序后,按key1按键播放《IF YOU》,再次按key1可暂停播放,按key2可切换歌曲到《国际歌》,再按key3可切换歌曲到《孤勇者》
芯片:STC15F2K61S2
完整工程文件和hex文件在这
提取码:1111
前言:相信大家焊好板子后最喜欢玩的就是蜂鸣器播放音乐,路过每个教室基本都是各种杂音,毕竟这玩意真挺好玩的,于是我就根据老师的代码和谱子写了播放其他歌曲的文件(国际歌是我直接拿往届学长的音乐代码,来凑个数的),说实话这玩意看起来挺简单的,实际上挺难的,还得学一遍乐理知识,然后对着各种拍子和音调不断调试才能得到一个比较理想的状态,但是if you和孤勇者这两首曲子总感觉有些地方不是很完美,但对于摆烂人来说能听就行了。反正也是娱乐娱乐
废话不多说,代码如下:(谱子在最后)
/**********************
文件名称:beep.c
说明:进行音乐播放的例程,按下key1键后开始播放音乐
修改记录:
***********************/
/**********************
基于STC15F2K60S2系列单片机C语言编程实现
使用如下头文件,不用另外再包含"REG51.H"
***********************/
#include <STC15F2K60S2.h>
#define uint unsigned int
#define uchar unsigned char
sbit beep=P3^4; //蜂鸣器
sbit key1=P3^2; //按键1
sbit key2=P3^3; //按键2
uchar timeh,timel,jindu=0,gequ=0; //定义定时器的重装值
bit flag; //播放标志位
uchar code music1[] = //音乐代码,歌曲为《IF YOU》,格式为: 音符, 节拍, 音符, 节拍,
{
0x26,0x10,
0x25,0x10,
0x23,0x10,
0x21,0x10,
0x22,0x10,
0x23,0x10,
0x16,0x20,
0x22,0x08,
0x21,0x08,
0x22,0x08,
0x21,0x08,
0x22,0x08,
0x21,0x08,
0x22,0x10,
0x21,0x08,
0x22,0x08,
0x22,0x08,
0x21,0x08,
0x23,0x20,
0x26,0x10,
0x25,0x10,
0x23,0x10,
0x21,0x10,
0x22,0x10,
0x23,0x10,
0x16,0x20,
0x16,0x08,
0x17,0x10,
0x21,0x08,
0x21,0x08,
0x16,0x08,
0x21,0x08,
0x16,0x08,
0x21,0x08,
0x22,0x08,
0x23,0x08,
0x22,0x08,
0x22,0x10,
0x21,0x08,
0x21,0x08,
0x21,0x10,
0x15,0x08,
0x21,0x20,
0x31,0x10,
0x31,0x08,
0x31,0x08,
0x27,0x08,
0x26,0x08,
0x21,0x10,
0x32,0x10,
0x33,0x10,
0x36,0x10,
0x35,0x10,
0x33,0x10,
0x32,0x10,
0x31,0x10,
0x32,0x30,
0x32,0x08,
0x31,0x08,
0x32,0x08,
0x23,0x08,
0x32,0x10,
0x25,0x24,
0x25,0x08,
0x32,0x08,
0x31,0x08,
0x32,0x08,
0x33,0x24,
0x31,0x08,
0x31,0x10,
0x32,0x10,
0x33,0x10,
0x36,0x10,
0x35,0x10,
0x33,0x10,
0x32,0x10,
0x31,0x08,
0x31,0x08,
0x32,0x10,
0x31,0x30,
0x26,0x08,
0x26,0x08,
0x31,0x08,
0x26,0x08,
0x31,0x08,
0x31,0x24,
0x31,0x08,
0x31,0x08,
0x32,0x08,
0x31,0x08,
0x31,0x08,
0x31,0x24,
0x00,0x10,
};
uchar code music2[] = //歌曲为国际歌
{
0x25, 0x10, 0x31, 0x18, 0x27, 0x08, 0x32, 0x08, 0x31, 0x08, 0x25, 0x08, 0x23, 0x08, 0x26, 0x18, 0x26, 0x08, 0x24, 0x10, 0x20, 0x08,
0x26, 0x08, 0x32, 0x18, 0x31, 0x08, 0x27, 0x08, 0x26, 0x08, 0x25, 0x08, 0x24, 0x08, 0x23, 0x30,
0x25, 0x10, 0x31, 0x18, 0x27, 0x08, 0x32, 0x08, 0x31, 0x08, 0x25, 0x08, 0x23, 0x08, 0x26, 0x20, 0x24, 0x08,
0x26, 0x08, 0x32, 0x08, 0x31, 0x08, 0x27, 0x10, 0x32, 0x10, 0x34, 0x10, 0x27, 0x10, 0x31, 0x20, 0x31, 0x08, 0x30, 0x08,
0x33, 0x08, 0x32, 0x08, 0x27, 0x20, 0x26, 0x08, 0x27, 0x08, 0x31, 0x08, 0x26, 0x08, 0x27, 0x20, 0x25, 0x08,
0x25, 0x08, 0x24, 0x08, 0x25, 0x08, 0x26, 0x18, 0x26, 0x08, 0x32, 0x18, 0x31, 0x08, 0x27, 0x20, 0x27, 0x08, 0x20, 0x08,
0x32, 0x10, 0x32, 0x18, 0x27, 0x08, 0x25, 0x08, 0x25, 0x08, 0x24, 0x08, 0x25, 0x08, 0x33, 0x20, 0x31, 0x08,
0x26, 0x08, 0x27, 0x08, 0x31, 0x08, 0x27, 0x10, 0x32, 0x10, 0x31, 0x10, 0x26, 0x10, 0x25, 0x20, 0x25, 0x08, 0x20, 0x08,
0x33, 0x08, 0x32, 0x08, 0x31, 0x20, 0x25, 0x18, 0x23, 0x08, 0x26, 0x20, 0x24, 0x08, 0x20, 0x08,
0x32, 0x0c, 0x31, 0x04, 0x27, 0x20, 0x26, 0x10, 0x25, 0x10, 0x25, 0x20, 0x25, 0x08, 0x20, 0x08,
0x25, 0x10, 0x33, 0x20, 0x32, 0x10, 0x25, 0x10, 0x31, 0x20, 0x27, 0x18,
0x27, 0x08, 0x26, 0x18, 0x25, 0x08, 0x26, 0x10, 0x32, 0x10, 0x32, 0x20, 0x32, 0x08, 0x30, 0x08,
0x33, 0x0c, 0x32, 0x04, 0x31, 0x20, 0x25, 0x18, 0x23, 0x08, 0x26, 0x20, 0x24, 0x08, 0x20, 0x08,
0x32, 0x0c, 0x31, 0x04, 0x27, 0x20, 0x26, 0x10, 0x25, 0x10, 0x33, 0x30,
0x33, 0x10, 0x35, 0x20, 0x34, 0x10, 0x33, 0x10, 0x32, 0x18, 0x33, 0x08, 0x34, 0x10, 0x30, 0x08,
0x34, 0x08, 0x33, 0x18, 0x33, 0x08, 0x32, 0x18, 0x32, 0x08, 0x31, 0x30,
0x00, 0x00
};
uchar code music3[] = //歌曲为孤勇者
{
0x16,0x08,0x17,0x08,
0x21,0x08,0x22,0x08,
0x17,0x08,0x21,0x08,
0x21,0x10,0x21,0x08,
0x17,0x08,0x21,0x08,
0x22,0x08,0x17,0x08,
0x21,0x08,0x21,0x10,
0x21,0x08,0x22,0x08,
0x23,0x08,0x22,0x08,
0x23,0x08,0x22,0x08,
0x23,0x10,0x23,0x08,
0x22,0x08,0x23,0x10,
0x25,0x10,0x23,0x10,
0x16,0x08,0x17,0x08,
0x21,0x08,0x22,0x08,
0x17,0x08,0x21,0x08,
0x21,0x10,0x21,0x08,
0x17,0x08,0x21,0x08,
0x22,0x08,0x17,0x08,
0x21,0x08,0x21,0x10,
0x21,0x08,0x22,0x08,
0x23,0x08,0x22,0x08,
0x23,0x08,0x22,0x08,
0x23,0x10,0x23,0x08,
0x22,0x08,0x23,0x10,
0x25,0x10,0x23,0x10,
0x25,0x10,0x23,0x14,
0x25,0x08,0x23,0x14,
0x25,0x08,0x23,0x08,
0x25,0x08,0x26,0x08,
0x23,0x08,0x25,0x10,
0x25,0x08,0x23,0x14,
0x25,0x08,0x23,0x14,
0x25,0x08,0x23,0x08,
0x25,0x08,0x26,0x08,
0x23,0x08,0x25,0x10,
0x25,0x08,0x25,0x08,
0x23,0x08,0x22,0x08,
0x22,0x10,0x22,0x10,
0x21,0x08,0x23,0x08,
0x23,0x08,0x22,0x08,
0x22,0x10,0x22,0x10,
0x21,0x08,0x21,0x08,
0x16,0x20,0x25,0x08,
0x25,0x08,0x23,0x08,
0x22,0x08,0x22,0x10,
0x22,0x10,0x21,0x08,
0x23,0x08,0x23,0x08,
0x22,0x08,0x22,0x10,
0x22,0x10,0x21,0x08,
0x21,0x08,0x16,0x20,
0x00
};
uchar code quzi[] = //此数组数据为各个音符在定时器中的重装值,第一列是高位,第二列是低位 //时间
{
0xf8,0x8c, //低八度,低1
0xf9,0x5b,
0xfa,0x15, //低3
0xfa,0x67,
0xfb,0x04, //低5
0xfb,0x90,
0xfc,0x0c, //低7
0xfc,0x44, //中央C调
0xfc,0xac, //中2
0xfd,0x09,
0xfd,0x34, //中4
0xfd,0x82,
0xfd,0xc8, //中6
0xfe,0x06,
0xfe,0x22, //高八度,高1
0xfe,0x56,
0xfe,0x6e, //高3
0xfe,0x9a,
0xfe,0xc1, //高5
0xfe,0xe4,
0xff,0x03 //高7
};
/**********************
函数名称:void delay(unsigned int xms)
功能描述:延时
入口参数:xms:输入需要延时的毫秒值
出口参数:无
备注:
***********************/
void delay(unsigned int xms)
{
uint i,j;
for(i=xms; i>0; i--)
for(j=124; j>0; j--);
}
/**********************
函数名称:uchar quyin(uchar tem)
功能描述:在quzi数组中,找到music数组定义的简谱音符的重装值,并返回其在quzi数组中的位置
入口参数:tem:music数组中定义的简谱音符
出口参数:返回的是tem音符在quzi数组中的位置值
备注:
***********************/
uchar quyin(uchar tem)
{
uchar qudiao,jp,weizhi; //定义曲调,音符和位置
qudiao=tem/16; //高4位是曲调值
jp=tem%16; //低4位是音符
if(qudiao==1) //当曲调值为1时,即是低八度,低八度在quzi数组中基址为0
qudiao=0;
else if(qudiao==2) //当曲调值为2时,即是中八度,中八度在quzi数组中基址为14
qudiao=14;
else if(qudiao==3) //当曲调值为3时,即是高八度,高八度在quzi数组中,基址为28
qudiao=28;
weizhi=qudiao+(jp-1)*2; //通过基址加上音符作为偏移量,即可定位此音符在quzi数组中的位置
return weizhi; //返回这一个位置值
}
/**********************
函数名称:void playmusic()
功能描述:播放音乐
入口参数:无
出口参数:无
备注:
***********************/
void playmusic()
{
uchar p,m,tem; //m为节拍
while(1)
{
if(flag==1) //若播放的标志位为1则播放音乐
{
if(gequ==0) //歌曲选择位为0,则播放同一首歌
{
p=music1[jindu];
if(p==0x00) //如果碰到结束符,延时1秒,回到开始再来一遍
{
jindu=0;
delay(1000);
break;
}
else if(p==0xff) //若碰到休止符,延时100ms,继续取下一音符
{
jindu=jindu+1;
delay(100);
TR0=0;
break;
}
else //正常情况下取音符和节拍
{
tem=quyin(music1[jindu]); //取出当前音符在quzi数组中的位置值
timeh=quzi[tem]; //把音符相应的计时器重装载值赋予timeh和timel
timel=quzi[tem+1];
jindu++;
TH0=timeh; //把timeh和timel赋予计时器
TL0=timel;
m=music1[jindu]; //取得节拍
jindu++;
}
TR0=1; //开定时器1
delay(m*180); //等待节拍完成, 通过P3^4口输出音频
TR0=0; //关定时器1
beep=0; //使beep端口置0,起保护蜂鸣器作用
}
else if(gequ==1) //歌曲选择位为1,则播放小毛驴
{
p=music2[jindu];
if(p==0x00) //如果碰到结束符,延时1秒,回到开始再来一遍
{
jindu=0;
delay(1000);
break;
}
else if(p==0xff) //若碰到休止符,延时100ms,继续取下一音符
{
jindu=jindu+1;
delay(100);
TR0=0;
break;
}
else //正常情况下取音符和节拍
{
tem=quyin(music2[jindu]); //取出当前音符在quzi数组中的位置值
timeh=quzi[tem]; //把音符相应的计时器重装载值赋予timeh和timel
timel=quzi[tem+1];
jindu++;
TH0=timeh; //把timeh和timel赋予计时器
TL0=timel;
m=music2[jindu]; //取得节拍
jindu++;
}
TR0=1; //开定时器1
delay(m*300); //等待节拍完成, 通过P3^4口输出音频
TR0=0; //关定时器1
beep=0; //使beep端口置0,起保护蜂鸣器作用
}
else if(gequ==2) //歌曲选择位为2,则播放天空之城
{
p=music3[jindu];
if(p==0x00) //如果碰到结束符,延时1秒,回到开始再来一遍
{
jindu=0;
delay(1000);
break;
}
else if(p==0xff) //若碰到休止符,延时100ms,继续取下一音符
{
jindu=jindu+1;
delay(100);
TR0=0;
break;
}
else //正常情况下取音符和节拍
{
tem=quyin(music3[jindu]); //取出当前音符在quzi数组中的位置值
timeh=quzi[tem]; //把音符相应的计时器重装载值赋予timeh和timel
timel=quzi[tem+1];
jindu++;
TH0=timeh; //把timeh和timel赋予计时器
TL0=timel;
m=music3[jindu]; //取得节拍
jindu++;
}
TR0=1; //开定时器1
delay(m*200); //等待节拍完成, 通过P3^4口输出音频
TR0=0; //关定时器1
beep=0; //使beep端口置0,起保护蜂鸣器作用
}
}
else //播放标志位不为1时,暂停播放音乐
while(flag!=1);
}
}
/**********************
函数名称:void init_sys()
功能描述:系统初始化,功能是配置IO口
入口参数:无
出口参数:无
备注:
***********************/
void init_sys()
{
P0M0=0xff; //设置推挽模式
P0M1=0x00;
P2M0=0x08;
P2M1=0x00;
P3M0=0x10;
P3M1=0x00;
P4M0=0x00;
P4M1=0x00;
P5M0=0x00;
P5M1=0x00;
}
/**********************
函数名称:void init()
功能描述:定时器和外部中断的初始化
入口参数:无
出口参数:无
备注:
***********************/
void init()
{
TMOD=0x01; //设置定时器0,定时方式1,16位手动重装模式
TH0=0xD8; //设置定时初值
TL0=0xEF;
IE=0x87; // 1000 0111 EA=1,EX0=1,ET0=1,EX1=0;
IP=0x02; // 0000 0010 PT0=1; 定时器0优先级高
TR0=0; //定时器0开始运行
beep=0; //使beep端口置0,起保护蜂鸣器作用
}
void main()
{
init_sys(); //系统初始化
init();
P0=0x00;
key1=1; //两个按键设为输入状态,检测中断
key2=1;
flag=0; //播放标志位清零
while(1)
{
playmusic(); //播放音乐函数
}
}
/**********************
函数名称:void tim1() interrupt 1
功能描述:定时器0中断处理,重新装值,并把beep值取反,产生方波
入口参数:无
出口参数:无
备注:
***********************/
void tim1() interrupt 1 //计时器控制频率
{
TH0=timeh; //赋初值
TL0=timel;
beep=~beep; //中断使得beep翻转产生方波
}
/**********************
函数名称:void ex1() interrupt 0
功能描述:按下按键1的外部中断,对标志位取反,功能是暂停和播放音乐
入口参数:无
出口参数:无
备注:
***********************/
void ex1() interrupt 0
{
delay(5);
if(key1==0) //判断key1是否按下
{
delay(5);
if(key1==0)
{
while(!key1);
flag=~flag; //播放中断位取反,播放或者暂停
}
}
}
/**********************
函数名称:void ex2() interrupt 2
功能描述:按下按键2的外部中断,作用为切换歌曲
入口参数:无
出口参数:无
备注:
***********************/
void ex2() interrupt 2
{
delay(5);
if(key2==0) //按键key2按下,切换歌曲
{
jindu=0; //歌曲的进度清零,从头开始演唱
gequ++; //下一曲
if(gequ==3) //到达最后一首调到第一首
gequ=0;
}
}
边栏推荐
- 函数:用牛顿迭代法求方程的根
- 关于交换a和b的值的四种方法
- Interview Essentials: what is the mysterious framework asking?
- Statistics 8th Edition Jia Junping Chapter 2 after class exercises and answer summary
- 内网渗透之内网信息收集(三)
- Apache APIs IX has the risk of rewriting the x-real-ip header (cve-2022-24112)
- Constants, variables, and operators of SystemVerilog usage
- Es full text index
- 王爽汇编语言详细学习笔记二:寄存器
- Function: find the root of the equation by Newton iterative method
猜你喜欢
随机推荐
Fundamentals of digital circuit (IV) data distributor, data selector and numerical comparator
数字电路基础(四) 数据分配器、数据选择器和数值比较器
[pointer] octal to decimal
MySQL中什么是索引?常用的索引有哪些种类?索引在什么情况下会失效?
Bing Dwen Dwen official NFT blind box will be sold for about 626 yuan each; JD home programmer was sentenced for deleting the library and running away; Laravel 9 officially released | Sifu weekly
What level do 18K test engineers want? Take a look at the interview experience of a 26 year old test engineer
5 minutes to master machine learning iris logical regression classification
内网渗透之内网信息收集(三)
Statistics 8th Edition Jia Junping Chapter 2 after class exercises and answer summary
Fundamentals of digital circuit (V) arithmetic operation circuit
Statistics 8th Edition Jia Junping Chapter XIII Summary of knowledge points of time series analysis and prediction and answers to exercises after class
函数:计算字符串中大写字母的个数
【指针】八进制转换为十进制
Overview of LNMP architecture and construction of related services
How to use Moment. JS to check whether the current time is between 2 times
Zhejiang University Edition "C language programming experiment and exercise guide (3rd Edition)" topic set
Fundamentals of digital circuits (I) number system and code system
Database monitoring SQL execution
函数:字符串反序存放
Lintcode logo queries the two nearest saplings