51單片機(jī)實(shí)現(xiàn)音階,可放歌曲
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
單片機(jī)源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #define keyport P1
- #define out P0
- #define uchar unsigned char
- #define uint unsigned int
- uchar high,low; //定時(shí)器預(yù)裝值的高8位和低8位
- sbit S1 =P1^0; // 按鍵
- uchar keyvalue; // 鍵值
- uchar code name[] ="Chen xin chen";//顯示名字
- uchar code stu_num[] =" 1111120028";//顯示學(xué)號(hào)
- sbit RS = P2^0; // 數(shù)據(jù)或指令控制線
- sbit RW = P2^1; // 讀寫(xiě)控制線
- sbit E = P2^2; //使能控制線
- /*********************
- 延時(shí)函數(shù)
- *********************/
- void delay(uint j)
- {
- uchar i = 250;
- for(;j>0;j--)
- {
- while (--i);
- i= 249;
- while(--i);
- i=250;
- }
- }
- /*********************
- 檢查忙函數(shù),檢查L(zhǎng)CD是否處于忙狀態(tài)
- 如果處于忙則持續(xù)檢查
- *********************/
- void check_busy(void)
- {
- uchar temp;
- do{
- temp =0xff; //
- E = 0;
- RS= 0; //
- RW = 1;
- E =1;
- temp = out; //
- }while(temp&0x80); // 如果 BF =1 則持續(xù)檢查
- E = 0;
- }
- /*********************
- 寫(xiě)命令函數(shù)
- *********************/
- void write_command(uchar com)
- {
- check_busy();// 首先檢查忙
- E= 0;//預(yù)置0
- RS =0;
- RW =0; //按LCD寫(xiě)命令控制信號(hào)設(shè)置
- out = com;
- E =1; // 正脈沖
- _nop_();//
- E = 0; // 還原E
- delay(1);
- }
- /********************
- 寫(xiě)數(shù)據(jù)函數(shù)
- ********************/
- void write_data(uchar com)
- {
- check_busy();
- E=0; //預(yù)置0
- RS= 1;
- RW =0;//按LCD寫(xiě)數(shù)據(jù)控制信號(hào)設(shè)置
- out = com;
- E=1;// 正脈沖
- _nop_();
- E =0;
- delay(1);
- }
- /********************
- LCD初始化函數(shù)
- ********************/
- void lcd_initial(void) //
- {
- write_command(0x38); // 八位數(shù)據(jù),雙列顯示,5X7陣
- _nop_();
- write_command(0x0c); //開(kāi)顯示屏,關(guān)光標(biāo),光標(biāo)不顯示
- _nop_();
- write_command(0x06); //字符不移動(dòng),每次字符地址加1
- _nop_();
- write_command(0x01); //清屏
- _nop_();
- delay(100);
- }
- /********************
- //字符串顯函數(shù)
- ********************/
- void string(uchar add, uchar *s) reentrant
- {
- write_command(add);//顯示地址
- while(*s != '\0')
- {
- write_data(*s++);
- }
- }
- void interrupt_int(void)
- {
- EA =1;//總中斷允許
- EX0 =1;//外部中斷打開(kāi)
- EX1 =1;//
- IT0=1;//負(fù)跳變
- IT1 =1;//
- IP =0;//同一優(yōu)先級(jí)
- }
- void key_1(void) interrupt 0
- {
- EX0 =0;
- lcd_initial();
- string(0x83,name); //第一行第四個(gè)開(kāi)始顯示學(xué)號(hào)
- string(0xc2,stu_num);//第二行第三個(gè)開(kāi)始顯示姓名
- EX0 =1;//開(kāi)啟中斷
- }
- sbit speak=P3^0;
- sbit gao=P3^5;
- sbit di=P3^6;
- sbit zdbf=P3^7;
- uchar yinjie=1;
- uchar time;
- uchar n=0;
- uchar bo=0;
- uchar code fre[][2]= { 0x8c,0xf8,0x5b,0xf9,0x15,0xfa,0x67,0xfa,0x90,0xfb,0xae,0xfb,0x0c,0xfc, //低音
- 0x44,0xfc,0xac,0xfc,0x09,0xfd,0x34,0xfd,0x82,0xfd,0xc2,0xfd,0x06,0xfe, //中音
- 0x22,0xfe,0x56,0xfe,0x85,0xfe,0x9a,0xfe,0xc1,0xfe,0xe4,0xfe,0x03,0xff, //高音
- };
- void delay(uint );
- void ITimer0(void);//定時(shí)器初始化
- void key(void);
- void dtxs(int,int);
- void song()
- {
- TH0=high;
- TL0=low;
- TR0=1;
- delay(time*240);
- }
- void yinyue()//小星星歌曲
- {
- uchar code hls[]={ 1,2,2, 1,2,3, 5,2,2, 5,2,3, 6,2,2, 6,2,3, 5,2,4, 4,2,2, 4,2,3, 3,2,2 ,3,2,3 ,2,2,2, 2,2,3, 1,2,4, 5,2,2, 5,2,3, 4,2,2, 4,2,3, 3,2,2, 3,2,3, 2,2,4, 5,2,2, 5,2,3, 4,2,2, 4,2,3, 3,2,2, 3,2,3, 2,2,4};
- uchar m;
- n=0;
- while(n<174)
- {
- m=hls[n]+7*(hls[n+1]-1)-1;
- high=fre[m][1];
- low=fre[m][0];
- time=hls[n+2];
- n=n+3;
- song();
- }
- }
- void main (void)
- {
-
-
- uchar num;
- ITimer0();
- speak=0;
- interrupt_int();
-
- while(1)
- {
- key();
- switch(keyport)
- {
- case 0xfe:num=1;break;
- case 0xfd:num=2;break;
- case 0xfb:num= 3;break;
- case 0xf7:num= 4;break;
- case 0xef:num= 5;break;
- case 0xdf:num= 6;break;
- case 0xbf:num= 7;break;
- case 0x7f:num= 8;break;
- default:num= 0;break;
- }
- if(num==0)
- {
- TR0=0;
- speak=0;
- }
- else
- {
- high=fre[7*yinjie+num-1][1];
- low=fre[7*yinjie+num-1][0];
- TR0=1;
- }
- dtxs(yinjie,num);
- }
- }
- void ITimer0(void)
- {
- TMOD |= 0x01; //使用模式1,16位定時(shí)器,使用"|"符號(hào)可以在使用多個(gè)定時(shí)器時(shí)不受影響
- EA=1; //總中斷打開(kāi)
- ET0=1; //定時(shí)器中斷打開(kāi)
- TR0=1; //定時(shí)器開(kāi)關(guān)打開(kāi)
- }
- void Timer0_isr(void) interrupt 1
- {
- TH0=high;
- TL0=low;
- speak=!speak;
- if(zdbf==0)
- {
- delay(100);
- if(zdbf==0)
- {
- bo++;
- if(bo/2==1)
- { delay(100);
- if(n<174)n=500; //n賦值大于174,跳出while,停止音樂(lè)
- else n=0;
- dtxs(3,0);
- }
- if(bo%2==0)
- { delay(100);
- n=500; //n賦值大于174,跳出while,停止音樂(lè)
- }
- }
- }/**/
- }
- void key()//按鍵
- {
- if(zdbf==0)
- {delay(100);
- if(zdbf==0)
- yinyue();
- }
- if(gao==0)
- {
- delay(100);
- if(gao==0)
- {
- delay(100);
- if(yinjie==2)
- yinjie=1;
- else yinjie=2;
- }
- }
- if(di==0)
- {
- delay(100);
- if(di==0)
- {
- delay(100);
- if(yinjie==0)
- yinjie=1;
- else yinjie=0;
- }
- }
- }
- void dtxs(k,l)//k是按鍵號(hào),l是工作方式
- {
- char seg[14]={ 0x3F,/*0*/
- 0x06,/*1*/
- 0x5B,/*2*/
- 0x4F,/*3*/
- 0x66,/*4*/
- 0x6D,/*5*/
- 0x7D,/*6*/
- 0x07,/*7*/
- 0x7F,/*8*/
- 0x6F,/*9*/
- 0x37,/*N*/
- 0x38,/*L*/
- 0x76,/*H*/
- 0x79
- };
- P2=0x01;//選擇第一個(gè)數(shù)碼管
- P0=seg[l];//顯示按鍵號(hào)
- delay(4);
- P2=0x02;//選擇第二個(gè)數(shù)碼管
- P0=seg[k+10];//顯示工作方式
- delay(4);
- }
復(fù)制代碼
所有資料51hei提供下載:
仿真.7z
(100.06 KB, 下載次數(shù): 23)
2021-4-11 22:45 上傳
點(diǎn)擊文件名下載附件
|