找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1885|回复: 8
打印 上一主题 下一主题
收起左侧

单片机动态数码管和中断结合的程序问题

[复制链接]
跳转到指定楼层
楼主
我想实现一个计分板左三个数码管和右三个数码管是分数中间两个是--,按键处理的时候如果把按键处理封装成一个函数的话,再按按键的时候数码管不会显示,我想没有这个空窗期,想用中断试下看,但是不明白这个为什么不行?难道要用定时器计数器?

单片机源程序如下:
  1. #include <reg52.h>

  2. typedef unsigned char uchar;
  3. typedef unsigned int  uint;

  4. sbit key1 = P1^0;
  5. sbit key2 = P1^1;
  6. sbit key3 = P1^2;

  7. sbit LSA = P1^3;
  8. sbit LSB = P1^4;
  9. sbit LSC = P1^5;


  10. uint point1 = 0,point2 = 0;
  11. uchar code duan[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  12. uchar disp[8];

  13. void delay(uint z) {
  14.         uint y;
  15.         for (;z>0;z--) {
  16.                 for (y = 0; y < 110; y++) {
  17.                 }
  18.         }
  19. }

  20. void keyzhongduanInit() {
  21.         EA = 1;
  22.         EX0 = 1;
  23.         IT0 = 1;          //下降沿触发
  24. }


  25. void keypros() interrupt 0 {
  26.         if (key1 == 0) {
  27.                 delay (10);
  28.                 if (key1 == 0) {
  29.                         point1++;               
  30.                 }
  31.                 while (!key1);
  32.         }
  33.         if (key2 == 0) {
  34.                 delay (10);
  35.                 if (key2 == 0) {
  36.                         point2++;               
  37.                 }
  38.                 while (!key2);
  39.         }
  40.         if (key3 == 0) {
  41.                 delay (10);
  42.                 if (key3 == 0) {
  43.                         point1 = 0;
  44.                         point2 = 0;
  45.                 }
  46.                 while (!key3);
  47.         }
  48. }

  49. void DisplayData() {
  50.         disp[0] = duan[point1 / 100];
  51.         disp[1] = duan[point1 % 100 / 10];
  52.         disp[2] = duan[point1 % 10];
  53.         disp[3] = 0x40;
  54.         disp[4] = 0x40;
  55.         disp[5] = duan[point2 / 100];
  56.         disp[6] = duan[point2 % 100 / 10];
  57.         disp[7] = duan[point2 % 10];
  58. }

  59. void weixuan() {
  60.         uchar i;
  61.         for (i = 0; i < 8; i++) {
  62.                 switch (i) {
  63.                         case (0): LSA = 0;LSB = 0;LSC = 0;break;
  64.                         case (1): LSA = 1;LSB = 0;LSC = 0;break;
  65.                         case (2): LSA = 0;LSB = 1;LSC = 0;break;
  66.                         case (3): LSA = 1;LSB = 1;LSC = 0;break;
  67.                         case (4): LSA = 0;LSB = 0;LSC = 1;break;
  68.                         case (5): LSA = 1;LSB = 0;LSC = 1;break;
  69.                         case (6): LSA = 0;LSB = 1;LSC = 1;break;
  70.                         case (7): LSA = 1;LSB = 1;LSC = 1;break;
  71.                 }
  72.                 P0 = disp[i];
  73.                 delay(1);
  74.                 P0 = 0x00;
  75.         }
  76. }

  77. void main() {
  78.         keyzhongduanInit();
  79.         while (1) {
  80.                 DisplayData();
  81.                 weixuan();
  82.         }               
  83. }
复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:161164 发表于 2022-3-4 21:02 | 只看该作者
不要用delay和while(!Key1)!
不要用delay和while(!Key1)!
不要用delay和while(!Key1)!
没必要用中断
把keypros()函数放进main()的while(1)里
  1. void keypros()//多键短按
  2. {
  3.         static uchar Delay_XD=0;                        //消抖计数
  4.         if(!key1 || !Key2 || !Key3)
  5.         {
  6.                 if(Delay_XD<0xFF)Delay_XD++;
  7.                 if(Delay_XD==50)                        //调节消抖时间
  8.                 {
  9.                         if(!key1)
  10.                         {
  11.                                 point1++;
  12.                         }
  13.                         if(!Key2)
  14.                         {
  15.                                 point2++;
  16.                         }
  17.                         if(!key3)
  18.                         {
  19.                                 point1 = 0;
  20.                                 point2 = 0;
  21.                         }
  22.                 }
  23.         }
  24.         else                                                        //按键抬起
  25.                 Delay_XD=0;                                        //Delay_XD清0
  26. }
复制代码
回复

使用道具 举报

板凳
ID:213173 发表于 2022-3-4 21:13 | 只看该作者
按键扫描和数码管动态显示代码,常见有十多钟写法。你选择了两个最差的写法。给你改了一下,你试试。

  1. #include <reg52.h>

  2. typedef unsigned char uchar;
  3. typedef unsigned int  uint;
  4. /*
  5. sbit key1 = P1^0;
  6. sbit key2 = P1^1;
  7. sbit key3 = P1^2;
  8. sbit LSA = P1^3;
  9. sbit LSB = P1^4;
  10. sbit LSC = P1^5;
  11. **/
  12. uint point1=0,point2=0;
  13. uchar code duan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  14. uchar disp[8]={0,0,0,0x40,0x40,0,0,0};

  15. void delay(uint z)
  16. {
  17.         uint y;
  18.         for(;z>0;z--)
  19.                 for(y=0;y<110;y++);
  20. }

  21. void key_scan()
  22. {
  23.         static uchar count=0;
  24.         static bit key_sign=0;
  25.         uchar key_value=P1&0x07;
  26.         if(key_value!=0x07)
  27.         {
  28.                 if(++count>=10 && key_sign==0)
  29.                 {
  30.                         key_sign=1;
  31.                         switch(key_value)
  32.                         {
  33.                                 case 0x06: if(point1<100)point1++; break;
  34.                                 case 0x05: if(point2<100)point2++; break;
  35.                                 case 0x03: point1=0;point2=0; break;
  36.                                 default: break;
  37.                         }
  38.                 }
  39.         }
  40.         else
  41.         {
  42.                 count=0;
  43.                 key_sign=0;
  44.         }
  45. }

  46. void DisplayData()
  47. {
  48.         disp[0] = duan[point1/100%10];
  49.         disp[1] = duan[point1/10%10];
  50.         disp[2] = duan[point1%10];
  51.         disp[5] = duan[point2/100%10];
  52.         disp[6] = duan[point2/10%10];
  53.         disp[7] = duan[point2%10];
  54. }

  55. void weixuan()
  56. {
  57.         static uchar i;
  58.         P0=0x00;
  59.         P1&=0xc7;
  60.         P1|=i<<3;
  61.         P0=disp[i];
  62.         i=++i%8;
  63. }

  64. void main()
  65. {
  66.         while (1)
  67.         {
  68.                 key_scan();
  69.                 DisplayData();
  70.                 weixuan();
  71.                 delay(1);
  72.         }
  73. }
复制代码



回复

使用道具 举报

地板
ID:1007138 发表于 2022-3-5 13:04 | 只看该作者
wulin 发表于 2022-3-4 21:13
按键扫描和数码管动态显示代码,常见有十多钟写法。你选择了两个最差的写法。给你改了一下,你试试。

请问++count>=10是消抖用吗?还有P1&=0xc7;
        P1|=i<<3;这两句话没看懂什么意思
回复

使用道具 举报

5#
ID:1007138 发表于 2022-3-5 13:17 | 只看该作者
小小彩姬 发表于 2022-3-5 13:04
请问++count>=10是消抖用吗?还有P1&=0xc7;
        P1|=i

后面两句话懂了,但是按键模块里的count和key_sign是做什么的呢?
感谢大佬指导
回复

使用道具 举报

6#
ID:1007138 发表于 2022-3-5 13:24 | 只看该作者
wulin 发表于 2022-3-4 21:13
按键扫描和数码管动态显示代码,常见有十多钟写法。你选择了两个最差的写法。给你改了一下,你试试。

怎么感觉++count>=10实现不了呢?如果有按键按下的话,count才加1.这里好像不会循环判断吧为什么会超过10呢?不解
回复

使用道具 举报

7#
ID:213173 发表于 2022-3-5 14:35 | 只看该作者
小小彩姬 发表于 2022-3-5 13:24
怎么感觉++count>=10实现不了呢?如果有按键按下的话,count才加1.这里好像不会循环判断吧为什么会超过10 ...

非特殊情况不要用delay阻滞型延时和 while (x)死等。在几乎所有程序中都要让主循环不停跑起来。在这个示例中用delay的目的是控制主循环周期约1ms,也就是1ms时间子函数轮询一遍。按键按下count计数10次约10ms与按键状态key_sign标志“相与”,满足条件执行相应语句。key_sign=1,下次轮询时没有松手就不会重复执行。直到松手key_sign=0。数码管动态扫描同样是1ms显示1位,这样按键和数码管就不会互相干扰了。
回复

使用道具 举报

8#
ID:1007138 发表于 2022-3-5 15:47 | 只看该作者
wulin 发表于 2022-3-5 14:35
非特殊情况不要用delay阻滞型延时和 while (x)死等。在几乎所有程序中都要让主循环不停跑起来。在这个示 ...

这个count的意思是等一段时间先让数码管先亮起来,然后再做按键处理吧?最后的延时1ms好像可以去掉
回复

使用道具 举报

9#
ID:1007138 发表于 2022-3-5 16:06 | 只看该作者
小小彩姬 发表于 2022-3-5 15:47
这个count的意思是等一段时间先让数码管先亮起来,然后再做按键处理吧?最后的延时1ms好像可以去掉

请问这里为什么可以不延时1ms数码管显示,以前那个为什么要延时的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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