51單片機實現音階,可放歌曲
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png (30.98 KB, 下載次數: 56)
下載附件
2021-4-11 21:19 上傳
單片機源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #define keyport P1
- #define out P0
- #define uchar unsigned char
- #define uint unsigned int
- uchar high,low; //定時器預裝值的高8位和低8位
- sbit S1 =P1^0; // 按鍵
- uchar keyvalue; // 鍵值
- uchar code name[] ="Chen xin chen";//顯示名字
- uchar code stu_num[] =" 1111120028";//顯示學號
- sbit RS = P2^0; // 數據或指令控制線
- sbit RW = P2^1; // 讀寫控制線
- sbit E = P2^2; //使能控制線
- /*********************
- 延時函數
- *********************/
- void delay(uint j)
- {
- uchar i = 250;
- for(;j>0;j--)
- {
- while (--i);
- i= 249;
- while(--i);
- i=250;
- }
- }
- /*********************
- 檢查忙函數,檢查LCD是否處于忙狀態
- 如果處于忙則持續檢查
- *********************/
- void check_busy(void)
- {
- uchar temp;
- do{
- temp =0xff; //
- E = 0;
- RS= 0; //
- RW = 1;
- E =1;
- temp = out; //
- }while(temp&0x80); // 如果 BF =1 則持續檢查
- E = 0;
- }
- /*********************
- 寫命令函數
- *********************/
- void write_command(uchar com)
- {
- check_busy();// 首先檢查忙
- E= 0;//預置0
- RS =0;
- RW =0; //按LCD寫命令控制信號設置
- out = com;
- E =1; // 正脈沖
- _nop_();//
- E = 0; // 還原E
- delay(1);
- }
- /********************
- 寫數據函數
- ********************/
- void write_data(uchar com)
- {
- check_busy();
- E=0; //預置0
- RS= 1;
- RW =0;//按LCD寫數據控制信號設置
- out = com;
- E=1;// 正脈沖
- _nop_();
- E =0;
- delay(1);
- }
- /********************
- LCD初始化函數
- ********************/
- void lcd_initial(void) //
- {
- write_command(0x38); // 八位數據,雙列顯示,5X7陣
- _nop_();
- write_command(0x0c); //開顯示屏,關光標,光標不顯示
- _nop_();
- write_command(0x06); //字符不移動,每次字符地址加1
- _nop_();
- write_command(0x01); //清屏
- _nop_();
- delay(100);
- }
- /********************
- //字符串顯函數
- ********************/
- void string(uchar add, uchar *s) reentrant
- {
- write_command(add);//顯示地址
- while(*s != '\0')
- {
- write_data(*s++);
- }
- }
- void interrupt_int(void)
- {
- EA =1;//總中斷允許
- EX0 =1;//外部中斷打開
- EX1 =1;//
- IT0=1;//負跳變
- IT1 =1;//
- IP =0;//同一優先級
- }
- void key_1(void) interrupt 0
- {
- EX0 =0;
- lcd_initial();
- string(0x83,name); //第一行第四個開始顯示學號
- string(0xc2,stu_num);//第二行第三個開始顯示姓名
- EX0 =1;//開啟中斷
- }
- 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);//定時器初始化
- 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位定時器,使用"|"符號可以在使用多個定時器時不受影響
- EA=1; //總中斷打開
- ET0=1; //定時器中斷打開
- TR0=1; //定時器開關打開
- }
- 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,停止音樂
- else n=0;
- dtxs(3,0);
- }
- if(bo%2==0)
- { delay(100);
- n=500; //n賦值大于174,跳出while,停止音樂
- }
- }
- }/**/
- }
- 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是按鍵號,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;//選擇第一個數碼管
- P0=seg[l];//顯示按鍵號
- delay(4);
- P2=0x02;//選擇第二個數碼管
- P0=seg[k+10];//顯示工作方式
- delay(4);
- }
復制代碼
所有資料51hei提供下載:
仿真.7z
(100.06 KB, 下載次數: 23)
2021-4-11 22:45 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|