51单片机实现音阶,可放歌曲
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #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)
|