找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2490|回復: 12
收起左側

單片機獨立按鍵短按加1,長按連加總是無法實現,問題在哪?

[復制鏈接]
ID:997026 發(fā)表于 2022-2-13 19:42 | 顯示全部樓層 |閱讀模式
最近在做單片機獨立按鍵長按連加,短按加1的功能,網上找了很多例子,都不是很滿意,試了很多都不成功。最后找了一個很多人在用的代碼,不知道什么原因,在我這邊總是無法實現功能,搞了好幾天都不能解決,修修改改無數次,實在是沒思路了。以下是這部分代碼,希望大神賜教!

現在的主要問題是:
1,只能實現短按一次的功能,即數碼管顯示0時,短按一下可以增加到1,再按就沒反應了。
2,應該是KEY_SCAN() 和KEY_PROCESS()這兩個函數的問題,但是找了好久,改了很多也沒解決問題,現在沒有思路了。按鍵掃描函數KEY_SCAN()是在網上找的朱兆琪學習板的程序,我用的單片機是AVR的,在我上面怎么都用不了,不知道啥問題,不知道是程序問題還是硬件問題,感覺硬件沒啥問題,換另一種寫法就沒問題,但是如下寫法總是不行。

單片機源程序如下:
unsigned char   key_number=0;  //觸發(fā)的按鍵編號
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; //觸發(fā) 一次SW1單次觸發(fā),如果松手,立即返回到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  //持續(xù)按住大于1s時,進入連加狀態(tài)
        {
                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; //觸發(fā)SW1連續(xù)觸發(fā),實現長按SW1超過1s, 產生每250ms觸發(fā)一次按鍵的效果
               
                }
        }

   return  key_number; //返回按鍵編號值

}


void KEY_PROCESS (uint8_t min_sec_set_temp)

{  
            KEY= KEY_SCAN(); //根據返回的按鍵編號值處理
                switch (KEY)
                {
                        case 1:  // SW1 單次觸發(fā)
                        min_sec_set_temp ++;
                        if (min_sec_set_temp >99)
                        {
                                min_sec_set_temp=0;
                        }
                        //key_number=0;
                        
                        break;
                        
                        case 2: //SW1開始連加觸發(fā)
                        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; //開中斷
}


回復

使用道具 舉報

ID:301191 發(fā)表于 2022-2-14 01:32 | 顯示全部樓層
頂一下
回復

使用道具 舉報

ID:213173 發(fā)表于 2022-2-14 05:43 | 顯示全部樓層
給你一個應用示例參考
4位數碼管時鐘溫度表仿真.rar (175.42 KB, 下載次數: 32)

回復

使用道具 舉報

ID:57657 發(fā)表于 2022-2-14 06:26 | 顯示全部樓層
你可以看下這個框架是怎么實現長按連加的
http://www.torrancerestoration.com/bbs/dpj-214058-1.html
回復

使用道具 舉報

ID:844772 發(fā)表于 2022-2-14 08:51 | 顯示全部樓層
不是那兩個函數的問題,是你用它們的問題吧?   
case 2: //SW1開始連加觸發(fā)      
           min_sec_set_temp --; //為啥用--呢?明明是++的。
回復

使用道具 舉報

ID:997026 發(fā)表于 2022-2-14 10:04 | 顯示全部樓層
glinfei 發(fā)表于 2022-2-14 08:51
不是那兩個函數的問題,是你用它們的問題吧?   
case 2: //SW1開始連加觸發(fā)      
           min_sec_ ...

不是的,這個貼的時候注釋沒改過來。實際程序不是這樣的。
回復

使用道具 舉報

ID:997026 發(fā)表于 2022-2-14 10:08 | 顯示全部樓層
wulin 發(fā)表于 2022-2-14 05:43
給你一個應用示例參考

感謝!我研究一下
回復

使用道具 舉報

ID:997026 發(fā)表于 2022-2-14 10:08 | 顯示全部樓層
npn 發(fā)表于 2022-2-14 06:26
你可以看下這個框架是怎么實現長按連加的
http://www.torrancerestoration.com/bbs/dpj-214058-1.html

感謝,我研究一下
回復

使用道具 舉報

ID:313048 發(fā)表于 2022-2-14 10:14 | 顯示全部樓層
用狀態(tài)機不難吧就一個短按狀態(tài)和長按狀態(tài),外加一個無按下時的狀態(tài)
回復

使用道具 舉報

ID:997026 發(fā)表于 2022-2-14 10:19 | 顯示全部樓層
AUG 發(fā)表于 2022-2-14 10:14
用狀態(tài)機不難吧就一個短按狀態(tài)和長按狀態(tài),外加一個無按下時的狀態(tài)

我用狀態(tài)機試一下,謝謝
回復

使用道具 舉報

ID:161164 發(fā)表于 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. }
復制代碼
回復

使用道具 舉報

ID:1005190 發(fā)表于 2022-2-14 20:58 | 顯示全部樓層
局部靜態(tài)變量static了解一下
回復

使用道具 舉報

ID:997026 發(fā)表于 2022-2-14 22:23 | 顯示全部樓層
lkc8210 發(fā)表于 2022-2-14 11:00
的確是KEY_PROCESS()的問題
你連基本的C語言函數傳參都沒有弄懂

真的非常感謝你!

你解決了我的問題,我確實犯了這個錯誤,其實這個我是知道的,但有時就是陷入了死胡同。感謝你!我還得多努力,繼續(xù)學習!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表