5031|12

67

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

51单片机关于键盘扫描的问题 [复制链接]

想做一个单片机打地鼠小游戏,4*4键盘,4*4灯,灯一亮按对应的按键,按对的话发出响声,按错没有声音,成功10次之后播放音乐。但是程序写成这样之后,发现不论按不按按键...他都自己亮10次灯,每次都有成功的声音~最后播放音乐~不知道怎么回事,高手指点....


  1. #include
  2. #include
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. #define ulong unsigned long
  6. #define LED P1   


  7. #define SYSTEM_OSC   11059200//定义晶振频率
  8. #define SOUND_SPACE  4/5      //定义普通音符演奏的长度分率,//每4分音符间隔
  9. sbit    BeepIO    =  P3^6;  //定义输出管脚

  10. unsigned int  code FreTab[12]  = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表
  11. unsigned char code SignTab[7]  = { 0,2,4,5,7,9,11 };           //1~7在频率表中的位置
  12. unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };     
  13. unsigned char Sound_Temp_TH0,Sound_Temp_TL0; //音符定时器初值暂存
  14. unsigned char Sound_Temp_TH1,Sound_Temp_TL1; //音长定时器初值暂存


  15. unsigned char code Music_Two[];  

  16. void InitialSound(void)
  17. {
  18. BeepIO = 1;
  19. Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; // 计算TL1应装入的初值  (10ms的初装值)
  20. Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256; // 计算TH1应装入的初值
  21. TH1 = Sound_Temp_TH1;
  22. TL1 = Sound_Temp_TL1;
  23. TMOD  |= 0x11;
  24. ET0    = 1;
  25. ET1    = 0;
  26. TR0    = 0;
  27. TR1    = 0;
  28. EA     = 1;
  29. }



  30. void BeepTimer0(void) interrupt 1 //音符发生中断
  31. {
  32. BeepIO = !BeepIO;
  33. TH0    = Sound_Temp_TH0;
  34. TL0    = Sound_Temp_TL0;
  35. }

  36.                
  37. void delay(int k)
  38. {
  39.         int i,j;
  40.         for(i=0;i
  41.         {       
  42.                 for(j=0;j<30000;j++)
  43.                 {
  44.                        
  45.                 }       
  46.         }
  47. }




  48. void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
  49. {
  50. unsigned int NewFreTab[12];  //新的频率表
  51. unsigned char i,j;
  52. unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
  53. unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
  54. for(i=0;i<12;i++)     // 根据调号及升降八度来生成新的频率表
  55. {
  56.   j = i + Signature;
  57.   if(j > 11)
  58.   {
  59.    j = j-12;
  60.    NewFreTab[i] = FreTab[j]*2;
  61.   }
  62.   else
  63.    NewFreTab[i] = FreTab[j];

  64.   if(Octachord == 1)
  65.    NewFreTab[i]>>=2;
  66.   else if(Octachord == 3)
  67.    NewFreTab[i]<<=2;
  68. }        

  69. SoundLength = 0;
  70. while(Sound[SoundLength] != 0x00) //计算歌曲长度
  71. {
  72.   SoundLength+=2;
  73. }

  74. Point = 0;
  75. Tone   = Sound[Point];
  76. Length = Sound[Point+1];    // 读出第一个音符和它时时值

  77. LDiv0 = 12000/Speed;    // 算出1分音符的长度(几个10ms)
  78. LDiv4 = LDiv0/4;      // 算出4分音符的长度
  79. LDiv4 = LDiv4-LDiv4*SOUND_SPACE;  // 普通音最长间隔标准
  80. TR0   = 0;
  81. TR1   = 1;
  82. while(Point < SoundLength)
  83. {
  84.   SL=Tone%10;         //计算出音符
  85.   SM=Tone/10%10;         //计算出高低音
  86.   SH=Tone/100;         //计算出是否升半
  87.   CurrentFre = NewFreTab[SignTab[SL-1]+SH];  //查出对应音符的频率
  88.   if(SL!=0)
  89.   {
  90.    if (SM==1) CurrentFre >>= 2;   //低音
  91.    if (SM==3) CurrentFre <<= 2;   //高音
  92.    Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值
  93.    Sound_Temp_TH0 = Temp_T/256;
  94.    Sound_Temp_TL0 = Temp_T%256;
  95.    TH0 = Sound_Temp_TH0;
  96.    TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿
  97.   }
  98.   SLen=LengthTab[Length%10];  //算出是几分音符
  99.   XG=Length/10%10;    //算出音符类型(0普通1连音2顿音)
  100.   FD=Length/100;
  101.   LDiv=LDiv0/SLen;    //算出连音音符演奏的长度(多少个10ms)
  102.   if (FD==1)
  103.    LDiv=LDiv+LDiv/2;
  104.   if(XG!=1)
  105.    if(XG==0)     //算出普通音符的演奏长度
  106.     if (SLen<=4)
  107.      LDiv1=LDiv-LDiv4;
  108.     else
  109.      LDiv1=LDiv*SOUND_SPACE;
  110.    else
  111.     LDiv1=LDiv/2;   //算出顿音的演奏长度
  112.   else
  113.    LDiv1=LDiv;
  114.   if(SL==0) LDiv1=0;
  115.    LDiv2=LDiv-LDiv1;   //算出不发音的长度
  116.     if (SL!=0)
  117.   {
  118.    TR0=1;
  119.    for(i=LDiv1;i>0;i--)  //发规定长度的音
  120.    {
  121.     while(TF1==0);
  122.     TH1 = Sound_Temp_TH1;
  123.     TL1 = Sound_Temp_TL1;
  124.     TF1=0;
  125.    }
  126.   }
  127.   if(LDiv2!=0)
  128.   {
  129.    TR0=0; BeepIO=1;
  130.    for(i=LDiv2;i>0;i--)  //音符间的间隔
  131.    {
  132.     while(TF1==0);
  133.     TH1 = Sound_Temp_TH1;
  134.     TL1 = Sound_Temp_TL1;
  135.     TF1=0;
  136.    }
  137.   }
  138.   Point+=2;
  139.   Tone=Sound[Point];
  140.   Length=Sound[Point+1];
  141. }
  142. BeepIO = 1;
  143. }


  144. void success()
  145. {
  146.           BeepIO=~BeepIO;
  147. }





  148. void done()
  149. {       

  150.         unsigned char code Music_Two[] ={ 0x17,0x03, 0x16,0x03, 0x17,0x01, 0x16,0x03, 0x17,0x03,
  151.                                   0x16,0x03, 0x15,0x01, 0x10,0x03, 0x15,0x03, 0x16,0x02,
  152.                                   0x16,0x0D, 0x17,0x03, 0x16,0x03, 0x15,0x03, 0x10,0x03,
  153.                                   0x10,0x0E, 0x15,0x04, 0x0F,0x01, 0x17,0x03, 0x16,0x03,
  154.                                   0x17,0x01, 0x16,0x03, 0x17,0x03, 0x16,0x03, 0x15,0x01,
  155.                                   0x10,0x03, 0x15,0x03, 0x16,0x02, 0x16,0x0D, 0x17,0x03,
  156.                                   0x16,0x03, 0x15,0x03, 0x10,0x03, 0x15,0x03, 0x16,0x01,
  157.                                   0x17,0x03, 0x16,0x03, 0x17,0x01, 0x16,0x03, 0x17,0x03,
  158.                                   0x16,0x03, 0x15,0x01, 0x10,0x03, 0x15,0x03, 0x16,0x02,
  159.                                   0x16,0x0D, 0x17,0x03, 0x16,0x03, 0x15,0x03, 0x10,0x03,
  160.                                   0x10,0x0E, 0x15,0x04, 0x0F,0x01, 0x17,0x03, 0x19,0x03,
  161.                                   0x19,0x01, 0x19,0x03, 0x1A,0x03, 0x19,0x03, 0x17,0x01,
  162.                                   0x16,0x03, 0x16,0x03, 0x16,0x02, 0x16,0x0D, 0x17,0x03,
  163.                                   0x16,0x03, 0x15,0x03, 0x10,0x03, 0x10,0x0D, 0x15,0x00,
  164.                                   0x19,0x03, 0x19,0x03, 0x1A,0x03, 0x1F,0x03, 0x1B,0x03,
  165.                                   0x1B,0x03, 0x1A,0x03, 0x17,0x0D, 0x16,0x03, 0x16,0x03,
  166.                                   0x16,0x0D, 0x17,0x01, 0x17,0x03, 0x17,0x03, 0x19,0x03,
  167.                                   0x1A,0x02, 0x1A,0x02, 0x10,0x03, 0x17,0x0D, 0x16,0x03,
  168.                                   0x16,0x01, 0x17,0x03, 0x19,0x03, 0x19,0x03, 0x17,0x03,
  169.                                   0x19,0x02, 0x1F,0x02, 0x1B,0x03, 0x1A,0x03, 0x1A,0x0E,
  170.                                   0x1B,0x04, 0x17,0x02, 0x1A,0x03, 0x1A,0x03, 0x1A,0x0E,
  171.                                   0x1B,0x04, 0x1A,0x03, 0x19,0x03, 0x17,0x03, 0x16,0x03,
  172.                                   0x17,0x0D, 0x16,0x03, 0x17,0x03, 0x19,0x01, 0x19,0x03,
  173.                                   0x19,0x03, 0x1A,0x03, 0x1F,0x03, 0x1B,0x03, 0x1B,0x03,
  174.                                   0x1A,0x03, 0x17,0x0D, 0x16,0x03, 0x16,0x03, 0x16,0x03,
  175.                                   0x17,0x01, 0x17,0x03, 0x17,0x03, 0x19,0x03, 0x1A,0x02,
  176.                                   0x1A,0x02, 0x10,0x03, 0x17,0x0D, 0x16,0x03, 0x16,0x01,
  177.                                   0x17,0x03, 0x19,0x03, 0x19,0x03, 0x17,0x03, 0x19,0x03,
  178.                                   0x1F,0x02, 0x1B,0x03, 0x1A,0x03, 0x1A,0x0E, 0x1B,0x04,
  179.                                   0x17,0x02, 0x1A,0x03, 0x1A,0x03, 0x1A,0x0E, 0x1B,0x04,
  180.                                   0x17,0x16, 0x1A,0x03, 0x1A,0x03, 0x1A,0x0E, 0x1B,0x04,
  181.                                   0x1A,0x03, 0x19,0x03, 0x17,0x03, 0x16,0x03, 0x0F,0x02,
  182.                                   0x10,0x03, 0x15,0x00, 0x00,0x00 };
  183.         InitialSound();             //定时器初始化
  184.         Play(Music_Two,11,3,3000);
  185. }


  186. int suijishu_a(int i)//随机数函数
  187.           
  188. {
  189.                 uint table[] ={
  190.   0x87,0x8b,0x8d,0x8e,
  191.         0x47,0x4b,0x4d,0x4e,
  192.         0x27,0x2b,0x2d,0x2e,
  193.         0x17,0x1b,0x1d,0x1e
  194.         }          ;

  195.   return table[i];
  196. }

  197. uchar scan()
  198. {
  199.         int num;
  200.         uint temp;
  201.         P0=0xfe;                 //扫描第一行     
  202.         temp=P0;
  203.         temp=temp&0xf0;
  204.         if(temp!=0xf0)             //判断按键是否被按下
  205.         {
  206.                 delay(3);                 //去抖         
  207.                 if(temp!=0xf0)
  208.                 switch(temp)
  209.                 {
  210.                         case 0xe0 : num=0;         //第一个按键被按下
  211.                         break;
  212.                         case 0xd0 : num=1;         //第二个按键被按下
  213.                         break;
  214.                         case 0xb0 : num=2;         //第三个按键被按下     
  215.                         break;
  216.                         case 0x70 : num=3;         //第四个按键被按下
  217.                 }
  218.         }
  219.                 P0=0xfd;             //扫描第二行                           
  220.                 temp=P0;
  221.                 temp=temp&0xf0;                                

  222.                 if(temp!=0xf0)         //判断按键是否被按下
  223.                 {
  224.                         delay(3);      //去抖
  225.                         if(temp!=0xf0)
  226.                         {
  227.                                 switch(temp)
  228.                                 {
  229.        
  230.                                         case 0xe0 : num=4;      //第五个按键被按下      
  231.                                                 break;
  232.                                         case 0xd0 : num=5;      //第6个按键被按下     
  233.                                                 break;
  234.                                         case 0xb0 : num=6;       //第7个按键被按下   
  235.                                                 break;
  236.                                         case 0x70 : num=7;       //第8个按键被按下
  237.                                 }
  238.                         }

  239.         }

  240.         P0=0xfb;               //扫描第三行
  241.         temp=P0;
  242.         temp=temp&0xf0;
  243.         if(temp!=0xf0)           //判断按键是否被按下                          
  244.         {
  245.                 delay(3);           //去抖
  246.                 if(temp!=0xf0)
  247.                 switch(temp)
  248.                 {
  249.                         case 0xe0 : num=8;    //第9个按键被按下
  250.                                 break;
  251.                         case 0xd0 : num=9;    //第10个按键被按下
  252.                                 break;
  253.                         case 0xb0 : num=10;   //第11个按键被按下
  254.                                 break;
  255.                         case 0x70 : num=11;   //第12个按键被按下
  256.                 }

  257.         }
  258.         P0=0xf7;                  //扫描第四行
  259.         temp=P0;
  260.         temp=temp&0xf0;
  261.         if(temp!=0xf0)
  262.         {
  263.                 delay(3);              // 去抖
  264.                 if(temp!=0xf0)          //判断按键是否被按下
  265.                 switch(temp)
  266.                 {
  267.                         case 0xe0 : num=12;   //第13个按键被按下
  268.                                 break;
  269.                         case 0xd0 : num=13;      //第14个按键被按下
  270.                                 break;
  271.                         case 0xb0 : num=14;      //第15个按键被按下
  272.                                 break;
  273.                         case 0x70 : num=15;      //第16个按键被按下
  274.                 }
  275.         }
  276.         return num;              //返回被按下的按键的序号
  277. }





  278. void main()
  279. {   
  280.           uchar count,n1,n2;

  281.           while(1)
  282.           {
  283.                     n1=rand()%16;
  284.                   if(n1==7 || n1==10 || n1==13)
  285.                   {
  286.                           n1=3;
  287.                   }
  288.                   LED=suijishu_a(n1);
  289.                   
  290.                   n2=scan();  
  291.                   if(n1==n2)
  292.                   {
  293.                                 success();
  294.                                 count++;
  295.                   }
  296.                   else continue;
  297.                   
  298.                   if(count==10)
  299.                   {
  300.                         done();
  301.                         break;
  302.                   }
  303.          }

  304.    

  305. }
复制代码

最新回复

能加一下QQ吗,想请你指教!!!谢谢,我是一名大二的学生,谢谢  详情 回复 发表于 2012-3-29 16:21
点赞 关注

回复
举报

75

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
函数scan()有两个错误:
1,返回值是uchar 还是 int呢?
2,int num没有初始化,没按键的时候,返回的是随机值。(这估计是就是你想要的答案所在吧)
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

板凳
 

void BeepTimer0(void) interrupt 1 //音符发生中断
{
BeepIO = !BeepIO;
TH0    = Sound_Temp_TH0;
TL0    = Sound_Temp_TL0;
}

这里的BeepIO = !BeepIO;应该改为BeepIO = ~BeepIO;吧!你的运算符用错的!
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

4
 
发现不论按不按按键...他都自己亮10次灯,每次都有成功的声音~最后播放音乐~不知道怎么回事,高手指点....
是所有的灯都亮十次吗 还是只有一个灯亮十次啊
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

5
 
引用 1 楼 lin0119 的回复:
函数scan()有两个错误:
1,返回值是uchar 还是 int呢?
2,int num没有初始化,没按键的时候,返回的是随机值。(这估计是就是你想要的答案所在吧)

貌似不是这个问题~~我觉得是主函数里面~~scan()那块的问题~~~
 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

6
 
引用 2 楼 galle 的回复:
void BeepTimer0(void) interrupt 1 //音符发生中断
{
BeepIO = !BeepIO;
TH0? ? = Sound_Temp_TH0;
TL0? ? = Sound_Temp_TL0;
}

这里的BeepIO = !BeepIO;应该改为BeepIO = ~BeepIO;吧!你的运算符用错的!

改了还是这样的~~~不行呀~
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

7
 
引用 3 楼 ywf861029 的回复:
发现不论按不按按键...他都自己亮10次灯,每次都有成功的声音~最后播放音乐~不知道怎么回事,高手指点....
是所有的灯都亮十次吗 还是只有一个灯亮十次啊


不是所有灯都亮10次~~每次亮一个~~一共亮10次~~但是我们发现~~~貌似~这个灯也不是随机亮的~~不知道怎么回事~~~关键还是没法扫描~~没法判断这个n1和n2相等不~~
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

8
 
你的随机数是有问题的!你可以自己看看!只能出4个数,另外不用吧声音的开关放在中断中去做!按键最好使用中断方式,!在等待按键的时候死循环试试!
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

9
 
LED=suijishu_a(n1);
致使每次都亮
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

10
 
uchar scan()
没有有等待键释放就退出,致使
  n1=rand()%16;
          if(n1==7 || n1==10 || n1==13)
          {
              n1=3;
          }
          LED=suijishu_a(n1);
         
          n2=scan();  
          if(n1==n2)
          {
                success();
                count++;
          }
          else continue;
这几行代码在只有一次按键的情况下实行远远超过16次,即,
一个按键事件有一个n2,但是,要跟循环次数个n1比较.而刚才说了,循环次数远远超过16(看看你的延迟和通常一次按键的闭合时间比较一下),所以,你那个if(n1==n2)等价于if(n2<=15&&n2>=0),只要有按键按下,永远成立.另外,你没有在键盘扫描中,你没有定义nokey返回,有可能你不按键也会响哦
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

11
 
推荐你个好的,有可以定义灯亮了多久之后打了无效.实际也应该是这样的

  1. #define outtime  5000
  2. clock_t start_time,end_time;
  3. key k;
  4. int led;
  5. int count=10;
  6. while(1)
  7. {
  8.   led=rand()%16;
  9.   LED=table[led];
  10.   start_time=clock();
  11.   end_time=start_time;
  12.   k=nokey;
  13.   while((end_time-start_time
  14.       k=keyscan();
  15.   if(k==led)
  16.   {
  17.       weldone_things();
  18.   }
  19.   else
  20.      continue;
  21.   ....

  22. }



复制代码
 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

12
 

真是一粒金砂啊

我也正在做这样一个类似打地鼠的游戏机,同道中人!!!以后还请多多指教!!
 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

13
 

你好

能加一下QQ吗,想请你指教!!!谢谢,我是一名大二的学生,谢谢
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表