找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2753|回复: 19
收起左侧

怎么改进这个单片机电子琴,多按了几下按钮就死机了为什么呀?

[复制链接]
ID:919434 发表于 2021-5-11 22:14 来自手机 | 显示全部楼层 |阅读模式
小白求助!本来想达成按按键发出声音然后显示数字的功能,同时数字可以无限随着按键向左移动。于是我注释了if(num<=8)的语句,目的就是为了按键数字无限向左移动,但是这样子按键超过10次且不清除数字的时候,单片机就会死机!
    要怎么改才能实现电子琴显示数字无限向左移动且不死机呀?
拜托大佬了~
12796f7d81a59627.png
回复

使用道具 举报

ID:919434 发表于 2021-5-11 22:16 来自手机 | 显示全部楼层
仿真电路图是这样子的
1620742568569840601857166901574.jpg
回复

使用道具 举报

ID:919434 发表于 2021-5-11 22:50 来自手机 | 显示全部楼层
上面发的代码好像看不清,补发一下
-7806c17498801a7e.png
1b710af8f25114be.png
15f80d6efb467b15.png
51c68dabd13f4ad3.png
回复

使用道具 举报

ID:139866 发表于 2021-5-12 09:21 | 显示全部楼层
你要知道,你无论移动多少数据,到最后显示的只有8位,所以只要考虑8位显示就行了,左移之后显示低8位,就能达到你要的效果
回复

使用道具 举报

ID:919434 发表于 2021-5-12 09:51 来自手机 | 显示全部楼层
天ノ忆 发表于 2021-5-12 09:21
你要知道,你无论移动多少数据,到最后显示的只有8位,所以只要考虑8位显示就行了,左移之后显示低8位,就 ...

那怎么用程序表达显示最近输入的8位呐?
我现在的程序可以显示最近八位,但是我想不通为什么会死机呀
回复

使用道具 举报

ID:139866 发表于 2021-5-12 10:23 | 显示全部楼层
乌拉拉呜 发表于 2021-5-12 09:51
那怎么用程序表达显示最近输入的8位呐?
我现在的程序可以显示最近八位,但是我想不通为什么会死机呀

数码管显示那里不要管逻辑处理,只需要做到接到什么数据显示什么数据就行。
键盘读到的数据出来起来就更简单了,比如一开始是12345678,又读到一个9,就这样处理,
BUF = 12345678;
BUF = ((BUF << 1) | 9) & 0XFF;
这样就保证了数据只有8位,然后送入显示的函数进行显示
回复

使用道具 举报

ID:919434 发表于 2021-5-12 22:30 来自手机 | 显示全部楼层
天ノ忆 发表于 2021-5-12 10:23
数码管显示那里不要管逻辑处理,只需要做到接到什么数据显示什么数据就行。
键盘读到的数据出来起来就更 ...

这样改不行呀,我不会改啊啊啊。我太菜了
IMG20210512222933.jpg
回复

使用道具 举报

ID:213173 发表于 2021-5-13 08:05 | 显示全部楼层
乌拉拉呜 发表于 2021-5-12 09:51
那怎么用程序表达显示最近输入的8位呐?
我现在的程序可以显示最近八位,但是我想不通为什么会死机呀

不会死机,不受中断干扰,逐键左移显示键值。

无标题.jpg



  1. #include <reg51.h>
  2. #define uint unsigned int
  3. #define uchar unsigned char

  4. uchar code table[]={//共阳数码管段码"0~f-."
  5.                 0xc0,0xf9,0xa4,0xb0,
  6.                 0x99,0x92,0x82,0xf8,
  7.                 0x80,0x90,0x88,0x83,
  8.                 0xc6,0xa1,0x86,0x8e,0xbf,0x7f};

  9. uchar data key_buf[9]={0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xff};

  10. uchar KeyValue=0;//键值变量

  11. void keyscan()
  12. {
  13.         static uchar count=0;                //计数变量       
  14.         static bit sign=0;                        //位变量
  15.         uchar i;
  16.         P1=0xf0;
  17.         if(P1!=0xf0)
  18.         {
  19.                 if(++count>=10 && sign==0)
  20.                 {                       
  21.                         sign=1;
  22.                         switch(P1)
  23.                         {
  24.                                 case(0Xe0):KeyValue = 0;break;
  25.                                 case(0Xd0):KeyValue = 1;break;
  26.                                 case(0Xb0):KeyValue = 2;break;
  27.                                 case(0X70):KeyValue = 3;break;
  28.                         }
  29.                         P1=0x0f;       
  30.                         switch(P1)
  31.                         {
  32.                                 case(0X0e):KeyValue+= 0;break;
  33.                                 case(0X0d):KeyValue+= 4;break;
  34.                                 case(0X0b):KeyValue+= 8;break;
  35.                                 case(0X07):KeyValue+=12;break;
  36.                         }
  37.                         key_buf[8]=table[KeyValue];
  38.                         for(i=0;i<8;i++)
  39.                                 key_buf[i]=key_buf[i+1];//左移
  40.                 }
  41.         }
  42.         else
  43.         {
  44.                 sign=0;       
  45.                 count=0;
  46.         }
  47. }

  48. void Display()
  49. {
  50.         static uchar i;
  51.         P2=0x00;                        //消隐
  52.         P0=key_buf[i]; //送段码
  53.         P2=0x01<<i;    //送位码
  54.         i=++i%8;                        //循环计数
  55. }

  56. void Delay_Ms(uchar n)
  57. {
  58.         uchar k;
  59.         while(n--)
  60.         {
  61.                 for(k=0;k<113;k++);
  62.         }
  63. }

  64. void main()
  65. {
  66.         while(1)
  67.         {
  68.                 keyscan();
  69.                 Display();
  70.                 Delay_Ms(1);//控制主循环周期约1ms
  71.         }
  72. }
复制代码



回复

使用道具 举报

ID:919434 发表于 2021-5-13 20:22 来自手机 | 显示全部楼层
wulin 发表于 2021-5-13 08:05
不会死机,不受中断干扰,逐键左移显示键值。

谢谢大佬,不过我放控制中断的语句进去,扬声器就会一直响
回复

使用道具 举报

ID:213173 发表于 2021-5-13 21:25 | 显示全部楼层
乌拉拉呜 发表于 2021-5-13 20:22
谢谢大佬,不过我放控制中断的语句进去,扬声器就会一直响

开两个定时器,一个随键值控制喇叭发声频率,一个控制持续时间。不过要想声音好听就得添加DA转换和按键力度检测。
回复

使用道具 举报

ID:919434 发表于 2021-5-14 21:50 来自手机 | 显示全部楼层
wulin 发表于 2021-5-13 21:25
开两个定时器,一个随键值控制喇叭发声频率,一个控制持续时间。不过要想声音好听就得添加DA转换和按键力 ...

请前辈帮我看看代码,虽然知道功能但是不太会用代码表达呀。
  1. #include <reg51.h>
  2. #define uchar unsigned char
  3. uchar DisBuf[8];
  4. sbit P3_7=P3^7;
  5. unsigned char table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //
  6. unsigned char BitCode[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};    //                                             
  7. uchar code key_buf[16]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd, 0x7d,0xeb,
  8.                         0xdb, 0xbb, 0x7b,0xe7, 0xd7,0xb7,0x77}; //
  9. unsigned int wu[]={64580,64684,64777,64820,64898,64968,65030,65058,65058,65111};
  10. uchar KeyValue;   
  11. unsigned int num=0;   
  12. unsigned char i;

  13. void Delay_Ms(uchar n) //
  14. {
  15. uchar k;
  16. while(n--)
  17. {
  18.   for(k=0;k<113;k++);
  19. }
  20. }

  21. void Display()//
  22. {
  23.   uchar i;
  24.   for(i=0;i<8;i++)
  25. {
  26.   P0=DisBuf[i];   
  27.   P2=BitCode[i];  
  28.   Delay_Ms(1);
  29.   P0=0xff;
  30. }
  31. }

  32. uchar KeyScan()    //
  33. {
  34. uchar scan1,scan2,temp,j;
  35. P1 = 0x0f;
  36. scan1 = P1 & 0x0f;  

  37. if (scan1 != 0x0f)
  38. {
  39.   Delay_Ms(10);   
  40.   scan1 = P1 & 0x0f;

  41.   if (scan1 != 0x0f)  
  42.   {
  43.    P1 = 0xf0;
  44.    scan2 = P1 &  0xf0;

  45.    temp = scan1 | scan2 ;
  46.    for (j=0;j<16;j++)
  47.    {
  48.     if (temp == key_buf[j])
  49.      return j;   
  50.    }
  51.       
  52.   }
  53.   return (16);   
  54. }
  55. else
  56.   return (16);     
  57. }

  58. void main(void)
  59. {
  60.         
  61.         TMOD=0x01;
  62.         ET0=1;
  63.         EA=1;
  64. for(i=0;i<8;i++)
  65. {
  66. DisBuf[i]=0xff;
  67. }
  68.   while(1)
  69. {
  70.    Display();
  71.    KeyValue = KeyScan();
  72.            TR0=1;
  73.   if (KeyValue<16)
  74. {
  75.   while(KeyScan()<16);
  76.         
  77.   if(KeyValue<10)
  78. {
  79.   num++;
  80.         TR0=1;
  81. //if(num<=8)
  82. {
  83.   for(i=num-1;i>=1;i--)
  84. {
  85.   DisBuf[i]=DisBuf[i-1];//移位
  86.         
  87. }
  88.   DisBuf[0]=table[KeyValue];
  89. }
  90. }
  91.   else
  92. {
  93.         if(KeyValue==10)//清屏
  94.         {
  95.   for(i=0;i<=7;i++)
  96. {
  97.   DisBuf[i]=0xff;  
  98. }
  99.   num = 0;
  100. }
  101.    }
  102.   }
  103. }
  104. }

  105. void time() interrupt 1 //中断发声
  106. {
  107.         if(KeyValue<=9)
  108.         {
  109.         TH0=wu[KeyValue]/256;
  110.         TL0=wu[KeyValue]%256;
  111.         P3_7=!P3_7;
  112.         }
  113. }
复制代码
回复

使用道具 举报

ID:213173 发表于 2021-5-16 07:31 | 显示全部楼层
乌拉拉呜 发表于 2021-5-14 21:50
请前辈帮我看看代码,虽然知道功能但是不太会用代码表达呀。

改好了
简易电子琴.zip (117.76 KB, 下载次数: 16)
回复

使用道具 举报

ID:919434 发表于 2021-5-16 16:12 来自手机 | 显示全部楼层
wulin 发表于 2021-5-16 07:31
改好了

非常感谢~
回复

使用道具 举报

ID:919434 发表于 2021-5-24 21:20 来自手机 | 显示全部楼层
wulin 发表于 2021-5-16 07:31
改好了

前辈,我发现我之前的问题了,就是我定义的缓冲数组只有8个储存空间,所以按键超过储存空间时(按键次数超过8时),单片机就会死机,而且用我的代码,缓冲数组最多只能定义2的6次方的储存空间。
  但是前辈的代码可以实现无限左移动,并且没有缓冲数组的限制,小弟不才,没有看懂前辈的代码,不是很清楚前辈的代码是如何达到目的的,肯请前辈指教。
回复

使用道具 举报

ID:213173 发表于 2021-5-25 06:02 | 显示全部楼层
乌拉拉呜 发表于 2021-5-24 21:20
前辈,我发现我之前的问题了,就是我定义的缓冲数组只有8个储存空间,所以按键超过储存空间时(按键次数 ...

        uchar data key_buf[9]={0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xff};//显示缓冲数组长度9,初值任意填写。

        key_buf[8]=table[KeyValue];//将当前键值保存在缓冲数组的最后并覆盖上次保存的键值
        for(i=0;i<8;i++)
                key_buf=key_buf[i+1];//循环8次由后向前逐一覆盖替换保存的键值

        数码管只显示key_buf[0]~key_buf[7]就达到随按键左移显示键值的目的
回复

使用道具 举报

ID:919434 发表于 2021-5-25 23:57 来自手机 | 显示全部楼层
wulin 发表于 2021-5-25 06:02
uchar data key_buf[9]={0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xff};//显示缓冲数组长度9,初值任 ...

非常感谢前辈!终于弄好了,不过又出现了消影小问题,应该是我的键盘扫描函数的原因,我再想办法改改,单片机真的好磨人呀!
回复

使用道具 举报

ID:213173 发表于 2021-5-26 06:06 | 显示全部楼层
乌拉拉呜 发表于 2021-5-25 23:57
非常感谢前辈!终于弄好了,不过又出现了消影小问题,应该是我的键盘扫描函数的原因,我再想办法改改,单 ...

消隐问题是显示函数没有处理好,不在按键扫描函数。
回复

使用道具 举报

ID:919434 发表于 2021-5-26 08:27 来自手机 | 显示全部楼层
wulin 发表于 2021-5-26 06:06
消隐问题是显示函数没有处理好,不在按键扫描函数。

显示函数我用的和前辈是一样的,主函数也差不多
Screenshot_2021-05-26-08-27-28-53.jpg
回复

使用道具 举报

ID:919434 发表于 2021-5-27 12:02 来自手机 | 显示全部楼层
wulin 发表于 2021-5-26 06:06
消隐问题是显示函数没有处理好,不在按键扫描函数。

找到问题了,我换台电脑就可以了。
回复

使用道具 举报

ID:942522 发表于 2021-6-22 16:20 | 显示全部楼层

大佬,怎么删除字符,比如说按键按错了,想要删除数码管显示的错误数,怎么办啊?
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表