找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 27087|回复: 39
收起左侧

基于单片机的电子琴设计

  [复制链接]
ID:93478 发表于 2015-10-31 21:49 | 显示全部楼层 |阅读模式
功能如下:
1.通过按键能够发出相应的音符并播放产生乐音,实现演奏;
2.演奏的同时可数字显示当前的音调,利于培养乐感
3.可以选定播放固定乐曲自动演奏,演奏时LED进行节拍指示;
4.在自动演奏和奏乐的过程中按停止键则中断演奏;
  5.可以选择调节音或小。
采用stc89c52单片机作为核心器件,实现基本的音乐弹奏、音乐播放、音调显示和音乐节拍指示的功能。
1.音乐弹奏:通过程序识别4x4矩阵键盘中按下的键的坐标(x,y),
然后根据(x,y)从计数初值表中读取对应的计数初值,赋值给定时器0,定时器产生对应频率的方波,达到播放对应音调的功能。
2.音乐播放:先建立一个包含一首音乐的音调与节拍的表。其中,音调就是0x01(低音、do)、0x12(中音、re)、0x23(高音、mi)之类的数;节拍就是0x02(半拍),0x04(一拍)之类的数。然后,根据音调读取计数初值,再将计数初值赋给定时器T0 -> 开启定时器T0 -> 读取节拍并延时 -> 关闭定时器T0 。这样就发出了一个音,然后再读下一个音的初值与节拍,重复上一个操作即可。(具体实现方法见附录总程序)
3.数码管显示音调:
① 按键:读出按键坐标(x,y),用if语句来判断(x,y)该给数码管赋什么值,然后从uchar code num[] 表中读取这个值赋给数码管(例如P0)。
② 播放歌曲时:读入音调,根据音调的值来判断num这个表中的i,再把num赋给P0口。
4.led灯的节拍指示:采用定时器1来控制,作为节拍指示。
①按键时:根据按下的时长来控制led的点亮个数,并且是按一定的时间间隔逐个点亮;释放按键时,led灯按一定的时间间隔逐个熄灭,从而达到一种比较简单的节拍指示效果。
②播放音乐时:根据音符的节拍,控制点亮到哪一个灯,在点亮那个灯之前,前面的灯逐个等时距点亮。音符结束后,led灯全部一起熄灭。这样,达到了一个精确显示节拍的效果。
整体结构一一的去攻破,节拍什么的东西都是在网上直接搜一下就可以找到所要曲子的节拍和拍子,分享给大家

EEJN`@2E2PDJH6D@$4B}6[R.png
{17]}C2(G9V}9[[FIZD@I9S.png
68FO9IRVKH6HNTP@8TQI6PG.png

电子琴程序.zip

6.08 KB, 下载次数: 299, 下载积分: 黑币 -5

评分

参与人数 5黑币 +70 收起 理由
cai764127922 + 5 共享资料的黑币奖励!
西瓜味的美年达 + 5 绝世好帖!
s979462478 + 5 赞一个!
唐宋元明清 + 5 绝世好帖!
admin + 50 共享资料的积分奖励!

查看全部评分

回复

使用道具 举报

ID:95100 发表于 2015-12-5 14:48 来自手机 | 显示全部楼层
大神,可以把这个电子琴的代码给我一下吗,我下了没办法看
回复

使用道具 举报

ID:93478 发表于 2015-12-6 09:16 来自手机 | 显示全部楼层
1246173372 发表于 2015-12-5 14:48
大神,可以把这个电子琴的代码给我一下吗,我下了没办法看


#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int

#define allsong 4  //歌曲总数 按实际写

sbit P1_0 = P1^0;
sbit P1_1 = P1^1;
sbit P1_2 = P1^2;
sbit P1_3 = P1^3;
sbit P1_4 = P1^4;
sbit P1_5 = P1^5;
sbit P1_6 = P1^6;
sbit P1_7 = P1^7;
sbit beep = P3^0;
sbit key_play = P3^1;

uchar x = 0; /*矩阵键盘横坐标 从1开始 0为未按下的标志 */
uchar y = 0; /*矩阵键盘纵坐标 从1开始 0为未按下的标志 */
uchar flash = 0;//控制led灯显示的变量 */
uchar f_l;   /*按键发出音调的初值(低位)*/
uchar f_h; //高位
uchar song_l;/*歌曲音调的初值(低位)*/
uchar song_h;//高位  

uchar out = 0;/*声音输出变量 1表示有输出 0表示无输出 */
uchar yindiao;/*音调 定义为全局变量 为了在播放时数码管能显示当前音调*/
uchar yindiao_h;//音调的高四位
uchar yindiao_l;//音调的低四位
uchar jiepai;/*节拍(简而言之就是一个音调响的时间长度)*/
uchar song_id = 1;//歌曲序号变量
uchar temp_id = 1;//歌曲临时序号
uint which = 2;/*简谱表里的第几个音 从第2个开始  第0个用来存曲速,第1个占位*/
uchar same = 0; /*在暂停时选了同一首歌曲,用于跳出暂停循环*/

uchar key_x();  //获取键盘横坐标 函数
uchar key_y();//获取键盘纵坐标 函数
void play(); //播放歌曲 函数
void delayms(uint ms);//延时xx ms 函数
void delay(uint pai);//节拍延时 函数
void key_check(); //检查按键状态 函数
void display(); //数码管显示对应音调 函数
void speak();/*按键后 给定时器0赋对应音调的初值 从而发出声音*/
uchar choose();/*播放状态下 选歌函数 释放按键后才跳出函数,返回歌曲序号*/
uchar choose2();/*暂停状态下 选歌函数 不用释放按键即可跳出函数,返回歌曲序号 */
void play();//播放歌曲 函数

uchar code num[]={0x00,//数码管段选码
0x77,0x7c,0x39,0x5e,0x79,0x71,0x3d, //a - g
0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, //1 - 7
0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87 //1. - 7.
};

uchar code led_table[]={0xff,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00};/*发光二极管闪烁表*/

uchar code chuzhi[]={  //音调对应的计数初值
0xff,0xff,//占0位
0xf8,0x8c,//低1 (0x01)a -数码管显示方式
0xf9,0x5b,//  2 b
0xfa,0x15,//  3 c
0xfa,0x67,//  4 d
0xfb,0x04,//  5 e
0xfb,0x90,//  6 f
0xfc,0x0c,//低7(0x07)g
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /*占位 0x08 - 0x0b  (8 - 11)*/
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,/*占位 0x0c - 0x10(12 - 16)*/
0xfc,0x44,//中1 (0x11)  (17)
0xfc,0xac,//  2
0xfd,0x09,//  3
0xfd,0x34,//  4
0xfd,0x82,//  5
0xfd,0xc8,//  6
0xfe,0x06,//中7 (0x17)  (23)
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /*占位 0x18 - 0x1b   (24 - 27)*/
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /*占位 0x1c - 0x20 (28 - 32)*/
0xfe,0x22,//高1 (0x21)1.   (33)
0xfe,0x56,//2 2.
0xfe,0x85,//3 3.
0xfe,0x9a,//4 4.
0xfe,0xc1,//5 5.
0xfe,0xe4,//6 6.
0xff,0x03 //高7 (0x27)7.   (39)
};

uchar code ymt[]={//玉满堂
0x96,0x00, //曲速 0x96表示 150拍/分
0x00,0x0a,0x05,0x02,0x15,0x02,0x12,0x02,
0x13,0x04,0x13,0x02,0x15,0x02,0x12,0x04,0x12,0x02,0x13,0x02,
0x12,0x10,
0x13,0x04,0x13,0x02,0x12,0x02,0x13,0x04,0x15,0x02,0x16,0x02,
0x15,0x0c,0x13,0x02,0x15,0x02,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x04,0x15,0x02,0x13,0x02,
0x15,0x0c,0x15,0x02,0x16,0x02,
0x21,0x04,0x21,0x02,0x22,0x02,0x23,0x04,0x22,0x02,0x21,0x02,
0x22,0x10,
0x23,0x08,0x15,0x02,0x16,0x02,0x21,0x02,0x22,0x02,
0x23,0x04,0x23,0x02,0x22,0x02,0x21,0x06,0x21,0x02,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x04,0x13,0x04,
0x15,0x10,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x04,0x21,0x02,0x22,0x02,
0x23,0x04,0x23,0x02,0x22,0x02,0x21,0x06,0x21,0x02,
0x16,0x02,0x21,0x02,0x16,0x02,0x21,0x02,0x22,0x02,0x23,0x02,0x25,0x02,0x23,0x02,
0x22,0x0c,0x21,0x02,0x22,0x02,
0x23,0x06,0x15,0x02,0x16,0x02,0x21,0x02,0x22,0x02,
0x23,0x04,0x23,0x02,0x22,0x02,0x21,0x06,0x21,0x02,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x02,0x21,0x02,0x15,0x02,0x13,0x02,
0x15,0x0c,0x13,0x02,0x15,0x02,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x04,0x16,0x02,0x21,0x02,
0x22,0x04,0x22,0x02,0x23,0x02,0x22,0x04,0x22,0x02,0x23,0x02,
0x25,0x02,0x26,0x02,0x23,0x02,0x25,0x02,0x22,0x02,0x23,0x02,0x21,0x02,0x16,0x02,
0x21,0x10,

0xff
};
uchar code dl[]={  //蝶恋  
0x8c,0x00, //曲速 0x8c表示 140拍/分
0x13,0x04,0x13,0x04,0x13,0x04,0x12,0x04,0x13,0x08,
0x12,0x04,0x13,0x04,0x12,0x04,0x12,0x04,0x06,0x08,
0x06,0x04,0x07,0x04,0x11,0x08,0x12,0x04,0x11,0x04,0x07,0x08,0x06,0x04,0x05,0x04,0x06,0x10,
0x13,0x04,0x13,0x04,0x13,0x04,0x12,0x04,0x13,0x0c,
0x16,0x04,0x15,0x04,0x16,0x04,0x15,0x04,0x15,0x04,0x12,0x04,
0x12,0x04,0x13,0x04,0x14,0x08,0x15,0x04,0x14,0x04,0x13,0x04,0x12,0x04,0x11,0x04,0x13,0x0f,0x13,0x0c,
0x13,0x04,0x16,0x08,0x17,0x04,0x16,0x04,0x15,0x0c,0x13,0x04,0x15,0x0f,
0x13,0x04,0x15,0x04,0x12,0x08,0x16,0x04,0x15,0x04,0x13,0x08,0x12,0x04,0x12,0x04,0x13,0x0c,
0x12,0x08,0x16,0x04,0x16,0x0c,
0x11,0x08,0x16,0x04,0x16,0x08,
0x16,0x04,0x17,0x04,0x21,0x08,0x17,0x04,0x16,0x04,0x17,0x08,0x16,0x04,0x17,0x04,0x13,0x08,0x13,0x0c,
0x13,0x04,0x16,0x08,0x17,0x08,0x16,0x04,0x15,0x0c,0x13,0x04,0x15,0x10,
0x14,0x04,0x15,0x04,0x16,0x08,0x17,0x04,0x16,0x04,0x17,0x08,
0x16,0x04,0x17,0x04,0x13,0x10,0x13,0x10,
0x12,0x08,0x16,0x04,0x16,0x02,0x16,0x10,
0x11,0x04,0x16,0x04,0x16,0x02,0x16,0x08,
0x16,0x04,0x17,0x04,0x21,0x08,0x17,0x04,0x16,0x04,0x17,0x08,0x15,0x08,0x16,0x10,
0x23,0x04,0x22,0x04,0x22,0x04,0x21,0x04,0x21,0x04,0x17,0x04,0x17,0x04,0x16,0x04,
0x21,0x04,0x17,0x04,0x17,0x04,0x16,0x04,0x16,0x04,0x15,0x04,0x15,0x04,0x14,0x04,
0x16,0x04,0x15,0x04,0x15,0x04,0x14,0x04,0x14,0x04,0x13,0x04,0x13,0x04,0x12,0x04,
0x13,0x10,0x13,0x10,
0xff
};

uchar code srkl[]={//生日快乐
0x78,0x00, //曲速 120
0x15,0x02,0x15,0x02,
0x16,0x04,0x15,0x04,0x21,0x04,
0x17,0x04,0x00,0x04,0x15,0x02,0x15,0x02,
0x16,0x04,0x15,0x04,0x22,0x04,
0x21,0x08,0x15,0x02,0x15,0x02,
0x25,0x04,0x23,0x04,0x21,0x04,
0x17,0x04,0x16,0x08,
0x16,0x04,0x00,0x04,0x24,0x02,0x24,0x02,
0x23,0x04,0x21,0x04,0x22,0x04,
0x21,0x08,
0x21,0x08,0x00,0x08,
0x15,0x02,0x15,0x02,//第二遍
0x16,0x04,0x15,0x04,0x21,0x04,
0x17,0x04,0x00,0x04,0x15,0x02,0x15,0x02,
0x16,0x04,0x15,0x04,0x22,0x04,
0x21,0x08,0x15,0x02,0x15,0x02,
0x25,0x04,0x23,0x04,0x21,0x04,
0x17,0x04,0x16,0x08,
0x16,0x04,0x00,0x04,0x24,0x02,0x24,0x02,
0x23,0x04,0x21,0x04,0x22,0x04,
0x21,0x08,
0x21,0x08,0x00,0x04,
0xff
};
uchar code test[]={//测试
0x78,0x00, //曲速 0x78表示 120拍/分
0x01,0x04,0x02,0x04,0x03,0x04,0x04,0x04,0x05,0x04,0x06,0x04,0x07,0x04,0x00,0x04,
0x11,0x08,0x12,0x07,0x13,0x06,0x14,0x05,0x15,0x04,0x16,0x03,0x17,0x02,0x00,0x01,
0x21,0x01,0x22,0x02,0x23,0x03,0x24,0x04,0x25,0x05,0x26,0x06,0x27,0x07,0x00,0x08,
0xff,
};


void delayms(uint ms)  /*ms 等于1时,延时1ms 等于2时,延时2ms,以此类推*/
{
uchar a,b,c;   //+3
while(ms--)
   {
for(c=1;c>0;c--)// 1+2 = 3
       for(b=142;b>0;b--)  //1*( 1+142*2)) = 285
           for(a=2;a>0;a--);// 142*(1+2*2) = 710
}
}

void delay(uint pai)/*pai 是节拍  pai若定义成uchar类型,当节拍>0x0c时,会造成数据溢出,产生失真。*/
{
uchar a,b,c;

while(pai--)//延迟pai 个 6.25ms
{
    for(c=1;c>0;c--)   //1+2=3
   for(b=28;b>0;b--)// 1*(1+28*2)  =57
       for(a=110;a>0;a--);//28*(1+110*2) = 6188
}

}

uchar key_x()   /*P1口高位接纵坐标(P1.7 - P1.4) 低位接横坐标(P1.3 - P1.0)*/
{
uchar i;
P1 = 0x0f; /*有按键按下后 对应按键的横坐标电位被拉低( 注意低电位引脚不能被高电位引脚抬高,只能是低电位拉低高电位)*/
if(P1_0 == 0)
{delayms(5); //延时5ms 去抖动
if(P1_0 == 0)
i = 1;
}
else if(P1_1 == 0)
{delayms(5);
if(P1_1 == 0)
i = 2;
}
else if(P1_2 == 0)
{delayms(5);
if(P1_2 == 0)
i = 3;
}
else if(P1_3 == 0)
{delayms(5);
if(P1_3 == 0)
i = 4;
}
else
i = 0;
return (i);//0表示按键未按下
}

uchar key_y()
{
uchar j;
P1 = 0xf0;
if(P1_4 == 0)
{delayms(5);
if(P1_4 == 0)
j = 1;
}
else if(P1_5 == 0)
{delayms(5);
if(P1_5 == 0)
j = 2;
}
else if(P1_6 == 0)
{delayms(5);
if(P1_6 == 0)
j = 3;
}
else if(P1_7 == 0)
{delayms(5);
if(P1_7 == 0)
j = 4;
}
else
j = 0;
return (j);
}

void key_check() /*检查矩阵按键坐标、播放键的状态及播放键状态设置*/
{
x = key_x();
y = key_y();

if(key_play == 0)
key_play = 0; /*保持播放键引脚低电平,让其作为歌曲正在播放的标志*/
else
key_play = 1; /*保持播放键引脚高电平,让其作为歌曲未播放的标志*/
}

void display() /*数码管显示相应的音调*/
{
if(key_play == 1)  //按键弹奏时
{if(x != 0 && y != 0 )
{
if(x == 1)
P0 = num[3 + y] ;  //低音4 - 7
else if(x == 2)
P0 = num[7 + y];  //中音1 - 4
else if(x == 3)
P0 = num[11 + y];  //中音5 - 7 和 高音 1
else if(x == 4)
P0 = num[15 + y];  //高音2 - 5
}
else
P0 = 0x00;
}
else  //播放音乐时
{if(yindiao_h == 0)  /* yindiao变量的高四位表示 低(0) 中(1) 高(2) 音*/
P0 = num[yindiao_l];/*yindiao变量的低四位表示“调”, 数码管显示当前音调*/
else if(yindiao_h == 1) //中音
  P0 = num[yindiao_l + 7];
else if(yindiao_h == 2) //高音
P0 = num[yindiao_l + 14];
}

}

void speak()/* 按键 ,为定时器0 T0 赋计数初值,让 T0函数驱动蜂鸣器发出对应的音调 */
{
if(x == 1)
{
f_h = chuzhi[2*y + 6];  //低音4 - 7
f_l = chuzhi[2*y + 6 + 1];
}
else if(x == 2)
{
f_h = chuzhi[(16+y)*2]; //中音 1 -4
f_l = chuzhi[(16+y)*2 +1];
}
else if(x == 3)
{
if(y <= 3)
{
f_h = chuzhi[(20+y)*2]; //中音 5 - 7  
f_l = chuzhi[(20+y)*2 + 1];
}
else
{
f_h = chuzhi[66]; //高音1
f_l = chuzhi[67];
}
}
else if(x == 4)
{
f_h = chuzhi[(33+y)*2];  //高音2 -5
f_l = chuzhi[(33+y)*2 + 1];
}

}
void timer0() interrupt 1  //定时器0  
{
if(key_play == 0)
{
TL0 = song_l;
TH0 = song_h;

beep = ~beep;
}
else
if(x != 0 && y != 0 && key_play == 1)/*当有矩阵按键按下,并且不播放歌曲时 */
{
TL0 = f_l;//赋初值
TH0 = f_h;//
beep = ~beep; /*蜂鸣器引脚电平取反,定时器每溢出一次电平取反一次,不同的计数初值对应不同的溢出时间,对应不同的方波频率 */
}
}

void timer1() interrupt 3 //定时器1 led灯起落
{
TL1 = 0x00;
TH1 = 0x54;/*定时器1 高8位初值。控制led灯的起落快慢(数值不严格)*/

if(key_play == 1) //不播放歌曲时
{
if(x != 0 && y != 0 && flash < 8 )//最大加到8
++flash;
else if(x == 0 && y == 0 && flash >0 )  //最小减到0
--flash;

P2 = led_table[flash];
}
else if(key_play == 0 )   //播放歌曲时
{
if(out == 1 && flash < 8 && flash < jiepai)/*out ==1 表示有歌曲发声时,(flash<jiepai)使 led灯刚好指示节拍*/
++flash;
else if(out == 0 && flash > 0)
--flash;

P2 = led_table[flash];

}
}

uchar choose()//播放状态下 选歌
{
uchar i = 0;   //第i首歌 初值0表示未选歌
uchar j;

x = key_x();
y = key_y();

if(x == 1 && y == 1)
    i = 1;//选第一首
else if(x == 1 && y == 2)
   i = 2; //选第二首
else if(x == 1 && y == 3)
  i = 3;
else if(x == 1 && y == 4)
i = 4;
else if(x == 2 && y == 1)
i = 5;
else if(x == 4 && y == 1)// 上一首
i = 13;   
else if(x == 4 && y == 2)//用作暂停播放
i = 14;   
else if(x == 4 && y == 3)//下一首
i = 15;
else if(x == 4 && y == 4)
i = 16;//用作停止播放


if(i == song_id)
{
which = 2; //选同一首歌时,重播这首歌
}
else if(i > allsong && i < 13)/*如果按键号 在 最大歌曲序号 和 功能键 之间,返回原歌曲序号*/
i = song_id;//
else if(i == 0) //i等于初值 说明未按键
i = song_id; //不按键选歌时,返回原歌曲的序号

while(1)//释放按键时才进行下一步
{
x = key_x();
y = key_y();

if(x == 1)
j = y;
else if(x == 2)
j = 4 + y;
else if(x == 3)
j = 8 + y;
else if(x == 4)
j = 12 + y;

if(x == 0 || (j > allsong && j < 13))  /*释放按键 或者按键号 在 最大歌曲序号 和 功能键 之间时 跳出循环*/
break;
}

return(i);
}

uchar choose2()/*选歌不用放开按键  在暂停的状态下使用 */
{
uchar i = 0;

  x = key_x();
y = key_y();

if(x == 1 && y == 1)//选第一首
  i = 1;
else if(x == 1 && y == 2)//选第二首
   i = 2;
else if(x == 1 && y == 3)
  i = 3;
else if(x == 1 && y == 4)
i = 4;
else if(x == 2 && y == 1)
i = 5;
else if(x == 4 && y == 1)// 上一首
i = 13;   
else if(x == 4 && y == 2)//用作暂停播放
i = 14;   
else if(x == 4 && y == 3)//下一首
i = 15;
else if(x == 4 && y == 4)
i = 16;//用作停止播放

if(i == song_id)
{
same = 1;
which = 2; /*选了同一首歌时,重播这首歌(0,1用来存曲速了 故从2开始)  */
}
else if(i > allsong && i < 13)/*如果按键号 在 最大歌曲序号 和 功能键 之间,返回原歌曲序号*/
i = song_id;
else if(i == 0)   //i等于初值 说明未按键
i = song_id; /*不按键选歌时,返回原歌曲的序号*/

return(i);
}

void play()//播放歌曲
{  
  uint qusu;//歌曲播放速度 (拍/分)
  uint pai2; /*pai2 = (2400/qusu)*jiepai; 送到delay()函数*/

while(1)
{
while(1)
{
choose_id:
   temp_id = choose(); //选歌

/****************************↓↓↓↓↓暂停↓↓↓↓↓*****************************************/
  if(temp_id == 14) //如果按下暂停键
  {  
  delayms(500);//延时500ms
  while(1)
{
temp_id = choose2();/*choose2 按下就起作用 不必等到放开按键才起作用*/
if(temp_id == 14)  /*再次按下“暂停键” 表示继续播放*/
{
break;
}
else if(temp_id == 16)/*按下停止键 ,功能表现为:暂停播放时也能停止播放,回到播放前状态*/
{
song_id = 16;
break;
}
else if(temp_id == 13)//上一首
{
which = 2;
if(song_id == 1)
song_id = allsong ;//播放最后一首
else
--song_id;
break;
}
else if(temp_id == 15) //下一首
{
which = 2;
if(song_id == allsong)
song_id = 1;   //播放第一首
else
++song_id;
break;
}
else if(temp_id != song_id && temp_id <= allsong)/*选了另一首歌曲 屏蔽掉了未定义的按键*/
{
which = 2;   /*从歌曲的第一个音播放 (0,1用来存曲速了 故从2开始)*/
song_id = temp_id;
break;
}
else if(same == 1)
break;
}
same = 0; //跳出循环后 需重置为0
  }
/****************************↑↑↑↑↑暂停↑↑↑↑↑***************************************/
else if(temp_id == 13)//上一首
{
which = 2;
if(song_id == 1)
song_id = allsong ;//播放最后一首
else
--song_id;
}
else if(temp_id == 15) //下一首
{
which = 2;
if(song_id == allsong)
song_id = 1;   //播放第一首
else
++song_id;
}
else if(temp_id == 16)
{
song_id = 16;
}
else if(temp_id != song_id && temp_id <= allsong) //选了另一首歌曲
{
which = 2;   //从歌曲的第一个音播放
song_id = temp_id;
}
/**************************************************************************************/
nochoose://不用选歌 当正常放完一首歌时,跳到这里
if(song_id == 3)
{key_play = 0;
if(srkl[which] == 0xff) /* 遇到结束符  跳出循环(内循环) 停止播放 */
break;
qusu = srkl[0];
yindiao = srkl[which]; //音调
jiepai = srkl[which+1]; //节拍
}
else
if(song_id == 1)
{key_play = 0;
if(ymt[which] == 0xff) /* 遇到结束符  跳出循环(内循环) 停止播放 */
break;
qusu = ymt[0];
yindiao = ymt[which]; //音调
jiepai = ymt[which+1];  //节拍
}
else
if(song_id == 2)
{ key_play = 0;
if(dl[which] == 0xff) /* 遇到结束符 跳出循环 停止播放 */
break;
qusu = dl[0];
yindiao = dl[which]; //
jiepai = dl[which+1];   //
}
else if(song_id == 4)
  {
  key_play = 0;
if(test[which] == 0xff) /* 遇到结束符 跳出循环 停止播放*/
break;
qusu = test[0];
yindiao = test[which];
jiepai = test[which+1];  
  }
/******************************************************************************/
else if(song_id == 16 )
  {  
  which = 2;
  break;
  }
else
  {
  key_play = 1;
  goto choose_id;   /*如果既没有选歌 又没有停止 返回去做选择*/
  }
/********************************************************************************************/
yindiao_l = yindiao % 16;// 低四位 调
yindiao_h = yindiao /16;/*高四位 。。是低音0 中音1 还是 高音2*/


if(yindiao != 0) /*音调不为0。(当音调为0时表示这个音不响 但依旧要占这个音的播放时间)*/
{
song_h = chuzhi[yindiao*2];
song_l = chuzhi[yindiao*2+1];

TR0 = 1;   /*给初值赋值后,开启定时器0 蜂鸣器开始发声 */
TR1 = 1;/*开启定时器1  ,led开始闪动*/
display(); //数码管显示音调
out = 1;   /*正在发声的标志,定时器1得以控制led灯按一定的时间间隔 逐个点亮 */
}
else
{
TR0 = 0;
out = 0;
TR1 = 0;
P0 = 0x00;
flash = 0;
P2 = led_table[0];
}

pai2 = (2400/qusu)*jiepai;
delay(pai2); /*延时 = 节拍数 x 125ms  (决定着1个音的发声时间) */
TR0 = 0;//蜂鸣器停止发声
P0 = 0x00;
out = 0;

delayms(39); /*唱完一个音停xx ms(决定每个音调之间的时间间隔 根据个人喜好节奏来定 */

TR1 = 0;  //led停止闪动
flash = 0;
P2 = led_table[0];
which = which + 2;//下一个音

}  /*已经放完一首歌,或者停止播放,接下来判断是停止播放还是播放下一首  */

TR0 = 0;
P0 = 0x00;
out = 0;
flash = 0;
P2 = led_table[0];

if(song_id == 16) /*坐标(4,4)的键盘作为停止播放键*/
{
while(1)
{
x = key_x();
if(x == 0)
break;/*松开按键 才结束 避免触发其他程序 比如电子琴发声、led显示等*/
}

key_play = 1; /*播放键引脚置高电平,播放结束的标志*/
song_id = 1;  // 第一首歌开始
which = 2;  // 每首歌的最开始的一个音
break; /*跳出第二个循环(即结束play函数)*/
}
else if(song_id == allsong)/*当放到最后一首时,从第一首开始   (当前共3首)  */
{
song_id = 1;
which = 2;
delayms(1000); //一秒后从第一首开始播放
goto nochoose;
}
else  
{
++song_id; /*歌曲序号自动+1 自动播放下一首歌*/
which = 2;
delayms(1000);
goto nochoose;//不用选歌 播放下一首
}
}
}

void main()
{
P0 = 0x00;
P2 = 0xff;
TMOD = 0x11; /*定时器0 定时器1 都采用方式1(16位定时器方式) */
IE = 0x8a;
PT0 = 1; /*设置定时器0为高优先级,避免被定时器1干扰,造成声音失真*/

while(1)
{

key_check();
if(key_play == 1 && x != 0 && y != 0)
{
TR1 = 1;
display();
speak();
TR0 = 1;
}
else  if(key_play == 0)
{
key_play = 0;
play(); /*play函数有循环语句,当按下停止键(16键)时才能跳出 */
}
else
{
if(flash == 0)/*当flash 减到0时 再关闭定时器1,即 让led灯全部熄灭再关闭T1  */
TR1 = 0;

TR0 = 0;
P0 = 0x00;
}
}
}
回复

使用道具 举报

ID:64089 发表于 2015-12-28 10:23 | 显示全部楼层
Good ,我学习一下按键音调的编程思想,很好。
回复

使用道具 举报

ID:134300 发表于 2016-7-23 21:09 | 显示全部楼层
大神,如果要换歌代码怎么换算,很多歌曲代码换过来就不能用了
回复

使用道具 举报

ID:129008 发表于 2016-7-24 00:42 | 显示全部楼层
题主能提供清晰的原理图吗,你这个图看不清元件参数
回复

使用道具 举报

ID:150634 发表于 2016-11-27 21:38 | 显示全部楼层
大神 能给个清晰的电路原理图吗,我想照做一个,可是看不清楚原件参数
回复

使用道具 举报

ID:150634 发表于 2016-11-27 21:41 | 显示全部楼层
rosam_zhang 发表于 2016-7-24 00:42
题主能提供清晰的原理图吗,你这个图看不清元件参数

你有上面那个电子琴的电路图了不  能看清原件参数的
回复

使用道具 举报

ID:130231 发表于 2017-3-11 21:32 | 显示全部楼层
我下载来看看。
回复

使用道具 举报

ID:130231 发表于 2017-3-11 21:43 | 显示全部楼层
上面电路图我看的不是清楚,有清楚点的吗
回复

使用道具 举报

ID:183991 发表于 2017-3-27 23:16 | 显示全部楼层
求助清晰原理图
回复

使用道具 举报

ID:166841 发表于 2017-3-28 09:38 | 显示全部楼层
有没有清晰得原理图
回复

使用道具 举报

ID:165068 发表于 2017-3-28 11:17 | 显示全部楼层
谢谢。最近正在做类似的东西,给了很多启发,谢谢、
回复

使用道具 举报

ID:200093 发表于 2017-5-12 20:43 | 显示全部楼层
谢谢大神
回复

使用道具 举报

ID:110278 发表于 2017-5-22 10:01 | 显示全部楼层
很实用。可以试看看。
回复

使用道具 举报

ID:213533 发表于 2017-6-21 22:20 | 显示全部楼层
有点6666
回复

使用道具 举报

ID:218611 发表于 2017-7-12 21:03 | 显示全部楼层
求清晰原理图
回复

使用道具 举报

ID:218611 发表于 2017-7-12 21:12 | 显示全部楼层
大神不在线,好惆怅
回复

使用道具 举报

ID:218611 发表于 2017-7-12 21:52 | 显示全部楼层
学长,桂电的啊,你几级的,我想用你的来做课设,苦涩笑
回复

使用道具 举报

ID:219457 发表于 2017-7-13 17:48 来自手机 | 显示全部楼层
好强大

评分

参与人数 1黑币 +5 收起 理由
还恋一个人 + 5 很给力!

查看全部评分

回复

使用道具 举报

ID:261683 发表于 2017-12-18 19:21 | 显示全部楼层
希望发一个清晰的原理图
回复

使用道具 举报

ID:274077 发表于 2018-1-10 00:26 | 显示全部楼层
围观大佬
回复

使用道具 举报

ID:333064 发表于 2018-5-31 14:57 | 显示全部楼层
好贴,支持一下
回复

使用道具 举报

ID:345148 发表于 2018-6-5 08:16 | 显示全部楼层
好资料 感谢楼主分享
回复

使用道具 举报

ID:285652 发表于 2018-6-24 12:35 | 显示全部楼层
好贴支持一下
回复

使用道具 举报

ID:357774 发表于 2018-6-24 14:26 | 显示全部楼层
很不错,支持一下,给力
回复

使用道具 举报

ID:387592 发表于 2018-8-31 16:05 | 显示全部楼层
大神可以发一下生成的hex文件给我吗?QQ邮箱1638078283@qq.com
回复

使用道具 举报

ID:387592 发表于 2018-8-31 16:32 | 显示全部楼层
电压大小??
回复

使用道具 举报

ID:493035 发表于 2019-3-18 10:50 | 显示全部楼层
谢谢大神!!!
回复

使用道具 举报

ID:482729 发表于 2019-3-19 09:14 | 显示全部楼层
绝世好帖!
回复

使用道具 举报

ID:399179 发表于 2019-3-20 20:36 | 显示全部楼层
真的好强大!
回复

使用道具 举报

ID:493822 发表于 2019-3-24 18:23 | 显示全部楼层
谢谢大佬
回复

使用道具 举报

ID:399179 发表于 2019-3-26 09:04 来自手机 | 显示全部楼层
这个能不能发出钢琴的音啊?
回复

使用道具 举报

ID:511461 发表于 2019-6-13 20:10 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:614806 发表于 2019-10-10 16:35 | 显示全部楼层
求清晰电路图
回复

使用道具 举报

ID:588278 发表于 2019-12-6 15:37 | 显示全部楼层
有清楚点的原理图吗?
回复

使用道具 举报

ID:658466 发表于 2019-12-7 20:43 | 显示全部楼层
受教了
回复

使用道具 举报

ID:652972 发表于 2019-12-7 22:24 来自手机 | 显示全部楼层
仿真图不清楚啊
回复

使用道具 举报

ID:103311 发表于 2019-12-10 00:34 | 显示全部楼层
谢谢大佬
回复

使用道具 举报

ID:961300 发表于 2021-11-19 14:41 | 显示全部楼层
原理图有清晰点的吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表