单片机八音盒程序
2020-12-16 来源:51hei
单片机源程序如下:
#include #include #define uhar unsigned char #define uint unsigned int sbit key1=P3^2;//定义按key1可切换花样 sbit key2=P3^3;//定义按key2可切换歌曲 sbit fm=P3^5;//蜂鸣器连续的IO口,接蜂鸣器的管脚 sbit rs=P2^0; sbit rw=P2^1; sbit ep=P2^2; uchar i; uchar Tong_index=0;//音乐片段索引音符索引 uchar song_index=0; uchar *discode;//暂存LCD需要显示的歌名 uchar *song_Tone,*song_Time; uchar code dis1[]={'song1'};//第一首歌名,dis1~dis4位LCD第一行要显示的歌名; uchar code dis2[]={'song2'}; uchar code dis3[]={'song3'}; uchar code dis4[]={'song4'}; uchar code dis[]={'K1:Down K2:Up'}; //第二行显示的内容 uint code Tong_tab[]={62018,62401,62491,62895,63184,63441,63506,63773, 63965,64137,64215,64360,64488,64603,64654,64751,64836,64876,64948,65012,65067,65535}; //---------------------------简谱--------------------------------------- //编程规则:字节高位是简谱,低位是持续时间,代表多少个十六分音符。 //1-7代表中央C调,8-E代表高八度,0代表停顿 //最后的0是结束标志 //uchar code song1_Tone[]={ // 歌曲1的演奏音符 //11,9,11,14,12,14,12,11,11,7,8,9,8,7,8, //11,9,11,14,13,12,14,11,11,7,8,9,6,7, //12,14,14,13,12,13,14,12,13,14,12,12,11,10,7,8, //11,9,11,14,13,12,14,11,11,8,9,10,6,7,0xff};//结束标志 //uchar code song1_Time[]={ // 歌曲1的节拍频率 //4,2,2,8,4,2,2,8,4,2,2,4,2,2,12, //4,2,2,4,2,4,4,8,4,2,2,4,2,12, //4,4,8,4,2,2,8,2,2,2,2,2,2,2,2,16, //4,2,2,4,2,4,4,8,4,2,2,4,2,12,0xff}; //uchar code song2_Tone[]={ // 歌曲2的演奏音符 //7,8,9,7,7,8,9,7,9,10,11,9,10,11, //11,12,11,10,9,7,11,12,11,10,9,7,7,4,7,7,4,7,0xff};//结束标志 //uchar code song2_Time[]={ // 歌曲2的节拍频率 //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,0xff}; //uchar code song3_Tone[]={ // 歌曲3的演奏音符 //7,7,7,8,9,9,9,9,10,11,12,12,11,10,9,11,11,8,9,7, //7,7,7,8,11,9,9,9,10,11,12,12,11,10,9,11,11,8,9,7,0xff};//结束标志 //uchar code song3_Time[]={ // 歌曲3的节拍频率 //2,2,2,2,4,2,2,2,2,4,2,2,2,2,4,2,2,2,2,4, //2,2,2,2,4,2,2,2,2,4,2,2,2,2,4,2,2,2,2,5,0xff}; //uchar code song4_Tone[]={ // 歌曲4的演奏音符 //5,9,9,9,9,8,7,8,7,6,5,12,12,12,12,12,11, //2,11,11,10,9,9,12,12,11,9,8,7,8,7,6,5,9, //2,7,7,6,5,9,8,7,6,4,12,0xff};//结束标志 //uchar code song4_Time[]={ // 歌曲4的节拍频率 //2,2,2,2,2,2,2,2,2,2,8,2,2,2,2,4,2, //2,2,2,2,8,2,2,2,2,4,2,2,2,2,2,4,2, //2,2,2,2,4,2,2,2,2,2,8,0xff}; void delayms(uint ms) { uchar a; while(ms--) { for(a=230;a>0;a--); } } uchar Busy_Check(void)//测试LED忙碌状态 { uchar LCD_Status; rs=0; rw=1; ep=1 _nop_(); _nop_(); _nop_(); _nop_(); LCD_Status=P0&0x80; ep=0; return LCD_Status; } void led_wemd(uchar cmd)//写入指令数据到LCD { while(Busy_Check()); rs=0; rw=0; ep=0; _nop_() _nop_() P0=cmd; _nop_() _nop_() _nop_() _nop_() ep=1; _nop_() _nop_() _nop_() _nop_() ep=0; } void lcd_pos(uchar pos) { lcd_wcmd(pos|0x80); } void lcd_wdat(uchar dat) { while(Busy_Check()); rs=0; rw=0; ep=0; _nop_() _nop_() P0=cmd; _nop_() _nop_() _nop_() _nop_() ep=1; _nop_() _nop_() _nop_() _nop_() ep=0; } void lcd_init(void) //lcd初始化设定 { lcd_wcmd(0x38); //设置显示格式为16*2行显示,5*8点阵,8位 delay(1); lcd_wcmd(0x0C); //0x0c-显示开关设置 delay(1); lcd_wcmd(0x06); //0x06读写后指针+1 delay(1); lcd_wcmd(0x01);//清除lcd显示内容 } //----------------------------简谱音调对应的定时器初值--------------------------- //适合11.0592M的晶振,对定时器置入的初值 uchar code cuzhi[]={ 0xff,0xff,//占位用的,没有实际的意义 0xFC,0x8E,//中央C调1-7 0xFC,0xED, 0xFD,0x43, 0xFD,0x6A, 0xFD,0xB3, 0xFD,0xF3, 0xFE,0x2D, 0xFE,0x47, //高八度1-7 0xFE,0x76, 0xFE,0xA1, 0xFE,0xC7, 0xFE,0xD9, 0xFE,0xF9, 0xFF,0x16 }; uchar yinyue[]={0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0x0,0x0}; //将音调转化为对应的LED样式 void delay1(uint z); //延时1MS void delay(uint z); //延时165MS,即十六分音符 void song(); void beep();//蜂鸣器叫一声 void int0() interrupt 0 { delayms(100); if(INT0==0) { TR0=0; if(song_index>5) { song_index=5; } else{song_index++;} if(song_index==1) {temp=songl[i];discode=dis2;} if(song_index==2) {temp=song2[i];discode=dis3;} if(song_index==3) {temp=song3[i];discode=dis4;} if(song_index==4) {temp=song4[i];discode=dis1;song_index=0;} TR0=1; i=0; } } void int1() interrupt 2 //外部中断1 { delayms(100); if(INT1==0) { TR1=0; if(song_index<1) { song_index=0; } else{song_index--;} if(song_index==1) {temp=song[i];discode=dis2;} if(song_index==2) {temp=song2[i];discode=dis3;} if(song_index==3) {temp=song3[i];discode=dis4;} if(song_index==4) {temp=song4[i];discode=dis1;song_index=0;} TR0=1; i=0; } } //---------------.按照51单片机的中断向量顺序编的号,也是缺省状态下的优先级------------ //外部中断0 interrupt 0 //定时器0 interrupt 1 //外部中断1 interrupt 2 //定时器1 interrupt 3 //串口中断 interrupt 4 //定时器2 interrupt 5 void timer0() interrupt 1 //用于产生各种音调 定时器0 { TH0=Tone_tab[Tone_index]/256;//重置T0定时初值 TL0=Tone_tab[Tone_index]%256; fm=~fm; } void LCD_disp(void) { uchar i; lcd_pos(0); i=0; while(discode!='