代码
#include<reg52.h>
sbit BUZZER=P2^0; unsigned char th,tl; unsigned char flag1,flag2; char code table[]={ 0xc0,0xf9,0xa4,0xb0 /*,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xc6,0xa1,0x86,0x8e*/ }; unsigned int TONE[14]={1012,956,852,759,716,638,568,506,478,426,379,1276,1136,1433}; unsigned char code SONG[4][150]={ {5,5,5,5,3,4,5,8,6,6,6,6,8,6,5,5,5,5,5,5,7,6,4,4,4,4,4,4,4,3,2,1,1,8,8,8,8,5,3,8, 8,10,9,9,9,9,8,7,6,6,7,7,7,7,7,8,9,5,7,7,8,9,8,7,8,8,20}, {5,8,6,8,5,3,5,2,3,5,3,5,6,8,5,6,5,3,5,1,3,2,3,2,1,2,3,6,5,3,5,6,5,8,6,5,3,5,2,5,2, 3,2,1,20}, {3,5,8,6,5,3,5,6,8,5,8,10,9,8,9,8,6,8,5,3,5,6,5,6,8,9,5,6,3,2,1,2,2,2,3,5,5,8,2,3, 5,3,5,8,6,5,3,5,6,8,5,8,10,9,8,9,8,6,8,5,3,5,6,5,6,8,9,5,6,3,8,6,5,3,2,1,2,2,3,5,8,10,9,8,9,8,5,6,8,20}, {1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,4,3,1,5,6,5,4,3,1,2,11,1,2,11,1,20} }; unsigned char code BEAT[4][150]={ {4,4,4,4,4,4,8,8,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,8,4,4,4,4,4,2,8,8,4,4,4,4,4,4,8,4,8,4, 4,4,4,2,4,8,8,4,4,4,4,4,4,8,8,4,4,4,4,4,4,8,8}, {8,8,4,4,8,4,4,4,4,8,4,4,4,4,4,4,4,4,4,8,4,8,4,4,4,4,16,4,4,4,4,8,4,4,4,4,4,4,8,4,4,4,4,16}, {4,4,4,4,16,4,4,4,4,16,8,4,8,8,4,4,4,4,16,8,4,8,4,4,8,4,4,16,4,4,8,16,8,4,4,8,8,8,4,4,16,4,4,4,4,16, 4,4,4,4,16,8,4,8,8,4,4,4,4,16,8,4,8,4,4,8,4,4,16,8,4,8,8,4,4,8,16,8,4,16,8,4,8,8,4,4,4,4,16}, {4,4,4,4,4,4,4,4,4,4,8,4,4,8,2,2,2,2,4,4,2,2,2,2,4,4,4,4,8,4,4,8} };
void SET_BUZZER_TONE(unsigned int tone) { TR0=0; //关闭定时器0 //TH0=(65536-tone)/256; //TL0=(65536-tone)%256; th=(65536-tone)/256; tl=(65536-tone)%256; TR0=1 ; //开启定时器0 }
void DELAY_MIN_BEAT (unsigned char x) { unsigned int i,j,k; for (i=0;i<x;i++) { for(j=0;j<100;j++) for(k=0;k<120;k++); } TR0=0;//关闭定时器0 }
void TIME0_INIT() { IE|=0x82; //1000_0010开启总中断并开启定时器0 TMOD=0x01;//定时器О工作在方式1 IP=0x02; //定时器0具有最高优先级 }
void INT_INIT(){ IE|=0x85;//1000_0101开启总中断并开启外部中断0,1 TCON|=0x05;//外部中断0和1负边缘触发 }
void display(char a) { P0=table[a]; }
void main() { char num1,num2; unsigned char flag0; num1=0;//对应递增按钮,即外部中断О num2=0;//对应递减按钮,即外部中断1 flag0=1;//定时器TO中断标志位 flag1=0;//递增中断标志位 flag2=0;//递减中断标志位 BUZZER=0; TIME0_INIT();//定时器初始化 INT_INIT();//外部中断初始化 while(1) { display(num1); while(flag0) //定时器TO中断标志位 { if(SONG[num1][num2]==20) flag0=0; //如果检测到最后一个音调为20,说明此曲应该结束 else { if(flag1==1) //中断检测 { num1++; if(num1>3) num1=0; num2=0; flag1=0; display(num1); } if(flag2==1) //中断检测 { num1--; if(num1<0) num1=3 ;num2=0; flag2=0; display(num1); } SET_BUZZER_TONE(TONE[SONG[num1][num2]]);//音调 DELAY_MIN_BEAT(BEAT[num1][num2]) ;//节拍 num2++; } } num2=0; flag0=1; num1++; if(num1==4) num1=0; } } void T0_TONE(void) interrupt 1 { TH0=th; TL0=tl ; BUZZER=~BUZZER; } void INT0_SELECT(void) interrupt 0{ flag1=1; } void INT1_SELECT(void) interrupt 2{ flag2=1; }
|