当前位置:网站首页>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;
}
}
边栏推荐
- The salary of testers is polarized. How to become an automated test with a monthly salary of 20K?
- Don't you even look at such a detailed and comprehensive written software test question?
- “Hello IC World”
- 使用 flask_whooshalchemyplus jieba实现flask的全局搜索
- Quaternion -- basic concepts (Reprint)
- [pointer] counts the number of times one string appears in another string
- With 27K successful entry ByteDance, this "software testing interview notes" has benefited me for life
- 《统计学》第八版贾俊平第一章课后习题及答案总结
- [issue 18] share a Netease go experience
- [pointer] the array is stored in reverse order and output
猜你喜欢
数字电路基础(五)算术运算电路
Keil5-MDK的格式化代码工具及添加快捷方式
Wang Shuang's detailed learning notes of assembly language II: registers
Intranet information collection of Intranet penetration (3)
ES全文索引
C language do while loop classic Level 2 questions
《统计学》第八版贾俊平第四章总结及课后习题答案
Soft exam information system project manager_ Project set project portfolio management --- Senior Information System Project Manager of soft exam 025
Statistics 8th Edition Jia Junping Chapter 5 probability and probability distribution
《统计学》第八版贾俊平第三章课后习题及答案总结
随机推荐
“Hello IC World”
我的第一篇博客
With 27K successful entry ByteDance, this "software testing interview notes" has benefited me for life
《统计学》第八版贾俊平第三章课后习题及答案总结
SystemVerilog discusses loop loop structure and built-in loop variable I
【指针】求字符串的长度
Summary of thread implementation
New version of postman flows [introductory teaching chapter 01 send request]
Statistics 8th Edition Jia Junping Chapter 4 Summary and after class exercise answers
Get started with Matplotlib drawing
Es full text index
Cadence physical library lef file syntax learning [continuous update]
《統計學》第八版賈俊平第七章知識點總結及課後習題答案
{1,2,3,2,5}查重问题
浙大版《C语言程序设计实验与习题指导(第3版)》题目集
[issue 18] share a Netease go experience
函数:计算字符串中大写字母的个数
Detailed introduction to dynamic programming (with examples)
【指针】删除字符串s中的所有空格
ByteDance ten years of experience, old bird, took more than half a year to sort out the software test interview questions