基于STC89C52单片机的简易电子琴(课程设计) 下载本文

XG=Length/10; //算出音符类型(0普通1连音2顿音) FD=Length/100; LDiv=LDiv0/SLen; //算出连音音符演奏的长度(多少个10ms) if (FD==1) LDiv=LDiv+LDiv/2; if(XG!=1) if(XG==0) //算出普通音符的演奏长度 if (SLen<=4) LDiv1=LDiv-LDiv4; else LDiv1=LDiv*SOUND_SPACE; else LDiv1=LDiv/2; //算出顿音的演奏长度 else LDiv1=LDiv; if(SL==0) LDiv1=0; LDiv2=LDiv-LDiv1; //算出不发音的长度 if (SL!=0) { TR0=1; for(i=LDiv1;i>0;i--) //发规定长度的音 { while(TF1==0); TH1 = Sound_Temp_TH1; TL1 = Sound_Temp_TL1; TF1=0; } } if(LDiv2!=0) { TR0=0; beep=1; for(i=LDiv2;i>0;i--) //音符间的间隔 { while(TF1==0); TH1 = Sound_Temp_TH1; TL1 = Sound_Temp_TL1; TF1=0; } } Point+=2; Tone=Sound[Point]; Length=Sound[Point+1]; }

beep = 0;

1

TR0=0;//关闭定时器 }

//键盘矩阵扫描

//返回按下的键的值

unsigned char keys_scan(void) { unsigned char Tmp,k=16; P2=0x0F; delay_1ms(2); Tmp=P2 ^ 0x0F; switch(Tmp)//确定扫描的是哪一行 { case 1: k=0;break; case 2: k=1;break; case 4: k=2;break; case 8: k=3;break; default: return 16; //无键按下,返回 } P2=0xF0; delay_1ms(2); Tmp=(P2>>4)^0x0F; switch(Tmp)//确定扫描的是那一列 { case 1: k+=0; break; case 2: k+=4; break; case 4: k+=8; break; case 8: k+=12;break; default: return 16; //无键按下,返回 } return k; }

void main() //主程序 { unsigned char key_NO=0; P1=0xFF; //数码管显示关闭 //设置定时器工作方式1,以及相关开启寄存器 TMOD |= 0x11; ET0 = 1; ET1 = 0; TR0 = 0; TR1 = 0; EA = 1; //设置定时器初值

1

TH0=tone_delay_table[key_NO]/256; TL0=tone_delay_table[key_NO]%6; TH1 = (65535-50000)/256;// 计算TL1应装入的初值 (10ms的初装值) TL1 = (65535-50000)%6; while(1) { P2=0xF0; if(P2!=0xF0)//当有按键按下时,需要显示数码管及设置定时器的开启 { key_NO=keys_scan();//调用键盘扫描 P1=DSY_CODE[key_NO];//在数码管上显示按下的键 if(key_NO<15)//按下那个键,发出对应的音调 { Sound_Temp_TH0=tone_delay_table[key_NO]/256; Sound_Temp_TL0=tone_delay_table[key_NO]%6; } else if(key_NO==15)//按下最后一个键时,要播放音乐 { Play(Music, 0, 3, 300); //TR1 = 0;//音长中断 } TR0=1;//开启定时器0,音符中断 } else//当没有键按下时,数码管不显示,也无声音发出;如果是播放音乐,则一直显示 { TR0=0;//关闭定时器 P1=0xFF;//数码管显示关闭 } delay_1ms(2);//稍做延时,可以避免误判断 } }

//音符发生的中断

void play_tone() interrupt 1 { TH0=Sound_Temp_TH0; TL0=Sound_Temp_TL0; beep=~beep; }

1