电路原理图如下:
单片机源程序如下:
- sfr P4=0xe8;// 定义 P4组 I0 口
- #include<reg51.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit speaker=P1^4;// 喇叭接 30 脚
- sbit key1=P1^0;// 流水灯按键 (暂时)
- sbit key2=P1^1;// 播放音乐按键(暂定)
- uchar a,b,num1,s1num,n1,n2;
- char num;// 定义 num为可以负数
- uchar code yinfu[]={0xfb,0xe9, //Do
- 0xfc,0x5c, //Re
- 0xfc,0xc1, //Mi
- 0xfc,0xef, //Fa
- 0xfd,0x45, //So
- 0xfd,0x92, //La
- 0xfd,0xd0, //Si
- 0xfd,0xee, //Do#
- 0x00,0x00, // 间隔
- };
- uchar code shengri_tone[]={ 1,0,1,2,1,4,3,0, // 生日快乐音调
- 1,0,1,2,1,5,4,0,
- 1,0,1,8,6,4,3,2,0,
- 7,0,7,6,4,5,4,0 //0 代表不发声,即停顿;数字即为音调
- };
- uchar code shengri_beat[]={ 24,1,24,48,48,48,72,5,// 节拍
- 24,1,24,48,48,48,72,5,
- 24,1,24,48,48,48,48,72,5,
- 24,1,24,48,48,48,72,5 // 节拍,即tone 表各音调的延时
- };
- uchar code ledtable[]={0x7f,0xbf,0xdf,0xef, // 取反
- 0xf7,0xfb,0xfd,0xfe};//P0 组口的发光二极管代码(焊接过程可能会相反,具体更改)
- uchar code ledtable2[]={0x7f,0xbf,0xdf,0xef, // 取反
- 0xf7,0xfb,0xfd,0xfe};//P2 组口发光二极管代码 , 相反!
- void check_key();// 改为 P3组为按键
- void keyscan();
- void turn();// 顺时针流动
- void back();
- void qianhou();
- void dangshuang();
- void delay(uint z);// 延时函数声明
- void delay1(void);// 声明第二个延时函数
- void play1(void);// 播放生日快乐
- void main()
- {
- s1num=0;// 流水灯种类标志
- key1=1;
- key2=1;
- TMOD=0x01;
- TH0=a;
- TL0=b;
- ET0=1;// 打开定时器,但是未允许中断
- TR0=1;
- while(1)
- {
- check_key();
- keyscan();
- }
- }
- void time0() interrupt 1
- {
- TH0=a;
- TL0=b;
- speaker=~speaker;
- }
- void check_key()
- {
- P3=0xff;// 先赋给 P2组口高电平
- switch(P3)// 按下一个键相应 4 个灯亮
- {
- case 0xfe:P0=0xee;P2=0x77;a=0xfb;b=0xe9;EA=1;break;//P0,P2 组为发光二极管组
- case 0xfd:P0=0xdd;P2=0xbb;a=0xfc;b=0x5c;EA=1;break;// 注意: EA不能改为 TR0
- case 0xfb:P0=0xbb;P2=0xdd;a=0xfc;b=0xc1;EA=1;break;
- case 0xf7:P0=0x77;P2=0xee;a=0xfc;b=0xef;EA=1;break;
- case 0xef:P0=0xee;P2=0x77;a=0xfd;b=0x45;EA=1;break;
- case 0xdf:P0=0xdd;P2=0xbb;a=0xfd;b=0x92;EA=1;break;
- case 0xbf:P0=0xbb;P2=0xdd;a=0xfd;b=0xd0;EA=1;break;
- case 0x7f:P0=0x77;P2=0xee;a=0xfd;b=0xee;EA=1;break;
- default:EA=0;speaker=0;//P0=0xff;P2=0xff ;
- }
- }
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void keyscan()
- {
- if(key1==0)
- {
- delay(5);
- if(key1==0)
- {
- s1num++;
- while(!key1);
- if(s1num==1)
- {
- turn();
- }
- }
- if(s1num==2)
- {
- back();
- }
- if(s1num==3)
- {
- qianhou();
- }
- if(s1num==4)
- {
- dangshuang();
- }
- if(s1num==5)
- s1num=1;
- }
- if(key2==0)
- {
- delay(5);
- while(~key2);
- play1();
- }
- }
- void delay1(void)// 第二个延时函数
- {
- uchar n=15;
- while(n--)
- {
- uchar i;
- for(i=0;i<125;i++);
- }
- }
- void play1(void)// 播放生日快乐
- {
- uchar m=0;
- uchar s;
- uchar c=1;
- P0=0xaa;
- P2=0x55;
- while(1)
- {
- EA=0;
- c=shengri_tone[m]; // 取音符
- s=shengri_beat[m]; // 取节拍
- a=yinfu[2*c-2];
- b=yinfu[2*c-1];
- EA=1;
- while(s--)
- {
- delay1();
- P0=~P0;
- P2=~P2;
- }
- m++;
- if(m>=33) return; // 数值是 shengri相关表中的元素数量
- }
- }
- /* 以下为 N种流水灯流动花式 */
- void turn()// 流水灯顺时针走动( 5 次)
- {
- for(num1=0;num1<8;num1++)
- {
- for(num=0;num<8;num++)
- {
- P0=ledtable[num];
- delay(30);// 时间暂定
- }
- P0=0xff;// 之后关闭 P1组
- for(num=7;num>-1;num--)
- {
- P2=ledtable2[num];
- delay(30);
- }
- P2=0xff;// 之后关闭 P2组
- }
- }
- void back()// 逆时针流动
- {
- for(num1=0;num1<8;num1++)
- {
- for(num=0;num<8;num++)
- {
- P2=ledtable[num];
- delay(30);
- }
- P2=0xff;
- for(num=7;num>-1;num--)
- {
- P0=ledtable2[num];
- delay(30);
- }
- P0=0xff;
- }
- }
- void qianhou()// 前后来回
- {
- for(num1=0;num1<10;num1++)
- {
- for(num=0;num<8;num++)
- {
- P0=ledtable[num];
- P2=ledtable2[num];
- delay(30);
- }
- P0=0xff;
- P2=0xff;
- for(num=7;num>-1;num--)
- {
- P0=ledtable[num];
- P2=ledtable2[num];
- delay(30);
- }
- P0=0xff;
- P2=0xff;
- }
- }
- void dangshuang()// 单数双数
- {
- for(num1=0;num1<15;num1++)
- {
- P0=0x55;
- P2=0xaa;
- delay(150);
- P0=0xaa;
- P2=0x55;
- delay(150);
- }
- }
复制代码
原理图是png图片格式的,以上程序的Keil格式文件下载:已删除
|