找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3458|回复: 24
收起左侧

单片机按键控制led流水灯闪程序错误解决

[复制链接]
ID:939271 发表于 2021-6-17 12:49 | 显示全部楼层 |阅读模式
求大佬看看这个程序的错误
我想设计一个程序实现,一个按键控制led流水灯闪,一个按键控制灭。但现在按键却没有反应,求大佬看看哪里出了问题
单片机源程序如下:
#include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器
#include<intrins.h>                //因为要用到左右移函数,所以加入这个头文件

typedef unsigned int u16;          //对数据类型进行声明定义
typedef unsigned char u8;

#define led P2           //将P2口定义为led 后面就可以使用led代替P2口
sbit k1=P3^1; //定义 P31 口是 k1
sbit k2=P3^0;
/*
函 数 名         : delay
函数功能                 : 延时函数,i=1时,大约延时10us
*/
void delay(u16 i)
{
        while(i--);        
}
函 数 名         : keypros
函数功能         : 按键处理函数,判断按键 K1 是否按下
*/
void keypros()
{         u8 a=0;
     if(k1==0) //检测按键 K1 是否按下
      {
        delay(1000); //消除抖动 一般大约 10ms
        if(k1==0) //再次判断按键是否按下
       {
            a=1;
         
       }
        while(!k1);  //检测按键是否松开               
                }
     if(k2==0) //检测按键 K1 是否按下
      {
        delay(1000); //消除抖动 一般大约 10ms
        if(k2==0) //再次判断按键是否按下
       {
            a=0;
         
       }
        while(!k2);  //检测按键是否松开               
                }
}

/*
函 数 名       : main
函数功能           : 主函数
*/

void main()
{  u8 a;
   u8 i=0;
   
   
  while(1)
  {        
    keypros();
    if(a==1)
        {        
        led=0xfe;    //         P2  1111 1110(7654 3210)
        delay(50000); //大约延时450ms        
        
                        for(i=0;i<7;i++)         //将数字左移一位,led灯右移
                {
                        led=_crol_(led,1);
                        delay(50000); //大约延时450ms        
                }
        keypros();        
        
        }        
          else{led=0xff;
        keypros();
        }
        
   }
   

  

}
回复

使用道具 举报

ID:453974 发表于 2021-6-17 14:32 | 显示全部楼层
感觉应该是按键的延时时间太长了
回复

使用道具 举报

ID:298123 发表于 2021-6-17 14:44 | 显示全部楼层
两个变量a是啥意思?你想表达什么样的逻辑?
回复

使用道具 举报

ID:94031 发表于 2021-6-17 14:51 | 显示全部楼层
按键状态不能被及时检测造成,最好按键状态由外部中断及时检测。
回复

使用道具 举报

ID:939271 发表于 2021-6-17 15:27 | 显示全部楼层
xuyaqi 发表于 2021-6-17 14:51
按键状态不能被及时检测造成,最好按键状态由外部中断及时检测。

那怎么解决啊?求教
回复

使用道具 举报

ID:711539 发表于 2021-6-17 15:49 | 显示全部楼层
这边建议你回头看看C语言。
  1. void keypros()函数的a,是局部变量。
  2. void main()函数的a,是局部变量。
  3. 它们是两个变量。
  4. 解决方法:取消这两个局部变量,开设一个新的全局变量a。
复制代码

以上。
回复

使用道具 举报

ID:298123 发表于 2021-6-17 16:01 | 显示全部楼层
ncml 发表于 2021-6-17 15:27
那怎么解决啊?求教

按键检测也许是有问题,但也不至于不能用,对初学者,这样的做法也能理解。问题的关键在于你全局变量和局部变量没有搞清楚,还有函数返回值也没有概念。
回复

使用道具 举报

ID:298123 发表于 2021-6-17 16:07 | 显示全部楼层
任重而道远!还是希望打好基础,做应用能做和做好,还是差别很大的!
回复

使用道具 举报

ID:489002 发表于 2021-6-17 16:30 | 显示全部楼层
局部变量 函数1中的a和函数2中的a其实是两个不同的a
回复

使用道具 举报

ID:94031 发表于 2021-6-17 16:35 | 显示全部楼层
ncml 发表于 2021-6-17 15:27
那怎么解决啊?求教

在你程序基础上改了,你试一下。
//k1按下灯循环,k2按下停

#include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器
#include<intrins.h>                //因为要用到左右移函数,所以加入这个头文件

typedef unsigned int u16;          //对数据类型进行声明定义
typedef unsigned char u8;

sbit k1=P3^1; //定义 P31 口是 k1
sbit k2=P3^0;

u8 a;

/*
函 数 名         : keypros
函数功能         : 按键处理函数,判断按键 K1 是否按下
*/
void keypros()
{         
  if(k1==0) //检测按键 K1 是否按下
        {
               
         if(k1==0) //再次判断按键是否按下
         {
                                a=1;
         }
                while(!k1);  //检测按键是否松开               
        }
  if(k2==0) //检测按键 K1 是否按下
        {
               
                if(k2==0) //再次判断按键是否按下
         {
                                a=0;
                 
         }
                while(!k2);  //检测按键是否松开               
        }
}

/*
函 数 名         : delay
函数功能                 : 延时函数,i=1时,大约延时10us
*/
void delay(u16 i)
{
        u16 m;
       
  for(m=0;m<i;)//  
        {
                keypros();
                m++;
        }

}

/*
函 数 名       : main
函数功能           : 主函数
*/
void main()
{  
  u8 ii=0;
        u8 led;
       
  while(1)
  {      
    keypros();
    if(a==1)
                {      
                        led=0xfe;    //         P2  1111 1110(7654 3210)
                                         
                        for(ii=0;ii<7;)//将数字左移一位,led灯右移         
                        {
                                //keypros();
                                led=_crol_(led,1);
                                P2=led;
                                delay(20000); //
        ii++;                               
                        }
                        keypros();      
         
                }      
    led=0xff;    //
                P2=led;
   }
       
         
}
回复

使用道具 举报

ID:298123 发表于 2021-6-17 16:57 | 显示全部楼层
xuyaqi 发表于 2021-6-17 16:35
在你程序基础上改了,你试一下。
//k1按下灯循环,k2按下停

越改越错啦!按键检测里,必要的延迟还是需要的。
回复

使用道具 举报

ID:824490 发表于 2021-6-17 18:00 | 显示全部楼层
按键没延时,如何去抖动?
回复

使用道具 举报

ID:939271 发表于 2021-6-17 19:09 | 显示全部楼层
菜鸟yc 发表于 2021-6-17 15:49
这边建议你回头看看C语言。
以上。

我已经知道错误了,感谢
回复

使用道具 举报

ID:939271 发表于 2021-6-17 19:10 | 显示全部楼层
hz_dyg 发表于 2021-6-17 16:01
按键检测也许是有问题,但也不至于不能用,对初学者,这样的做法也能理解。问题的关键在于你全局变量和局 ...

好的,我主要是为了做作业,以后有机会会加深了解的
回复

使用道具 举报

ID:939271 发表于 2021-6-17 19:16 | 显示全部楼层
菜鸟yc 发表于 2021-6-17 15:49
这边建议你回头看看C语言。
以上。

请问一下,我现在按楼下修改的添加了全局变量,k1点亮没问题,但k2必须长按才能熄灭是什么原因啊?
回复

使用道具 举报

ID:939271 发表于 2021-6-17 19:19 | 显示全部楼层
菜鸟yc 发表于 2021-6-17 15:49
这边建议你回头看看C语言。
以上。

不用了,我懂了,我必须在led流水灯的流程结束的一瞬间执行按键函数的时候按k2才能执行函数使led熄灭。
回复

使用道具 举报

ID:94031 发表于 2021-6-17 19:38 | 显示全部楼层
hz_dyg 发表于 2021-6-17 16:57
越改越错啦!按键检测里,必要的延迟还是需要的。

为了按键的及时性没有延时也是可以的,不要太教条,不要延时会产生什么问题?
回复

使用道具 举报

ID:94031 发表于 2021-6-17 19:41 | 显示全部楼层
名字不是重点 发表于 2021-6-17 18:00
按键没延时,如何去抖动?

在这个程序里不去抖动会出什么问题,不要太教条。
回复

使用道具 举报

ID:94031 发表于 2021-6-17 19:46 | 显示全部楼层
ncml 发表于 2021-6-17 19:16
请问一下,我现在按楼下修改的添加了全局变量,k1点亮没问题,但k2必须长按才能熄灭是什么原因啊?

还是按键响应不及时问题。
回复

使用道具 举报

ID:298123 发表于 2021-6-18 09:19 | 显示全部楼层
xuyaqi 发表于 2021-6-17 19:41
在这个程序里不去抖动会出什么问题,不要太教条。

啊!? 不去抖,按键按下瞬间,很多次跳变,你的程序还能按逻辑运行吗? 这不是教条不教条的问题,没有技术能原谅,但误人子弟不能原谅!
回复

使用道具 举报

ID:94031 发表于 2021-6-18 09:25 | 显示全部楼层
hz_dyg 发表于 2021-6-18 09:19
啊!? 不去抖,按键按下瞬间,很多次跳变,你的程序还能按逻辑运行吗? 这不是教条不教条的问题,没有技 ...

跳变次数再多也是 a=1,会出问题吗?
回复

使用道具 举报

ID:934353 发表于 2021-6-18 11:04 | 显示全部楼层
ncml 发表于 2021-6-17 19:19
不用了,我懂了,我必须在led流水灯的流程结束的一瞬间执行按键函数的时候按k2才能执行函数使led熄灭。

你如果想随时灭掉流水灯,最好设置外部中断,这样就可以随时灭灯了,非常方便
回复

使用道具 举报

ID:824490 发表于 2021-6-18 16:40 | 显示全部楼层
xuyaqi 发表于 2021-6-17 19:41
在这个程序里不去抖动会出什么问题,不要太教条。

这不是教条不教条, 是关乎软件代码的强壮!不延时不怕误触发?不怕干扰?谁家代码的按键不做去抖?
如同进餐馆吃饭,有人要烫一下碗筷,而有些人觉得麻烦不烫,一样的道理。
玩玩可以,真要做产品只能呵呵了。万分之一的BUG机率,对客户来说就是100%的出错。
回复

使用道具 举报

ID:824490 发表于 2021-6-18 16:44 | 显示全部楼层
没有去抖,可能边上一个小车启动一下、大功率电器一个开关、、、你需要的状态就不复存在 了。。。
回复

使用道具 举报

ID:939710 发表于 2021-6-20 12:02 | 显示全部楼层
你最后检测松开的代码应该放在第二次检测按下的括号里,因为你是加了消抖延时的,如果是抖动带来的低电平,延时之后进入了高电平,这样你的程序就卡在了检测是否松开,  虽然你把延时消了能解决这个问题。但是消抖的功能也就没了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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