找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2618|回复: 22
收起左侧

关于单片机C语言按键程序问题

[复制链接]
ID:777834 发表于 2020-9-7 21:39 来自手机 | 显示全部楼层 |阅读模式
大家好呀,为何定义a=1时,下面if判断a==0时,程序才能进去的,可为何定义a=1时,程序也能进得来的呢?想不通
IMG_20200907_213156.jpg
回复

使用道具 举报

ID:332444 发表于 2020-9-7 22:11 | 显示全部楼层
断章取义?当按钮没按下时又赋值0因此可以通过判断。
回复

使用道具 举报

ID:777834 发表于 2020-9-7 22:30 来自手机 | 显示全部楼层
xianfajushi 发表于 2020-9-7 22:11
断章取义?当按钮没按下时又赋值0因此可以通过判断。

能详细的说下吗,谢谢
回复

使用道具 举报

ID:511890 发表于 2020-9-8 00:38 | 显示全部楼层
应该是变量名冲突或者静态局部变量的问题吧。
一种可能是还有一个变量a的优先级优先于你设置的那个静态变量。
另一种可能是这个静态变量已经在别的地方被初始化过一次了,所以在这里,这个变量已经不能被再次初始化。相当于这条语句无用。
       不明白这里为啥要用static,一般情况下的局部变量如果没有必要的话,最好让程序本身去处理,而不用加上static。

评分

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

查看全部评分

回复

使用道具 举报

ID:213173 发表于 2020-9-8 06:37 | 显示全部楼层
这段按键代码中位变量a不论初始定义为1或0,初次调用an_jian()时只要S1没有按下就执行else a=0;,由于a是静态变量,再次调用an_jian()时a值不变。假设先按住S1不放再加电,就执行不了LED1=~LED1;,必须松手以后再次按下才能执行LED1=~LED1;。但通常从加电到操作按键,an_jian()已经被调用了无数遍。这就是楼主感觉a不论初始定义为1或0都能正常工作的原因。
这段代码的合理写法:
void an_jian()
{
        static bit a=0;
        if(S1==0)
        {
                delays_2ms(15);
                if(S1==0 && a==0)
                {
                        a=1;
                        LED1=~LED1;
                }
        }
        else
        {
                a=0;
        }
}
回复

使用道具 举报

ID:777834 发表于 2020-9-8 08:03 来自手机 | 显示全部楼层
幻剑心 发表于 2020-9-8 00:38
应该是变量名冲突或者静态局部变量的问题吧。
一种可能是还有一个变量a的优先级优先于你设置的那个静态变 ...

您好,谢谢您的回复先,不加static不行,试过了,没有松手检测
回复

使用道具 举报

ID:777834 发表于 2020-9-8 08:25 来自手机 | 显示全部楼层
wulin 发表于 2020-9-8 06:37
这段按键代码中位变量a不论初始定义为1或0,初次调用an_jian()时只要S1没有按下就执行else a=0;,由于a是静 ...

您好,首先谢谢你的回复,应该就是这样的了,现在我在想可以在这个原基础上改长按与短按的程序吗,比如短按LED1亮,长按LED2亮,网上有用while(S1==0)作计数累加的,大于某个数就是长按,短于某个数就是短按,但是有个问题就是不松开就就不能执行其它的程序了,您看能不能改下,或写下程序,我验证下,谢谢啦,不能用定时中断哦,我想看用其它的方法可不可以做到,谢谢啦
回复

使用道具 举报

ID:213173 发表于 2020-9-8 11:34 | 显示全部楼层
jianuli 发表于 2020-9-8 08:25
您好,首先谢谢你的回复,应该就是这样的了,现在我在想可以在这个原基础上改长按与短按的程序吗,比如短 ...

给你一个简单的长短按键示例参考,延时函数相当于其它应用程序所占时间,按键时间长短不影响其它程序运行,端口根据实际电路自行定义。
#include <reg51.H>
#define uchar unsigned char
#define uint unsigned int

sbit LED1=P3^0;                                        //LED1端口定义
sbit LED2=P3^1;                                        //LED2端口定义
sbit key =P3^2;                                        //开关端口定义       

/****1ms延时子程序(12MHz)****/
void delayms(uint k)
{
        uint i,j;
        for(i=k;i>0;i--)
                for(j=125;j>0;j--);
}
/******按键扫描程序*******/
void keyscan()
{
        static bit sign=0;                //长按标志
        static uint count=0;                //消抖、长短识别计数变量                       

        if(key==0)                                        //检测按键如果按下
        {
                count++;
                if(count>500)
                        count=501;
                if(count==500)                        //长按0.5s                       
                {
                        sign=1;                          //长按标志置1
                        LED2=~LED2;
                }
        }
        else                                                //按键抬起
        {
                if(count>=10 && sign==0)//短按
                        LED1=~LED1;       
                count=0;                                //计数清0
                sign=0;                                //长按标志置清0
        }
}

void main()
{
        while(1)
        {
                keyscan();
                //其它任务
                delayms(1);//控制主循环周期约1ms
        }
}

回复

使用道具 举报

ID:777834 发表于 2020-9-8 12:39 来自手机 | 显示全部楼层
wulin 发表于 2020-9-8 11:34
给你一个简单的长短按键示例参考,延时函数相当于其它应用程序所占时间,按键时间长短不影响其它程序运行 ...

好的,谢谢啦,有空我验证下,到时回复你
回复

使用道具 举报

ID:777834 发表于 2020-9-8 14:33 来自手机 | 显示全部楼层
wulin 发表于 2020-9-8 11:34
给你一个简单的长短按键示例参考,延时函数相当于其它应用程序所占时间,按键时间长短不影响其它程序运行 ...

您好呀,刚刚按你的程序试了下,发现短按时可以正常开与关,长按后,就死机一样了,短按与长按都不行了,您看看是哪里的问题,谢谢啦
回复

使用道具 举报

ID:777834 发表于 2020-9-8 14:34 来自手机 | 显示全部楼层
wulin 发表于 2020-9-8 11:34
给你一个简单的长短按键示例参考,延时函数相当于其它应用程序所占时间,按键时间长短不影响其它程序运行 ...

图片贴不上来
回复

使用道具 举报

ID:328014 发表于 2020-9-8 15:15 | 显示全部楼层

回帖上图的方法:http://www.51hei.com/bbs/dpj-134340-1.html

手机版 点照相机按钮可以直接上图
回复

使用道具 举报

ID:213173 发表于 2020-9-8 15:41 | 显示全部楼层

这个程序虽然非常简单,本着负责任的态度我还是用仿真软件验证无误才发出的。你说长按后,就像死机一样。我再次用TX-1C实验板验证,只改了端口定义,确定没有任何问题。你仔细检查你的硬件电路有没有问题。为防止直接发代码出错,用专用代码文字模式发。
  1. #include <reg51.H>
  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. sbit LED1=P1^0;                 //LED1端口定义
  5. sbit LED2=P1^1;                 //LED2端口定义
  6. sbit key =P3^4;                 //开关端口定义        

  7. /****1ms延时子程序(11.0592MHz)****/
  8. void delayms(uint k)
  9. {
  10.         uint i,j;
  11.         for(i=k;i>0;i--)
  12.                 for(j=110;j>0;j--);
  13. }
  14. /******按键扫描程序*******/
  15. void keyscan()
  16. {
  17.         static bit sign=0;       //长按标志
  18.         static uint count=0;     //消抖、长短识别计数变量                        
  19.        
  20.         if(key==0)               //检测按键如果按下
  21.         {
  22.                 count++;
  23.                 if(count>500)
  24.                         count=501;
  25.                 if(count==500)   //长按0.5s                        
  26.                 {
  27.                         sign=1;  //长按标志置1
  28.                         LED2=~LED2;
  29.                 }
  30.         }
  31.         else                         //按键抬起
  32.         {
  33.                 if(count>=10 && sign==0)//短按
  34.                         LED1=~LED1;        
  35.                 count=0;                   //计数清0
  36.                 sign=0;                   //长按标志置清0
  37.         }
  38. }

  39. void main()
  40. {
  41.         while(1)
  42.         {
  43.                 keyscan();
  44.                 //其它任务
  45.                 delayms(1);//控制主循环周期约1ms
  46.         }
  47. }
复制代码




回复

使用道具 举报

ID:123289 发表于 2020-9-8 15:44 | 显示全部楼层
如果你能弄清楚,静态变量在单片机中是如何存储的,它放在哪里,你就明白。
主要是你对变量在单片机中是如何存储的,未弄清楚。
回复

使用道具 举报

ID:777834 发表于 2020-9-8 18:48 来自手机 | 显示全部楼层
yzwzfyz 发表于 2020-9-8 15:44
如果你能弄清楚,静态变量在单片机中是如何存储的,它放在哪里,你就明白。
主要是你对变量在单片机中是如 ...

您好,因为刚开始学单片机,所以很多知识点还没弄懂,又因为是自学的,身边没人指导,所以很简单的问题也要很久才能理解。
回复

使用道具 举报

ID:777834 发表于 2020-9-8 18:55 来自手机 | 显示全部楼层
wulin 发表于 2020-9-8 15:41
这个程序虽然非常简单,本着负责任的态度我还是用仿真软件验证无误才发出的。你说长按后,就像死机一样。 ...

您好,我再重写一遍看看
回复

使用道具 举报

ID:777834 发表于 2020-9-8 20:16 来自手机 | 显示全部楼层
wulin 发表于 2020-9-8 15:41
这个程序虽然非常简单,本着负责任的态度我还是用仿真软件验证无误才发出的。你说长按后,就像死机一样。 ...

您好呀,是我自己写错了,不好意思啊,我写成左边这样的,写成右边的才对,现在程序可以完美运行了,丝毫不影响其它程序的执行,能说说原理吗,就是不太明白怎样与while那里结合执行,谢谢啦,有点麻烦你了
IMG_20200908_200434.jpg
回复

使用道具 举报

ID:89515 发表于 2020-9-8 22:02 来自手机 | 显示全部楼层
这样做,程序太大。按键会卡卡的!!!而且不符合肖抖原理。学习下就好。
回复

使用道具 举报

ID:777834 发表于 2020-9-8 22:09 来自手机 | 显示全部楼层
mengzhixinheng 发表于 2020-9-8 22:02
这样做,程序太大。按键会卡卡的!!!而且不符合肖抖原理。学习下就好。

您好,是的,就当学习,如果while(1)中还有延时,那按键基本动不了,刚才试过,哈哈,如果while(1)中没有延时的话就运行的很完美
回复

使用道具 举报

ID:89515 发表于 2020-9-9 10:25 来自手机 | 显示全部楼层
jianuli 发表于 2020-9-8 22:09
您好,是的,就当学习,如果while(1)中还有延时,那按键基本动不了,刚才试过,哈哈,如果while(1)中没有 ...

运行完美?你想多了,这样写,要运行完美,你必须精确控制每个函数的运行时间,做到严格的消抖。不然实际应用肯定不保险的!非要不用定时器中断的话,你得学习一下程序轮询的方法,不过相信我,不加时间片更麻烦。我感觉没意义。
回复

使用道具 举报

ID:146782 发表于 2020-9-9 10:35 | 显示全部楼层
变量应该定义成局部变量
回复

使用道具 举报

ID:777834 发表于 2020-9-9 12:19 来自手机 | 显示全部楼层
mengzhixinheng 发表于 2020-9-9 10:25
运行完美?你想多了,这样写,要运行完美,你必须精确控制每个函数的运行时间,做到严格的消抖。不然实际 ...

嗯,这样写法当作学习,谢谢指导
回复

使用道具 举报

ID:777834 发表于 2020-9-28 22:08 来自手机 | 显示全部楼层
wulin 发表于 2020-9-8 15:41
这个程序虽然非常简单,本着负责任的态度我还是用仿真软件验证无误才发出的。你说长按后,就像死机一样。 ...

您好呀,在这个程度基础上想改按键释放延时时间怎样改,谢谢啦,指导一下
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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