51电子琴,附带仿真
单片机源程序如下:
- //////////////////////////////////////////////////////////////////////////////////
- // 功能描述 : OLED 4接口
- // ----------------------------------------------------------------
- // GND 电源地
- // VCC 接5V或3.3v电源
- // SCL P1^0
- // SDA P1^1
- // ----------------------------------------------------------------
- // K9 P1^2;//音乐播放按键
- // KD P1^3;//低音播放
- // KG P1^4;//高音播放
- // beep P1^5; //蜂鸣器定义
- //******************************************************************************/
- #include "REG52.h"
- #include "oled.h"
- #include "bmp.h"
- #include <music.h>
- #define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
- #define uint unsigned int //无符号整型 宏定义 变量范围0~65535
- sbit K9=P1^2;//音乐播放按键2
- sbit KD=P1^3;//低音播放
- sbit KG=P1^4;//高音播放
- sbit beep=P1^5; //蜂鸣器定义
- sbit K10=P1^6;//录入指示
- sbit K11=P1^7;//休止符
- sbit K12=P3^2;//播放录入的
- sbit K13=P3^3;//
- unsigned char n=0,m=0,k=0; //定义取频率常数m和节拍常数n 数组元素编号k
- unsigned char music_load[]={ 8,2,9,2,10,2,11,2,12,2,12,2,12,1,11,1,10,2,11,2,11,2,11,1,10,1,9,1,0xff,8,2,10,2,12,4,0};
- void delay(uchar i)//用于OLED显示
- {
- uchar j,u,v;
- for(j=i;j>0;j--)
- for(u=125;u>0;u--)
- for(v=125;v>0;v--);
- }
-
- void delayms(unsigned char j) //毫秒延时子程序 用于播放音乐
- {
- while(--j); //采用while(--j) 不要采用while(j--); 各位可编译一下看看汇编结果就知道了!
- }
-
- void TimerInit()
- {
- TMOD|=0X11;//选择为定时器0/1模式,工作方式1,仅用TR0/1打开启动。
- TH1=0x0b; //节拍用
- TL1=0xdc;
- IE=0x8A;//1000,1010打开EA/ET1/ET0
- }
- /******************按键程序*************************/
- void oled_menu()//4功能
- {
-
- OLED_ShowNum(0,0,1,1,16);//1234
- OLED_ShowNum(0,2,2,1,16);
- OLED_ShowNum(0,4,3,1,16);
- OLED_ShowNum(0,6,4,1,16);
-
- OLED_ShowCHinese(10,0,7);//单音播放
- OLED_ShowCHinese(28,0,8);
- OLED_ShowCHinese(46,0,9);
- OLED_ShowCHinese(64,0,10);
-
- OLED_ShowCHinese(10,2,9);//播放音乐
- OLED_ShowCHinese(28,2,10);
- OLED_ShowCHinese(46,2,11);
- OLED_ShowCHinese(64,2,12);
-
- OLED_ShowCHinese(10,4,13);//录入音乐
- OLED_ShowCHinese(28,4,14);
- OLED_ShowCHinese(46,4,11);
- OLED_ShowCHinese(64,4,12);
-
- OLED_ShowCHinese(10,6,9);//播放录入音乐
- OLED_ShowCHinese(28,6,10);
- OLED_ShowCHinese(46,6,13);
- OLED_ShowCHinese(64,6,14);
- OLED_ShowCHinese(82,6,11);
- OLED_ShowCHinese(100,6,12);
-
- }
- void oled_start()//欢迎使用林天羽
- {
- OLED_ShowCHinese(26,0,0);//欢迎使用
- OLED_ShowCHinese(46,0,1);//
- OLED_ShowCHinese(66,0,2);//
- OLED_ShowCHinese(86,0,3);//
-
- OLED_ShowCHinese(36,4,4);//林天羽
- OLED_ShowCHinese(56,4,5);//
- OLED_ShowCHinese(76,4,6);//
-
- OLED_ShowString(12,6,"2016330301081",16);
-
- delay(150);
- OLED_Clear();
- oled_menu();
- }
- void load_music() //录入功能--对应28个音,1个休止符自动1/4拍,末尾自动添加停止符号
- {
- uint i,j,temp;
- uchar ky=0,kj=0,kp=0; //定义数组元素编号ky,kj,kp,休止符次数kp
- music_load[0]=0;//保存第一个元素为0,按键时复写,并要求下一个元素为0
- while(K10==0)
- {
- start2:
- temp = P2;
- j=3;//C调
- if(KD==0)j=4;//低音
- else if(KG==0)j=2;//高音
- if(KG==0&&KD==0)j=1;//更高音
- if(K11==0)//休止符1/4
- {
- delayms(5);
- if((ky+kj)%2==0)//如果此时需要输入音调,则直接用休止符代替
- {
- OLED_ShowCHinese(80,0,16);//休止符
- OLED_ShowCHinese(96,0,17);
- OLED_ShowCHinese(112,0,18);
- music_load[ky+kj+kp]=0xff;//保存休止符为0xff
- music_load[ky+kj+kp+1]=0;
- kp++;
- while(K11==0);P0=0;OLED_ShowCHinese(80,0,15);OLED_ShowCHinese(96,0,15);OLED_ShowCHinese(112,0,15);
- }
- else if((ky+kj)%2==1)//如果此时需要输入节拍,则节拍默认1/4,外加1/4休止
- {
- OLED_ShowCHinese(80,0,16);//休止符
- OLED_ShowCHinese(96,0,17);
- OLED_ShowCHinese(112,0,18);
- music_load[ky+kj+kp]=1;
- music_load[ky+kj+kp+1]=0xff;//保存休止符为0xff
- music_load[ky+kj+kp+2]=0;
- kj++;
- kp++;
- while(K11==0); P0=0;OLED_ShowCHinese(80,0,15);OLED_ShowCHinese(96,0,15);OLED_ShowCHinese(112,0,15);
- }
- goto start2;
- }
- for(i=0;i<8;i++)
- {
- if(temp==for_P2[i])
- {
- if((ky+kj)%2==0)//音调
- {
- OLED_ShowNum(100,0,1+i,1,16);
- m=7*j-i-1;n=0xff; //取频率常数m=28-mk,mk=music[第一个元素] 和 节拍常数n=4*nk,nk=music[第二个元素]
- music_load[ky+kj+kp]=28-m;//保存
- music_load[ky+kj+kp+1]=4;//自动补齐节拍为一拍
- music_load[ky+kj+kp+2]=0;//确保结束符号
- TR1=1; //开定时器1
- TH0=T_H0[m];
- TL0=T_L0[m];
- while(P2==for_P2[i]) TR0=1; //等待节拍完成, 通过P1口输出音频(可多声道哦!)
- TR0=0;
- TR1=0;
- OLED_ShowCHinese(100,0,15);
- ky++;
- }
- else if((ky+kj)%2==1)//节拍
- {
- /***********************/
- P0=smg_du[1+i];//使数码管显示该音调的字符
- music_load[ky+kj+kp]=i+1;//保存
- music_load[ky+kj+kp+1]=0;
- kj++;
- while(P2==for_P2[i]);
- }
- }
- }
- }
-
- }
- void play_music_load() //按下按键播放单音--一个音阶7个音
- {
- unsigned char i=0,p=0;
- while(1)
- {
- start:
- p=music_load[i];
- if(p==0) //音乐停止标志
- {
- i=0;
- delayms(100);
- goto ending;
- }
- else if(p==0xff) //若碰到休止符,停止1/4拍,用第八个按键输入休止符
- {
- i=i+1;
- n=1;//暂停1/4拍
- P0=smg_du[0];
- OLED_ShowNum(100,0,0,1,16);
- TR1=1;
- while(n!=0);
- TR0=0;
- OLED_ShowCHinese(100,0,15);
- goto start;
- }
- else //取频率常数m和节拍常数n
- {
- m=28-music_load[i++];
- n=8*music_load[i++];
- P0=smg_du[(28-m)%7];
- OLED_ShowNum(100,0,(28-m)%7,1,16);
- }
- TR1=1; //开定时器1
- TH0=T_H0[m];
- TL0=T_L0[m];
- while(n!=0) TR0=1;
- TR0=0;
- TR1=0;
- OLED_ShowCHinese(100,0,15);
- } ending: ;
- }
- int main(void)
- {
- TimerInit();
- OLED_Init(); //初始化OLED
- OLED_Clear();
- oled_start();
- //播放音乐部分
-
- while(1)
- {
- // if(K13==0)key();//1
- // if(K9==0)play_music();
- if(K10==0)load_music();//1
- if(K12==0)play_music_load();
- //OLED_ShowNum(100,0,1+i,1,16);OLED_ShowCHinese(100,0,15);
- }
- }
-
- void int0() interrupt 1 //采用中断0 控制音调
- {
- TH0=T_H0[m];
- TL0=T_L0[m];
- beep=~beep;
- }
- void int1() interrupt 3 //采用中断3 控制节拍 优先级低
- {
- TH1=0x0b;
- TL1=0xdc;
- n--;
- }
复制代码
所有资料51hei提供下载:
51单片机电子琴.rar
(97.26 KB, 下载次数: 27)
|