找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机独立按键短按加1,长按连加总是无法实现,问题在哪?

[复制链接]
跳转到指定楼层
楼主
ID:997026 发表于 2022-2-13 19:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在做单片机独立按键长按连加,短按加1的功能,网上找了很多例子,都不是很满意,试了很多都不成功。最后找了一个很多人在用的代码,不知道什么原因,在我这边总是无法实现功能,搞了好几天都不能解决,修修改改无数次,实在是没思路了。以下是这部分代码,希望大神赐教!

现在的主要问题是:
1,只能实现短按一次的功能,即数码管显示0时,短按一下可以增加到1,再按就没反应了。
2,应该是KEY_SCAN() 和KEY_PROCESS()这两个函数的问题,但是找了好久,改了很多也没解决问题,现在没有思路了。按键扫描函数KEY_SCAN()是在网上找的朱兆琪学习板的程序,我用的单片机是AVR的,在我上面怎么都用不了,不知道啥问题,不知道是程序问题还是硬件问题,感觉硬件没啥问题,换另一种写法就没问题,但是如下写法总是不行。

单片机源程序如下:
unsigned char   key_number=0;  //触发的按键编号
unsigned short  key_time_delay_cnt_SW1 =0;   // SW1 按键去抖动计数器
unsigned char   key_lock_SW1=0;              // SW1 自锁变量
unsigned short  key_cont_trigg_cnt_SW1 =0;   //SW1连加计数器


unsigned short  key_start_cnt1 =0; //中断启动计数器标志位
unsigned short  key_start_cnt2 =0;
unsigned short  key_start_trigg_cnt1 =0;
unsigned short  key_start_trigg_cnt2 =0;




uint8_t KEY_SCAN(void);  // 按键扫描函数
void KEY_PROCESS(uint8_t);  //按键处理函数



int  main(void)

{
  KEY_PROCESS(P_min_set_temp_ON);  //P_min_set_temp_ON在数码管上显示分和秒
}



uint8_t  KEY_SCAN(void)

{
        // 扫描SW1
        if (1==KEY_SW1)  //按键没有被按下(高电平),清零标志位
        {
                key_lock_SW1 =0;  //自锁标志位清零
                key_time_delay_cnt_SW1=0; //去抖延时清零
                key_start_cnt1=0;  //在中断中启动计数
                key_cont_trigg_cnt_SW1 =0;
                key_start_trigg_cnt1=0; //在中断中启动计数
        }
        
        else if (0==key_lock_SW1) //如果有按键按下,且是第一次按下
        {
                key_start_cnt1=1;  //中断中启动计数器,key_time_delay_cnt_SW1开始自加
                if (key_time_delay_cnt_SW1 > KEY_TIME_DELAY_SW1) //自加到10mms去抖动,KEY_TIME_DELAY_SW1为进入中断10次,约10ms
                {
                        key_time_delay_cnt_SW1 =0;
                        key_start_cnt1=0;
                        key_lock_SW1=1;
                        key_number=1; //触发 一次SW1单次触发,如果松手,立即返回到if (KEY_SW1)
               
                }
        }

        else if (key_time_delay_cnt_SW1 < KEY_TIME_ALWAYS_PRESS) //如果按住不放, 在1s内自加,KEY_TIME_ALWAYS_PRESS为1s
        {
                key_start_cnt1=1;
        }
        
        else  //持续按住大于1s时,进入连加状态
        {
                key_start_trigg_cnt1=1; //启动key_cont_trigg_cnt_SW1自加
                if (key_cont_trigg_cnt_SW1 > KEY_TIME_SEQ_INTER)  //自加到250ms后,清零,KEY_TIME_SEQ_INTER为250ms
                {
                        key_cont_trigg_cnt_SW1 =0;
                        key_start_trigg_cnt2=0;
                        key_number =2; //触发SW1连续触发,实现长按SW1超过1s, 产生每250ms触发一次按键的效果
               
                }
        }

   return  key_number; //返回按键编号值

}


void KEY_PROCESS (uint8_t min_sec_set_temp)

{  
            KEY= KEY_SCAN(); //根据返回的按键编号值处理
                switch (KEY)
                {
                        case 1:  // SW1 单次触发
                        min_sec_set_temp ++;
                        if (min_sec_set_temp >99)
                        {
                                min_sec_set_temp=0;
                        }
                        //key_number=0;
                        
                        break;
                        
                        case 2: //SW1开始连加触发
                        min_sec_set_temp --;
                        if (min_sec_set_temp >99)
                        {
                                min_sec_set_temp=99;
                        }
                        
                        break;

                        
                        default: ; break;
                }
               
                min_decade=min_sec_set_temp /10; //数码管显示
                min_the_uint=min_sec_set_temp %10;
                sec_decade=min_sec_set_temp /10;
                sec_the_uint=min_sec_set_temp %10;
               
        
                DISPLAY_TIME_SET_MIN_SEC(1); //数码管显示函数,通过按键加减数字可以显示出来               
}

        



ISR(TIMER1_OVF_vect) //中断服务程序, 8M/256分频,1ms进一次中断

{
        TIFR1  =0x01; //中断标志置位
        TIMSK1 =0x00;  //关中断
        
    if (key_start_cnt1==1)
    {
                key_time_delay_cnt_SW1 ++;
    }
        
        else
        {
                key_time_delay_cnt_SW1=0;
        }
        
         if (key_start_cnt2==1)
         {
                 key_time_delay_cnt_SW2++;
         }
         else
         {
                 key_time_delay_cnt_SW2=0;
         }
         
         if (key_start_trigg_cnt1==1)
         {
                 key_cont_trigg_cnt_SW1 ++;
         }
         else
         {
                 key_cont_trigg_cnt_SW1=0;
         }
         
         if (key_start_trigg_cnt2==1)
         {
                 key_cont_trigg_cnt_SW2 ++;
         }
         else
         {
                 key_cont_trigg_cnt_SW2=0;
         }
        
         
        TCNT1H =0xFF; //计数器重装初值高八位
        TCNT1L =0xE0; //计数器重装初值低八位
        TIMSK1=0x01; //开中断
}


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

使用道具 举报

沙发
ID:301191 发表于 2022-2-14 01:32 | 只看该作者
顶一下
回复

使用道具 举报

板凳
ID:213173 发表于 2022-2-14 05:43 | 只看该作者
给你一个应用示例参考
4位数码管时钟温度表仿真.rar (175.42 KB, 下载次数: 32)

回复

使用道具 举报

地板
ID:57657 发表于 2022-2-14 06:26 | 只看该作者
你可以看下这个框架是怎么实现长按连加的
http://www.51hei.com/bbs/dpj-214058-1.html
回复

使用道具 举报

5#
ID:844772 发表于 2022-2-14 08:51 | 只看该作者
不是那两个函数的问题,是你用它们的问题吧?   
case 2: //SW1开始连加触发      
           min_sec_set_temp --; //为啥用--呢?明明是++的。
回复

使用道具 举报

6#
ID:997026 发表于 2022-2-14 10:04 | 只看该作者
glinfei 发表于 2022-2-14 08:51
不是那两个函数的问题,是你用它们的问题吧?   
case 2: //SW1开始连加触发      
           min_sec_ ...

不是的,这个贴的时候注释没改过来。实际程序不是这样的。
回复

使用道具 举报

7#
ID:997026 发表于 2022-2-14 10:08 | 只看该作者
wulin 发表于 2022-2-14 05:43
给你一个应用示例参考

感谢!我研究一下
回复

使用道具 举报

8#
ID:997026 发表于 2022-2-14 10:08 | 只看该作者
npn 发表于 2022-2-14 06:26
你可以看下这个框架是怎么实现长按连加的
http://www.51hei.com/bbs/dpj-214058-1.html

感谢,我研究一下
回复

使用道具 举报

9#
ID:313048 发表于 2022-2-14 10:14 | 只看该作者
用状态机不难吧就一个短按状态和长按状态,外加一个无按下时的状态
回复

使用道具 举报

10#
ID:997026 发表于 2022-2-14 10:19 | 只看该作者
AUG 发表于 2022-2-14 10:14
用状态机不难吧就一个短按状态和长按状态,外加一个无按下时的状态

我用状态机试一下,谢谢
回复

使用道具 举报

11#
ID:161164 发表于 2022-2-14 11:00 | 只看该作者
的确是KEY_PROCESS()的问题
你连基本的C语言函数传参都没有弄懂

你这写法是值传递,等于

  1. uint8_t 真实户口结余 = 1000;

  2. void 手游(uint8_t);
  3. void 显示(uint8_t);

  4. void 手游(手游户口结余)
  5. {
  6.         if(有键按下)
  7.                 手游户口结余+1

  8.         显示(手游户口结余)
  9. }

  10. void main
  11. {
  12.         while(1)
  13.         {
  14.                 手游(真实户口结余);
  15.         }
  16. }
复制代码

只是把"真实户口结余"的值放进"手游户口结余"内
然后对"手游户口结余"+1
手游函数内的操作不会对"真实户口结余"有任何影响

正确写法应该是

  1. uint8_t 手游户口结余 = 1000;

  2. void 手游();
  3. void 显示(uint8_t);

  4. void 手游()
  5. {
  6.         if(有键按下)
  7.                 手游户口结余+1

  8.         显示(手游户口结余)
  9. }

  10. void main
  11. {
  12.         while(1)
  13.         {
  14.                 手游();
  15.         }
  16. }
复制代码
回复

使用道具 举报

12#
ID:1005190 发表于 2022-2-14 20:58 | 只看该作者
局部静态变量static了解一下
回复

使用道具 举报

13#
ID:997026 发表于 2022-2-14 22:23 | 只看该作者
lkc8210 发表于 2022-2-14 11:00
的确是KEY_PROCESS()的问题
你连基本的C语言函数传参都没有弄懂

真的非常感谢你!

你解决了我的问题,我确实犯了这个错误,其实这个我是知道的,但有时就是陷入了死胡同。感谢你!我还得多努力,继续学习!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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