制作出来的51单片机矩阵键盘控制播放音乐的实物图如下:
在前人的基础上改进了一下,按键共阳数码管显示,同时控制11个io口,定时播放音乐,按键P2^6是取消定时及播放。
单片机源程序如下:
- #include<reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define GPIO_KEY P1
- #define weixuan P2
- sbit BEEP=P2^5;
- sbit a= P3^7;sbit b= P3^3;sbit c= P3^4;sbit d= P3^5;
- sbit e= P3^6;sbit f= P2^2;sbit g= P2^3;sbit h= P2^4;
- sbit fm=P2^5; sbit key=P2^6;
- //uchar //用于存放定时器的高8
- //0~F的共阳数码管段码,最后一个是黑屏
- const uchar SEG_CODE[] =
- { 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
- 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF
- };
- sbit wei1=P2^0;
- sbit wei2=P2^1;
- sbit led1=P0^7;
- uchar ge,shi,bai;qian;KeyValue,j;timeh,timel;
- char aa=0;
- /*****延时函数*****/
- void delay1ms(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=112;y>0;y--); //12M晶振下,延时1MS
- }
-
- void delay(uchar x)
- {
- uchar i;
- while(x--)
- {
- for (i = 0; i<13; i++) {;}
- }
- }
- void beep()
- {
-
- BEEP=0; //关闭蜂鸣器
- delay(10); //延时
- BEEP=1; }
- /*****显示函数*****/
- void xianshi(uchar k)
- {
- ge=k%10; //个位
- shi=k/10; //十位
- bai=0;
-
- if(k>9)
- {
- weixuan=0xfd;
- P0=SEG_CODE[ge];//个位段选
- delay1ms(10);
- weixuan=0xfe;
- P0=SEG_CODE[shi];//十位段码,显示
- delay1ms(10);
- }
- else
- {
- weixuan=0xfe;
- P0=SEG_CODE[ge];//个位段选
- delay1ms(10);
-
- }
- }
- /***键盘扫描函数***/
- uchar keyscan()
- {
- GPIO_KEY=0x0f; //P1口值准备
- if(GPIO_KEY!=0x0f)
- {
- delay1ms(10); //延时消抖
- if(GPIO_KEY!=0x0f)//再次判断
- {
- GPIO_KEY=0x0f; //再次装值准备
- switch(GPIO_KEY) //测试行
- {
- case(0x07):KeyValue=0;break; //第一行
- case(0x0b):KeyValue=1;break; //第二行
- case(0x0d):KeyValue=2;break; //第三行
- case(0x0e):KeyValue=3;break; //第四行
- }
- GPIO_KEY=0xf0; //高四位赋1,判断准备
- switch(GPIO_KEY) //测试行
- {
- case(0x70):KeyValue=KeyValue; break; //0-3
- case(0xb0):KeyValue=KeyValue+4; break; //4-7
- case(0xd0):KeyValue=KeyValue+8;break; //8-11
- case(0xe0):KeyValue=KeyValue+12;break;//12-15
-
- }
- while((GPIO_KEY!=0x0f)&&(aa<10)) //判断是否松手,假若没有松手,
- //一段延时后依旧判断松手完成
- { beep();
- delay1ms(5);
- aa++;
-
- }
- aa=0;
- }
- }
- return KeyValue;
- }
- uchar code zbjbxf[]=
- { //定义猪八戒背媳妇的简谱数组
- 0x64,0xA3,0xC1,0xA2,0x62,0x84,0x61,0x81,0x61,0xA4,
- 0xA1,0x91,0xA1,0x81,0x64,0xA3,0xC1,0xD2,0xD2,0xD2,
- 0xA2,0xC4,0xA1,0xC1,0xA1,0xC1,0xD2,0xD2,0xD2,0xA2,
- 0xC4,0xC2,0x62,0xC2,0x62,0xA2,0xA2,0x84,0x94,0x94,
- 0x92,0x81,0x91, 0xA2,0xC2,0xD4,0xE4,0xA4,0xE4,0xA2,
- 0xE2,0xA2,0xE2,0xA2, 0xA2,0x84,0x94,0x94,0x92,0x81,
- 0x91,0xA2,0xC2,0xD8
- }; //适合12M 的晶振定时器初值表,高低 位分开
- uchar code chuzhi[]=
- {
- 0xff,0xff,0xFC,0x8E,0xFC, 0xED,0xFD,0x43,0xFD,0x6A,
- 0xFD,0xB3,0xFD,0xF3,0xFE,0x2D,0xFE, 0x47,0xFE,0x76,
- 0xFE,0xA1,0xFE,0xC7,0xFE,0xD9,0xFE,0xF9,0xFF,0x16
- };
- void timer0() interrupt 1 //定时器0中断服务程序
- {
- TH0=timeh;//将timeh 赋给计时器的高8
- TL0=timel;//将timel 赋给计时器的低8
- fm=~fm;
- }//定时器每次到时将蜂鸣器反相
-
- void delay0(uint z)
- { uint y;
- for(z;z>0;z--)
- for(y=19000;y>0;y--);
- }
- void delay1(uint z)
- { uint y;
- for(z;z>0;z--)
- for(y=112;y>0;y--);
- }
- void delay3(unsigned int x)
- {
- unsigned int i;
- while(x--)
- { if(key==0){delay1(5);if(key==0){break;}}
- for(i=0;i<113;i++);
- }
- }
- void play1()
- { uint temp; //存放简谱数组中的每一个音符的临时变量
- uchar jp; //jp 用于取出temp
- uchar i=0;
-
- while(1)
- {
- temp=zbjbxf[i];
- if(temp==0xff) break;
- jp=temp/16;
- if(jp!=0)
- {
- timeh=chuzhi[jp*2];
- timel=chuzhi[jp*2+1];
- TR0=1;//开定时器
- }
- else {TR0=0;fm=1;}
- delay0(temp%16);TR0=0;fm=1; delay1(5); TR0=1;i++;//关定时器
- if(key==0){delay1(5);if(key==0){break;}}
- }
- TR0=0;//关定时器
- fm=1; //关蜂鸣器
- }
- /*****主函数*******/
- void main()
- {
- uchar b;
- a=1; b=1;c=1;d=1;e=1;f=1;g=1;h=1;key=1;
- TMOD=0x01;//设置定时器T0工作于方式1
- IE=0x82; //允许T0 中断
- while(1)
- {
- if((GPIO_KEY!=0x0f)&&(aa<10))
- { delay1ms(10);//aa++;
- b=keyscan();
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
4X4键盘数码管显示及控制io 口.rar
(56.94 KB, 下载次数: 19)
|