找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 3428|回復(fù): 15
收起左側(cè)

51單片機(jī)如何實(shí)現(xiàn) 按下按鍵執(zhí)行某函數(shù)或語句,松開后停止執(zhí)行這個(gè)函數(shù)或語句

[復(fù)制鏈接]
ID:879924 發(fā)表于 2021-11-16 12:14 | 顯示全部樓層 |閱讀模式
本帖最后由 macboa 于 2021-11-16 12:25 編輯

在做一個(gè)51小車,用定時(shí)器掃描按鍵狀態(tài)。來控制加速和減速。
想實(shí)現(xiàn)的功能是,按住加速按鍵,執(zhí)行加速函數(shù),同時(shí)LED亮,松開就不再加速,燈滅,跳出。
  1. LED1=P1^0;
  2. LED2=P1^1;
  3. void main(void)
  4. {
  5.   unsigned char Key_Value=0;
  6.   Timer0_Init();
  7.   while(1)
  8.   {
  9.     Key_Value=getKey_Value();
  10.     switch(Key_Value)
  11.     {
  12.       case 1:LED1=1;Speed_UP();break;
  13.       case 2:LED2=1;Speed_Down();break;
  14.     }
  15.   }
復(fù)制代碼

我把case:改成
  1. case 1:
  2. {
  3.       while(Key_Value==1)
  4.       {
  5.           Speed_UP();
  6.           LED1=1;
復(fù)制代碼

可是還是一直在執(zhí)行。應(yīng)該如何修改呢?
下面是中斷函數(shù):
  1. void Timer0_ISR(void) interrupt 1
  2. {
  3.     static unsigned int Timer0_Count=0;
  4.     TL0=0x18;
  5.     TH0=0xFC;                                
  6.     Timer0_Count++;
  7.     if(Timer0_Count>=20)
  8.     {
  9.         Timer0_Count=0;
  10.         Key_Scan_Loop();
  11.     }
  12. }
復(fù)制代碼

這里是Key.c里的
  1. unsigned char getKey_State(void)
  2. {
  3.     unsigned char Key_Num=0;
  4.    
  5.     if(Key_OpenHeadLights==0){Key_Num=1;}
  6.     if(Key_BrakeMotor==0){Key_Num=2;}
  7.     if(Key_SpeedUpMotor==0){Key_Num=3;}
  8.     if(Key_BackMotor==0){Key_Num=4;}
  9.    
  10.     return Key_Num;
  11. }
  12. void Key_Scan_Loop(void)
  13. {
  14.     static unsigned char Key_NowState=0;    //按鍵現(xiàn)在狀態(tài)
  15.     static unsigned char Key_LastState=0;        //按鍵上次狀態(tài)
  16.    
  17.     Key_LastState=Key_NowState;
  18.     Key_NowState=getKey_State();
  19.    
  20.     if(Key_LastState==0&&Key_NowState==1)
  21.     {
  22.         Key_Number=1;
  23.     }
  24.     if(Key_LastState==0&&Key_NowState==2)
  25.     {
  26.         Key_Number=2;
  27.     }
  28.     if(Key_LastState==0&&Key_NowState==3)
  29.     {
  30.         Key_Number=3;
  31.     }
  32.     if(Key_LastState==0&&Key_NowState==4)
  33.     {
  34.         Key_Number=4;
  35.     }
  36. }
  37. unsigned char getKey_Value(void)
  38. {
  39.     unsigned char Key_Temp=0;
  40.    
  41.     Key_Temp=Key_Number;
  42.     Key_Number=0;
  43.    
  44.     return Key_Temp;
  45. }
復(fù)制代碼



回復(fù)

使用道具 舉報(bào)

ID:584814 發(fā)表于 2021-11-16 14:46 | 顯示全部樓層
void Key_Scan_Loop(void)
{
    static unsigned char Key_NowState=0;    //按鍵現(xiàn)在狀態(tài)
    static unsigned char Key_LastState=0;        //按鍵上次狀態(tài)
......
每進(jìn)一次 Key_Scan_Loop 都將按鍵現(xiàn)在的狀態(tài)和上次的狀態(tài)清零 ?
回復(fù)

使用道具 舉報(bào)

ID:554500 發(fā)表于 2021-11-16 15:29 | 顯示全部樓層

sbit Key=P1^0;

void Key_scan()
{
    static u8 i=0;

    if(Key==0)
    {
        if(i==0)
       {
            if(Key==0)
            {
                 i=1;
                //執(zhí)行按下函數(shù)
            }
        }
    }
  else
  {
      if(i==1)
     {
         //執(zhí)行釋放函數(shù)
     }
      i=0;
   }
}
回復(fù)

使用道具 舉報(bào)

ID:879924 發(fā)表于 2021-11-16 18:10 | 顯示全部樓層
man1234567 發(fā)表于 2021-11-16 14:46
void Key_Scan_Loop(void)
{
    static unsigned char Key_NowState=0;    //按鍵現(xiàn)在狀態(tài)

不是static了么?
回復(fù)

使用道具 舉報(bào)

ID:879924 發(fā)表于 2021-11-16 18:28 | 顯示全部樓層
18701931930 發(fā)表于 2021-11-16 15:29
sbit Key=P1^0;

void Key_scan()

試過不行,按下按鍵無反應(yīng)- -
回復(fù)

使用道具 舉報(bào)

ID:95407 發(fā)表于 2021-11-16 20:15 | 顯示全部樓層
while(Key_value==1)這里改成
回復(fù)

使用道具 舉報(bào)

ID:95407 發(fā)表于 2021-11-16 20:17 | 顯示全部樓層
while(Key_Value==1)改成 while(getKey_Value()==1)試下
回復(fù)

使用道具 舉報(bào)

ID:213173 發(fā)表于 2021-11-16 20:41 | 顯示全部樓層
這個(gè)示例程序適合樓主要求,要按實(shí)際電路重新定義端口。
  1. #include<reg51.h>        

  2. sbit key1=P3^2;
  3. sbit key2=P3^3;
  4. sbit OUT1=P1^0;
  5. sbit OUT2=P1^1;

  6. unsigned char state=0;//按鍵操作狀態(tài)

  7. void key_scan()//按鍵掃描函數(shù)
  8. {
  9.         static bit sign1=0,sign2=0;
  10.         static unsigned int count1=0,count2=0;
  11.        
  12.         if(!key1)
  13.         {
  14.                 if(++count1>=500 && sign1==0)//count1/count2消抖依主循環(huán)周期取值,估測(cè)10~20ms即可
  15.                 {
  16.                         sign1=1;
  17.                         state=1;
  18.                 }
  19.         }
  20.         else
  21.         {
  22.                 if(sign1==1)
  23.                 {
  24.                         sign1=0;
  25.                         state=2;
  26.                 }
  27.                 count1=0;
  28.         }

  29.         if(!key2)
  30.         {
  31.                 if(++count2>=500 && sign2==0)
  32.                 {
  33.                         sign2=1;
  34.                         state=3;
  35.                 }
  36.         }
  37.         else
  38.         {
  39.                 if(sign2)
  40.                 {
  41.                         sign2=0;
  42.                         state=4;
  43.                 }
  44.                 count2=0;
  45.         }
  46. }                       

  47. void key_service()//按鍵服務(wù)程序
  48. {
  49.         switch(state)
  50.         {
  51.                 case 1: OUT1=0; state=0; break;//任務(wù)完成state清0
  52.                 case 2: OUT1=1; state=0; break;
  53.                 case 3: OUT2=0; state=0; break;
  54.                 case 4: OUT2=1; state=0; break;
  55.         }
  56. }
  57. void main()
  58. {
  59.         while(1)
  60.         {
  61.                 key_scan();
  62.                 key_service();
  63.         }
  64. }
復(fù)制代碼

評(píng)分

參與人數(shù) 1黑幣 +30 收起 理由
macboa + 30 很給力!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:879924 發(fā)表于 2021-11-17 22:48 來自觸屏版 | 顯示全部樓層
zxian163 發(fā)表于 2021-11-16 20:15
while(Key_value==1)這里改成

試過 不行
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2021-11-17 23:25 | 顯示全部樓層
按照: 按下按鍵執(zhí)行某函數(shù)或語句,松開后停止執(zhí)行這個(gè)函數(shù)或語句
這個(gè)要求的話,不需要中斷,不需要其他任何,只需要:
sbit Key = P3.2;    //假定你的按鍵是這個(gè)

void main()
{
    其他代碼
while(1)
{
     其他代碼
if(Key)
{
       松開后停止執(zhí)行這個(gè)函數(shù)或語句
}
else
{
        按下按鍵執(zhí)行某函數(shù)或語句,
}
         其他代碼
}
}

按這個(gè)格式就可以了
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2021-11-17 23:27 | 顯示全部樓層
188610329 發(fā)表于 2021-11-17 23:25
按照: 按下按鍵執(zhí)行某函數(shù)或語句,松開后停止執(zhí)行這個(gè)函數(shù)或語句
這個(gè)要求的話,不需要中斷,不需要其他 ...

寫錯(cuò)了  不是: sbit Key = P3.2
是  sbit Key = P3^2;  不過,反正是假定,應(yīng)該沒有影響
回復(fù)

使用道具 舉報(bào)

ID:879924 發(fā)表于 2021-11-18 00:44 | 顯示全部樓層
188610329 發(fā)表于 2021-11-17 23:27
寫錯(cuò)了  不是: sbit Key = P3.2
是  sbit Key = P3^2;  不過,反正是假定,應(yīng)該沒有影響

謝謝哈,不過還是不行。要么就的按下去不亮,要么你就是一直亮
回復(fù)

使用道具 舉報(bào)

ID:879924 發(fā)表于 2021-11-18 00:48 | 顯示全部樓層
本帖最后由 macboa 于 2021-11-18 01:00 編輯
wulin 發(fā)表于 2021-11-16 20:41
這個(gè)示例程序適合樓主要求,要按實(shí)際電路重新定義端口。

老哥,你這個(gè)是相當(dāng)牛皮了。。。
感謝您!

但是還有一個(gè)不解之處。。。
就是我自己寫的
  1. main()
  2. {
  3.     if(Key_Value==1)
  4.     {
  5.         LED=0;
  6.     }
  7.     LED=1;
  8. }
復(fù)制代碼

按道理無論按下沒按下,LED=1這一步都會(huì)執(zhí)行啊。為啥這樣寫,按下之后再抬起,LED還是=0呢?也就是LED=1這一步根本沒有執(zhí)行,新手非常不解。。。還請(qǐng)大神明示。!

最后一個(gè)不解的地方就是,為何我把掃描函數(shù)放到定時(shí)器中斷里,按鍵就失效了呢?
回復(fù)

使用道具 舉報(bào)

ID:213173 發(fā)表于 2021-11-18 06:37 | 顯示全部樓層
macboa 發(fā)表于 2021-11-18 00:48
老哥,你這個(gè)是相當(dāng)牛皮了。。。
感謝您!
  1. main()
  2. {
  3.     if(Key_Value==1)
  4.     {
  5.         LED=0;
  6.     }
  7.     LED=1;//此語句結(jié)束后跑飛
  8. }


  9. void main()
  10. {
  11.         while(1)
  12.         {//永遠(yuǎn)約束在{}內(nèi)
  13.                 if(Key_Value==1)
  14.                 {
  15.                         LED=0;
  16.                 }
  17.                 else LED=1;
  18.         }
  19. }
復(fù)制代碼


掃描函數(shù)放到定時(shí)器中斷里一樣用,count1/count2消抖依中斷周期取值,10~20ms即可。
回復(fù)

使用道具 舉報(bào)

ID:123289 發(fā)表于 2021-11-18 14:47 | 顯示全部樓層
不要管按鍵,你能不能寫出一個(gè)加速的程序。
回復(fù)

使用道具 舉報(bào)

ID:879924 發(fā)表于 2021-11-19 11:01 | 顯示全部樓層
wulin 發(fā)表于 2021-11-18 06:37
掃描函數(shù)放到定時(shí)器中斷里一樣用,count1/count2消抖依中斷周期取值,10~20ms即可。

謝謝,已經(jīng)做到定時(shí)器里了。。?梢赃\(yùn)行。。。那個(gè)LED=1,不執(zhí)行的,還是不明白。。。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表