久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3514|回復: 20
收起左側

一個單片機按鍵長按,短按程序設計,為什么沒法實現功能?

  [復制鏈接]
ID:858009 發表于 2021-9-8 15:34 | 顯示全部樓層 |閱讀模式
本帖最后由 qwettyuio 于 2021-9-8 17:33 編輯

#include <reg51.h>
#include <intrins.h>

sbit LED = P1;
sbit KEY1 = P3^0;

typedef unsigned int uint;
typedef unsigned int uchar;
unsigned char modeFlag = 0;   //短按
unsigned char SetFlag  = 1;   //長按

void delay(uint x)    //延時程序函數
{
        uint i,j;
        for(i=x;i>0;i--)
        for(j=110;j>0;j--);
}
void key()
{
        uchar count;
        if(KEY1==0)
        {
                delay(10);
                if(KEY1==0)
                {
                        count=0;
                        while(KEY1==0)
                        {
                                count++;
                        }
                        if(count<500)
                        {
                                modeFlag++;
                                if(modeFlag>=4)
                                        modeFlag=0;
                        }
                        else
                        {
                                SetFlag++;
                                if(SetFlag>=3)
                                        SetFlag=1;
                        }
                }
        }
}
void main()
{
       
        while(1)
        {
                key();
                if(modeFlag==1)
                {
                        P1=0xfe;
                }
                else if(modeFlag==2)
                {
                        P1=0xfd;
                }
                else if(modeFlag==3)
                {
                        P1=0xfc;
                }
                else if(SetFlag==1)
                {
                        P1=0xfb;
                }
                else if(SetFlag==2)
                {
                        P1=0xfa;
                }
        }
}
回復

使用道具 舉報

ID:514901 發表于 2021-9-8 16:09 | 顯示全部樓層
while(KEY1==0)
                        {
                                count++;
                        }
這里沒加延時,你按一下,count估計要溢出好幾百次
回復

使用道具 舉報

ID:609524 發表于 2021-9-8 16:15 | 顯示全部樓層
把key函數放到while(1)里面呀,還有最好不要用while判斷按鍵,
回復

使用道具 舉報

ID:624769 發表于 2021-9-8 16:18 | 顯示全部樓層
  if(KEY1==0)
         {
                 delay(10);         這里你是為了消抖對吧?
                 if(KEY1==0)      那么,這里 == 0  的話,你手一定摁著
                 {
                         count=0;     這里 12 個機器 時鐘  (89C51前提下)
                         while(KEY1==0)    這里每次判斷12個機器時鐘   (89C51前提下)
                         {
                                 count++;     這里每24個 時鐘會累加一次     (89C51前提下)
                         }                                  也就是說,即便你用89C51, 晶振12MHz, 2微秒+1 就算你1毫秒就收手,也500次了。
回復

使用道具 舉報

ID:858009 發表于 2021-9-8 16:30 | 顯示全部樓層
188610329 發表于 2021-9-8 16:18
if(KEY1==0)
         {
                 delay(10);         這里你是為了消抖對吧?

怎么修改才可以
回復

使用道具 舉報

ID:858009 發表于 2021-9-8 16:32 | 顯示全部樓層
楊天想 發表于 2021-9-8 16:15
把key函數放到while(1)里面呀,還有最好不要用while判斷按鍵,

把他放進去,就實現不了短按和長按控制,目的是一個按鍵實現短按切換三個模式,長按控制;兩個電機
回復

使用道具 舉報

ID:858009 發表于 2021-9-8 16:33 | 顯示全部樓層
188610329 發表于 2021-9-8 16:18
if(KEY1==0)
         {
                 delay(10);         這里你是為了消抖對吧?

目的是一個按鍵實現短按切換三個模式,長按控制切換兩個電機
回復

使用道具 舉報

ID:858009 發表于 2021-9-8 16:35 | 顯示全部樓層
鄭漢松 發表于 2021-9-8 16:09
while(KEY1==0)
                        {
                                count++;

加延時也不可以,目的是一個按鍵實現短按切換三個模式,長按控制;兩個電機
回復

使用道具 舉報

ID:624769 發表于 2021-9-8 16:38 | 顯示全部樓層

我長按短按,都是在定時器里面判斷的.
回復

使用道具 舉報

ID:624769 發表于 2021-9-8 16:48 | 顯示全部樓層


按鍵.png
這是我以前做電壓表的時候, 用到的部分代碼, 里面有判斷長按短按,你可以參考.

由于是按鍵的端口復用, 1個IO口 通過LED的公共端的周期點亮,實現多個按鍵的判斷,你可以參考,也可以忽略。
T2定時器是 5毫秒進入一次。由于3個公用按鍵輪循,實際每個按鍵是15毫秒判斷一次,并且+1
回復

使用道具 舉報

ID:858009 發表于 2021-9-8 16:48 | 顯示全部樓層
188610329 發表于 2021-9-8 16:38
我長按短按,都是在定時器里面判斷的.

有例子嗎
回復

使用道具 舉報

ID:858009 發表于 2021-9-8 16:49 | 顯示全部樓層
188610329 發表于 2021-9-8 16:38
我長按短按,都是在定時器里面判斷的.

不是用51單片機的,用的是ch552單片機
回復

使用道具 舉報

ID:624769 發表于 2021-9-8 16:57 | 顯示全部樓層
qwettyuio 發表于 2021-9-8 16:49
不是用51單片機的,用的是ch552單片機

道理是一樣的, CH552 也是 51內核, 我用過閹割版 CH551, 少個ADC功能而以, 和89C51 基本一樣的編程,就是CH552多了些硬件,比如SPI什么的。還多了128字節的 Eeprom 真正的Eeprom 而不是 89C51那種用 IAP模擬的 Eeprom
回復

使用道具 舉報

ID:858009 發表于 2021-9-8 17:04 | 顯示全部樓層
188610329 發表于 2021-9-8 16:57
道理是一樣的, CH552 也是 51內核, 我用過閹割版 CH551, 少個ADC功能而以, 和89C51 基本一樣的編程,就 ...

你用過552,我想問一下我用定時器控制pwm輸出,按鍵脈寬怎么不能實現的
#include "CH552.H"                                                  
#include "Debug.H"
#include "Timer.H"
#include "stdio.h"
#include "GPIO.H"

#pragma  NOAREGS

//UINT8 FLAG;
//UINT16 Cap[8] = {0};
//typedef unsigned int uint16_t;
sbit LED1 = P3^4;
sbit led2 = P1^3;
sbit key = P1^4;
unsigned int condition=0;//這里高電平占一份
unsigned int cnt;                  //整個周期
void button();

void main( )
{
    CfgFsys( );                                                                //CH554時鐘選擇配置   
    mDelaymS(5);                                                               //修改主頻,建議稍加延時等待主頻穩定        
        Port3Cfg(1,4);
        Port1Cfg(1,3);
        Port1Cfg(3,4);
    mTimer0Clk12DivFsys();                                                           //T0定時器時鐘設置
    mTimer_x_ModInit(0,2);                                                     //T0 定時器模式設置
    mTimer_x_SetData(0,0x5555);                                                       //T0定時器賦值
    mTimer0RunCTL(1);                                                          //T0定時器啟動       
    ET0 = 1;                                                                   //T0定時器中斷開啟               
    EA = 1;
    while(1)
        {
                if(cnt>=100)
                {
                        LED1=0;
                }
                if(cnt<condition)
                {
                        LED1=1;
                }
                else
                {
                        LED1=0;
                }
                button();
        }
}
void Time0Interrupt(void) interrupt INT_NO_TMR0 using 1
{
        mTimer_x_SetData(0,0x5555);                                                       //T0定時器賦值
    cnt++;
}
void button()
{
        if(key==0)
        {
                mDelaymS(5);
                if(key==0)
                {
                        condition=condition+30;         //調制脈寬
            led2=!led2;                                //led燈反轉
            if(condition>=90)                //如果脈寬等于總周期了等于0
                        {
                                condition=90;
            }
            while(!key);                          //等待按鍵松手
                }
        }
}
回復

使用道具 舉報

ID:769980 發表于 2021-9-8 17:24 | 顯示全部樓層
在這里面加 延時試試吧,                       
while(KEY1==0)
                        {
                            if(count<200)  //防止溢出吧
                               {
                                count++;
                                 }
                                delay(10); //具體延時多久,你慢慢調試咯
                        }

看著你到處都是delay(10),LED顯示延時,檢測延時,這樣的程序,能實際使用嗎?
回復

使用道具 舉報

ID:624769 發表于 2021-9-8 17:29 | 顯示全部樓層
qwettyuio 發表于 2021-9-8 16:49
不是用51單片機的,用的是ch552單片機

我忽然想起一個問題, CH552,屬于 “產品向” 的單片機, 看你的代碼,你用 “學習向” 的單片機應該更好些。
回復

使用道具 舉報

ID:213173 發表于 2021-9-8 17:31 | 顯示全部樓層
給你一款簡單實用的按鍵長短按程序
  1. #include <REG51.H>
  2. #define uint unsigned int                         //宏定義數據類型uint
  3. #define uchar unsigned char                 //宏定義數據類型uchar
  4. #define key_S 1000                                        //宏定義短按(約20ms)
  5. #define key_L key_S*50                                //宏定義長按(約1s)

  6. sbit key=P3^6;
  7. sbit LED1=P1^0;
  8. sbit LED2=P1^4;

  9. void keyscan()                                                //按鍵掃描
  10. {
  11.         static uint count=0;                        //計數變量
  12.         if(!key)   
  13.         {  
  14.                 count++;  
  15.                 if(count==key_L)                        //長按
  16.                         LED2=!LED2;                                //長按任務
  17.                 if(count>key_L)                                //防止count溢出
  18.                         count=key_L+1;          
  19.         }  
  20.         else                                                        //按鍵抬起
  21.         {  
  22.                 if(count>key_S && count<key_L)//短按
  23.                         LED1=!LED1;                                //短按任務
  24.                 count=0;                                        //count清0
  25.         }   
  26. }
  27. void main()
  28. {
  29.         while(1)
  30.         {
  31.                 keyscan();       
  32.         }
  33. }
復制代碼
回復

使用道具 舉報

ID:123289 發表于 2021-9-9 14:49 | 顯示全部樓層
思路不清,故程序也寫不好,教你一下:
要點:
1、不要用DELAY()函數,何也?在DELAY這段時間里就無法做其它事,這段時間里與死機沒有區別。
2、不要在【按下】時做界定,而要在【彈起】時做界定。何也?這樣才知道是【短按】【中按】【長按】……
實現方法:
1、設置N個標記,分別表示:這里就用【短按】【長按】兩種吧,【短按】有效B_DA=1,【長按】有效B_CA=1。更多種按法如法炮制……
2、設置N個計時器,分別計時【短按】R_DA(如0.05-0.3秒)、【長按】R_CA(如>2秒)時間界定值。
3、做個定時器,用于計時,例如:10ms中斷一次。(這是避免用DELAY的方法!)
4、初始化參數:開機時將上述各參數清0。
5、主程序中執行如下程序:(這里享受結果,而且只需測試一下標記即可)
如果【短按】B_DA=1,就認為【短按】了,執行短按要做的事。一定要記住!:做完后將B_DA清0(這是做沒做過事件處理的關鍵所在)。如果B_DA=0就當什么也未發生,程序跳過。自然【長按】也類似處理,相信這點樓主不用教。
6、【最關鍵的部分:】定時中斷時執行如下程序:(在定時器中斷服務程序中處理,就避免用DELAY了,而且是最快完成界定)
6.1、如果B_DA=1,什么也不做(【短按】已被認可,所以無需再處理,當事件被處理后,主程序會將它清0的,未清0則說明還未處理,或正在處理過程中還未處理完畢)。【長按】類同。
6.2、如果【按鍵】按下了,則將R_DA+1,這里有個要點:需要設置一個極限,防止溢出,如253,到了253就不要再加了。R_CA類同!(這里只在按下時,才做按鍵的計時,但只計時,不做界定!)
6.3、如果【按鍵】彈起了,則做裁定:(要點:界定在彈起時做)
6.3.1、干擾裁定:R_DA<50ms(<5次),不做裁定,清R_DA=0,重新計時。R_CA同。(時間太短,作彈動處理。這個方法也可用于抗按鍵彈動處理程序,比用DEALY強多了!!)
6.3.2、有效裁定:R_DA=0.05-0.3秒(5-30次,時間在什么范圍內,你自己定),裁定為【短按】令B_DA=1,清R_DA=0,重計為下次做準備。R_CA>2秒(>200次,時間大于多少,你自己定),裁定為【長按】令B_CA=1,清R_CA=0,重新計時,為下次做準備。

妙吧:
中斷服務程序只做裁定(決定標記是否為1,鍵有效),但不做事件的處理!
主程序只識別處理事件(根據標記,決定做不做事件處理,做完后清除標記),卻不做裁定。
回復

使用道具 舉報

ID:123289 發表于 2021-9-9 14:54 | 顯示全部樓層

如果不考慮按鍵交叉(兩種或多種事件同時產生),只用一個計時器也可以識別【短按】【中按】【長按】……,這樣程序會更簡單,相信樓主自己會考慮清楚的。
回復

使用道具 舉報

ID:887202 發表于 2021-9-14 16:44 | 顯示全部樓層
建議你去搜索一下按鍵狀態機,實現按鍵長按短按雙擊等都是比較好的,而且實用性也很好,類似于你的這種通過延時去抖的方式實現按鍵其實是不太好的
回復

使用道具 舉報

ID:130230 發表于 2021-9-17 14:00 | 顯示全部樓層
狀態機,網上大把
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久不卡 | 国产精品久久久久久久久久不蜜臀 | jav成人av免费播放 | 99视频在线免费观看 | 国精产品一区一区三区免费完 | 色婷婷精品| 性高湖久久久久久久久3小时 | 一级黄a | 免费在线观看一级毛片 | 韩日在线 | 午夜码电影 | 91精品国产综合久久精品 | 欧美一区二区三区在线观看 | 99re6热在线精品视频播放 | 日韩天堂av | 国产在线观看一区二区三区 | 国产精品大片 | 亚洲精品68久久久一区 | 久久一区二区三区电影 | 国产在线资源 | 久久久久久久久久久久久久av | 欧美一区二区三区在线观看视频 | 亚洲五码在线 | 一区二区视频在线 | 国产精品日韩欧美一区二区三区 | 欧美一二三区 | 国产一级免费视频 | 色屁屁在线观看 | 日韩和的一区二区 | 日本中文字幕在线观看 | 一区二区三区视频在线免费观看 | 亚洲第1页| 一区二区三区在线免费观看 | 特一级毛片| 欧美精品在线观看 | 国产一区二区美女 | 另类在线 | 午夜精品一区 | 四虎午夜剧场 | 91精品国产91久久久久久最新 | 国产真实精品久久二三区 |