八音盒程序和与原理图见附件
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg52.h>
- #include<intrins.h>
- #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!='\0')
- {
- lcd_wdat(discode[i]);
- i++;
- }
- lcd_pos(0x40);
- i=0;
- while(dis[i]!='\0')
- {
- lcd_wdat(dis[i]);
- i++;
- }
- }
- void int_init(void)
- {
- TMOD=0x01;
- ET0=1;//允许Timer0中断
- EX0=1;//允许INT0中断
- IT0=1; //INT0为边沿触发
- EX1=1;
- IT1=1;
- EA=1;
- TR0=0; //Timer0停止
- }
- void main(void)
- {
- int_init();
- song_Tone=song1_Tone;
- song_Time=song1_Time;
- discode=dis1;
- lcd_init();
- while(1)
- {
- LCD_disp();
- Tone_index=song_Tone[i];
- if(Tone_index==0xFF)
- {
- i=0;
- TR0=0;
- }
- TR0=1;
- delayms(song_Time[Tone_index]*60);
- TR0=0
- i++
- }
- }
复制代码
所有资料51hei提供下载:
《流水灯音乐盒》.rar
(806.82 KB, 下载次数: 84)
|