找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2137|回复: 5
收起左侧

单片机旋转彩虹灯在运行时按键无反应

[复制链接]
回帖奖励 8 黑币 回复本帖可获得 1 黑币奖励! 每人限 1 次
ID:452212 发表于 2020-5-18 19:38 | 显示全部楼层 |阅读模式
  在用C语言写旋转彩虹灯(按键控制方向和速度)时遇到一个小问题,我知道问题在哪,但是解决不了;完整单片机代码如下:
  1. #include<reg51.h>
  2. #define unit unsigned int
  3. #define uchar unsigned char

  4. uchar code KEY_TABLE[]=
  5.                                 {0x11,0x21,//0001 0001,KEY0;0010 0001,KEY1
  6.                                 0x12,0x22};//0001 0010,KEY2;0010 0010,KEY3//按键表
  7. uchar code Out_TABLE[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//输出
  8. //1111 1110;1111 1101;1111 1011;1111 0111
  9. uchar code T_TABLE[]={0x64,0x50,0x3c,0x28,0x14};//延时部分
  10. uchar code Sout_TABLE[]={0x0f,0x17,0x1b,0x1d,0x1e};//指示灯
  11. //0000 1111;0001 0111;0001 1011;0001 1101;0001 1110;

  12. //延时10ms,基本延时单位和按键消抖部分
  13. void delay()
  14. {
  15. uchar t,ms;
  16. ms=10;
  17. while(ms--)for(t=0;t<120;t++);
  18. }
  19. //速度选择部分
  20. void delay1(uchar n)//n=20,40,60,80,100
  21. {
  22. uchar i;
  23.         for(i=0;i<n;i++)
  24.         {
  25.                 delay();
  26.         }
  27. }


  28. void main()
  29. {

  30.         
  31. uchar DIR = 0;//方向选择
  32. uchar m = 0;//方向实现(通过灯亮的顺序)
  33. uchar speed = 0;//速度档位
  34. uchar t=T_TABLE[speed];//速度对应延时表
  35. uchar i,num,key,temp;//变量定义
  36. P1=Out_TABLE[m];//输出
  37. P0=Sout_TABLE[speed];//速度挡位指示

  38. while(1)
  39. {        
  40.         //检测按键部分(线反转法)
  41.                 P3=0x30;//0011 0000;
  42.                         if(P3!=0x30)//
  43.                         {
  44.                         delay();//
  45.                         P3=0x30;//
  46.                                 if(P3!=0x30)//0001 0000;
  47.                                         {
  48.                                         temp =P3;//0001 0000;
  49.                                         P3=0x03;//0000 0011;=>0000 0010
  50.                                         key=temp|P3;//KEY=0001 0010;
  51.                                         key=0x33-key;//KEY=0010 0001;ZHAODAO 0X21,
  52.                                                 for(i=0;i<4;i++)
  53.                                                 {
  54.                                                         if(key==KEY_TABLE[i])
  55.                                                         {
  56.                                                         num = i;//NUM = 1;
  57.                                                         break;
  58.                                                         }
  59.                                                 }
  60.         //按键不同,功能不同
  61.                                                 switch(num)
  62.                                                 {        
  63.                                                   case 0:DIR=0;
  64.                                                         
  65.                                                         break;
  66.                                                 
  67.                                                         case 1:DIR=1;

  68.                                                         break;
  69.                                                         case 2:
  70.                                                         
  71.                                                         {
  72.                                                                 speed++;//=1,=2,=3,=4,=5
  73.                                                                 if(speed==5)
  74.                                                                         speed =0;
  75.                                                                 break;
  76.                                                         }
  77.                                                         case 3:
  78.                                                         {
  79.                                                                 speed--;//=4,=3,=2,=1,=0
  80.                                                                 if(speed==-1)
  81.                                                                         speed =4;
  82.                                                                 break;
  83.                                                         }
  84.                                                         
  85.                                                 }
  86.                                                 P0=P0=Sout_TABLE[speed];//指示灯输出
  87.                                                 t=T_TABLE[speed];
  88.                                                 
  89.                                                 if(DIR==0)
  90.                                                 {
  91.                                                         for(;m<=7;m++)
  92.                                                         {
  93.                                                                 P1=Out_TABLE[m];
  94.                                                                 delay1(t);
  95.                                                                
  96.                                                                 if(m==7)
  97.                                                                 {
  98.                                                                         m=-1;
  99.                                                                 }
  100.                                                         }
  101.                                                 }
  102.                                                 if(DIR==1)
  103.                                                 {
  104.                                                         for(;m>=0;m--)
  105.                                                         {
  106.                                                                 P1=Out_TABLE[m];
  107.                                                                 delay1(t);
  108.                                                                 if(m==0)
  109.                                                                 {
  110.                                                                         m=8;
  111.                                                                 }
  112.                                         }        
  113.                         }
  114.                 }        
  115. }
  116. }
  117.                 }
复制代码
问题点在:
if(DIR==0)
{
for(;m<=7;m++)
{
P1=Out_TABLE[m];
delay1(t);

if(m==7)
{
m=-1;
}
}
}

如果我这样写,执行时,再按键就失效了。我试着在里面加上“if(P3!=0x30)break;”,效果不好。希望有大佬可以帮帮忙或者提醒一下这种多次使用按键的应该怎么写。谢谢


回复

使用道具 举报

ID:739545 发表于 2020-5-19 17:21 | 显示全部楼层
这样表达经常出问题,定义某个管脚,然后判断P3_x==0试一下
回复

使用道具 举报

ID:565305 发表于 2020-5-19 18:14 | 显示全部楼层
从你现在代码结构来看:

    在 delay(1) 的 for(i=0;i<n;i++) 前面,要改几个局部变量为全局变量,并且加入按键判断的那段逻辑代码(改成函数形式),还要【状态变更】。

    当然,可能会觉得,没必要每次都判断按键啊, 所以,判断按键的时机,也有几种选择:

    # 在 delay(1) 中加全局计数器,当满某计数 CountMax 后,例如 CountMax=50 ms 就处理一次按键并【状态变更】一次
     (从目前代码看后续显示有大量 delay1() 函数)
      假设 n 大于了 CountMax 怎么处理? 简单,目前代码中,可以用 10ms 为一个单位,
      延迟 100 毫秒就相当于循环 10 次 10ms,会触发 CountMax>=50ms 两次。
      当然,这种方法,因为代码执行耗费时间长度不一样,计时会有偏差。

   # 或者,每轮 for(;m>=0;m--) / for(;m<=7;m++) 之后,再才读取按键并【状态变更】一次,当然这种会丢按键。
      一般来说,每一次按键,大概会有 60ms 以上 ,折算最高每秒按 15 下按键,一般人按 12  13 下最多了

   # 又或者在计时器中断上,每隔 XX 毫秒 读取按键消息(做个记录), 然后在 delay1() 中处理该消息,再进行【状态变更】。

   注:【状态变更】,包含强行退出 每轮 for(;m>=0;m--) / for(;m<=7;m++) 的循环结构的标志处理。
         简单点,可以让 delay1 返回值来做这样的判断 ,例如  for(...){  if(delay1(n)!=0) break;  ... }; 或者做个全局标志也行;
         同时,还要留存一些变量防止每次换状态后,灯从头跑起。

另外也有一些方法,比方说,灯的更新动作在定时器中断上(定时器中断代码内不写 delay 了),由按键改了 speed 或者灯态的值 → 换算并修订下次中断时间或者使能中断 。这种改法要防止中断重入、做消息处理以及变量规划等,细节比较多就不展开了。(反过来,按键更新,在定时器中断上做也行啊,就是灯方向处理)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:452212 发表于 2020-5-20 18:01 | 显示全部楼层
egypt 发表于 2020-5-19 18:14
从你现在代码结构来看:

    在 delay(1) 的 for(i=0;i=50ms 两次。

谢谢回复,我再仔细看看
回复

使用道具 举报

ID:755472 发表于 2020-5-21 08:30 | 显示全部楼层
程序有问题
回复

使用道具 举报

ID:452212 发表于 2020-5-21 10:18 | 显示全部楼层

请问你指的是程序的某个部分,还是全部?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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