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

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

QQ登錄

只需一步,快速開始

搜索
查看: 3515|回復(fù): 10
打印 上一主題 下一主題
收起左側(cè)

終于用自己的想法擺脫MCU按鍵計(jì)時(shí)總使用while死循環(huán)了(非阻塞?),61節(jié)日快樂

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:728915 發(fā)表于 2021-6-1 19:51 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
//*************************首先感嘆一下C語言的靈活性。
/************************************以下基于STM8單片機(jī)**************************/

/****為解決按鍵時(shí)采用死循環(huán),使CPU進(jìn)入假死機(jī)狀態(tài),大大浪費(fèi)單片機(jī)資源的情況*******/

/***以下文字為個(gè)人理解,大佬建議跳過,當(dāng)然,也歡迎各位指出偏駁之處***************/

/**單片機(jī)在一個(gè)時(shí)間點(diǎn)只能進(jìn)行一個(gè)動(dòng)作,并不能做到真正意義上的同時(shí)多任務(wù)動(dòng)作,只能在結(jié)束一個(gè)動(dòng)作后進(jìn)行下一個(gè)動(dòng)作,
由于每一個(gè)動(dòng)作所需要耗費(fèi)的時(shí)間特別短,所以在一定情況下可以看作多任務(wù)進(jìn)程。
以下利用中斷計(jì)時(shí)同理,在每一次計(jì)時(shí)的動(dòng)作耗費(fèi)時(shí)間特別短,做完這個(gè)動(dòng)作CPU就可以進(jìn)行其它動(dòng)作了,相當(dāng)于擺脫了死循環(huán),
不會(huì)讓CPU在那無意義地卡住,陷入要等待其它打破標(biāo)志的死循環(huán)**********************/

/***粗略非阻塞(不知道這算不算非阻塞)延時(shí)/計(jì)時(shí)思路:定時(shí)器進(jìn)行規(guī)定時(shí)間的中斷進(jìn)入,每進(jìn)一次中斷,(符合條件下)次數(shù)+1,以此作為粗略的基礎(chǔ)時(shí)間(1ms/5ms/10ms/100ms……)*****************************/

/*********************以下為代碼內(nèi)容***************************************/

#include <stm8s.h>
#include <stm8s_gpio.h>
#include <stm8s_tim4.h>
#include <stm8s_clk.h>


//按鍵K1-K2定義,只能讀取是否為“0”(按下)/不為“0”(松開),不能讀取是否為“1”或者其它的
#define K1 (GPIO_ReadInputData(GPIOC)&GPIO_PIN_1)   
#define K2 (GPIO_ReadInputData(GPIOC)&GPIO_PIN_2)   

//L1-L2燈亮/滅定義(繼電器K1-K2工作/不工作定義)
#define ON  1
#define OFF 0
#define L1(ON_OFF)  if(ON_OFF==ON)GPIO_WriteHigh(GPIOB, GPIO_PIN_3);\
                      else GPIO_WriteLow(GPIOB, GPIO_PIN_3)
#define L2(ON_OFF)  if(ON_OFF==ON)GPIO_WriteHigh(GPIOB, GPIO_PIN_2);\
                      else GPIO_WriteLow(GPIOB, GPIO_PIN_2)

//引腳初始化
void GPIO_Config()
  {

    //繼電器三極管控制引腳 PB2-3 初始化,高電平導(dǎo)通
   GPIO_Init(GPIOB, GPIO_PIN_2|GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST);

   //按鍵初始化:無中斷無浮點(diǎn)上拉輸入
   GPIO_Init(GPIOC, GPIO_PIN_1|GPIO_PIN_2, GPIO_MODE_IN_PU_NO_IT);

  }


//初始化定時(shí)器TIM4   
void Init_Timer4(void)
{
    TIM4_DeInit();  
    TIM4_TimeBaseInit(TIM4_PRESCALER_64, 0xFA);    /*初始化時(shí)基單元。128分頻 ,x=16M/128 ,                                                                                                                          自動(dòng)重載寄存器值為0xfa=16*15+10=250,
                                                                                 中斷溢出=x/0xfa 進(jìn)中斷一次2ms。
                                                                                 64分頻下0xFA進(jìn)中斷一次1ms ;                                                                                                                                                 128分頻下0x19進(jìn)中斷一次0.2ms***/
    TIM4_ClearFlag(TIM4_FLAG_UPDATE);   
    TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);    //使能TIM4更新中斷
    TIM4_Cmd(ENABLE);     //啟動(dòng)定時(shí)器
}


//定義全局變量:TIM4每1ms進(jìn)中斷一次 的各按鍵計(jì)次時(shí)間sk,各按鍵對(duì)應(yīng)上一次的計(jì)次時(shí)間skt
//因?yàn)槭侨肿兞浚梢栽谄渌胤秸{(diào)用數(shù)值后手動(dòng)進(jìn)行清零/賦值操作
u16 sk1=0;
u16 sk1t=0;
u16 sk2=0;
u16 sk2t=0;

//TIM4中斷服務(wù)函數(shù):按鍵按下開始計(jì)時(shí),按鍵松開停止計(jì)時(shí);
//上一次按鍵按下持續(xù)時(shí)間數(shù)值一直保持,直到下一次按鍵有效按下后松開(去抖動(dòng))。
//各按鍵獨(dú)立計(jì)時(shí),互不影響
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{

   //上一次K1按鍵按下時(shí)長:sk1t
    if(K1==0)   //按鍵按下
     {
       sk1++;   //TIM4每1ms進(jìn)中斷一次,此時(shí)sk1+1
       if(sk1==59999)    //防止達(dá)到計(jì)數(shù)上限,約59秒
       {
         sk1=0;
       }
     }  
    if(K1!=0)   //按鍵松開
     {
       if(sk1>=30)    //防抖動(dòng),也可以避免時(shí)間一直刷新
       {
         sk1t=sk1;    //因?yàn)槭侨肿兞浚梢栽谡{(diào)用數(shù)值結(jié)束后手動(dòng)進(jìn)行清零操作
       }
       sk1=0;     
     }

   //上一次K2按鍵按下時(shí)長:sk2t   
    if(K2==0)   //按鍵按下
     {
       sk2++;   //TIM4每1ms進(jìn)中斷一次,此時(shí)sk2+1
       if(sk2==59999)    //防止達(dá)到計(jì)數(shù)上限,約59秒
       {
         sk2=0;
       }
     }
    if(K2!=0)   //按鍵松開
     {
       if(sk2>=30)   //防抖動(dòng),也可以避免時(shí)間一直刷新
       {
         sk2t=sk2;      
       }
       sk2=0;     
     }

  TIM4_ClearITPendingBit(TIM4_IT_UPDATE);   //清除標(biāo)志位
}


//控制LED亮滅:上一次按鍵達(dá)到一定時(shí)間后亮,否則滅。各按鍵獨(dú)立工作,互不影響
void LED12(void)
{

// 按鍵K1控制燈L1
   if(sk1t>=500)    //按鍵K1持續(xù)按下約500ms
   {
     L1(ON);
   }
   else
   {
     L1(OFF);
   }

// 按鍵K2控制燈L2
   if(sk2t>=5000)    //按鍵K1持續(xù)按下約5000ms
   {
     L2(ON);
   }
   else
   {
     L2(OFF);
   }
}


//主函數(shù)
void main(void)
{
  /*下列語句除 while(1){}; 外,其余語句都只執(zhí)行一次,TIM4的定時(shí)器配置是只在函數(shù)Init_Timer4()里設(shè)置一次*/

  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);    //系統(tǒng)時(shí)鐘初始化為內(nèi)部時(shí)鐘16M
  Init_Timer4();     //初始化TIM4定時(shí)器配置
  GPIO_Config();    //初始化IO口
  enableInterrupts();    //使能中斷  
  while(1)
  {
   LED12();
  };   
}


//解決報(bào)錯(cuò)
#ifdef USE_FULL_ASSERT
void assert_failed(u8* file, u32 line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif


/***用我理解的方式,有些地方寫得不是很好,水平比較低,所以在網(wǎng)上看大佬寫的總是感覺云里霧里,復(fù)制下來編譯一哈發(fā)現(xiàn)總是會(huì)少些東西,
然后又不知道怎么補(bǔ),木得辦法咯,只能自己慢慢想,啊哈哈。最后祝各位61節(jié)日快樂,誰還不是個(gè)幼兒園沒畢業(yè)/剛畢業(yè)的孩子呢!***/




評(píng)分

參與人數(shù) 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂2 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:101106 發(fā)表于 2021-6-4 17:35 | 只看該作者
用中斷方式處理按鍵 長按、雙擊等特殊操作比較難識(shí)別...........
回復(fù)

使用道具 舉報(bào)

板凳
ID:728915 發(fā)表于 2021-6-5 19:21 | 只看該作者
killalljp 發(fā)表于 2021-6-4 17:35
用中斷方式處理按鍵 長按、雙擊等特殊操作比較難識(shí)別...........

嗯,那就需要我多轉(zhuǎn)轉(zhuǎn)腦子了,主要是中斷這種思想,比較費(fèi)腦子,啊哈哈
回復(fù)

使用道具 舉報(bào)

地板
ID:256945 發(fā)表于 2021-6-11 17:30 | 只看該作者
killalljp 發(fā)表于 2021-6-4 17:35
用中斷方式處理按鍵 長按、雙擊等特殊操作比較難識(shí)別...........

要精準(zhǔn)延時(shí),然后自己定義一個(gè)延時(shí)時(shí)間,在延時(shí)時(shí)間內(nèi)再次點(diǎn)擊則判斷為雙擊,超過則為兩次單擊
回復(fù)

使用道具 舉報(bào)

5#
ID:116773 發(fā)表于 2021-6-12 07:39 | 只看該作者
killalljp 發(fā)表于 2021-6-4 17:35
用中斷方式處理按鍵 長按、雙擊等特殊操作比較難識(shí)別...........

按鍵按下時(shí)讓定時(shí)器/計(jì)數(shù)器開始計(jì)數(shù),按鍵松開停止計(jì)數(shù),這樣就可以知道按鍵按下時(shí)間的長短了。
回復(fù)

使用道具 舉報(bào)

6#
ID:298123 發(fā)表于 2021-6-16 13:40 | 只看該作者
void task_KeyScan (void *params)
{
    static uint8_t s_KeyState = KEY_STATE_INIT;
    static uint16_t s_KeyTimeCount = 0;
    static uint16_t s_LastKey = KEY_VALUE_NULL;
    static uint16_t KeyNew = KEY_VALUE_NULL, KeyOld = KEY_VALUE_NULL;
    static uint8_t KeyReport = 0;
    static uint16_t key_continue = 0;
       
          do{
   
                KeyNew = myKeyScan();

    switch(s_KeyState)
    {
        case KEY_STATE_INIT:
                {
                    if(KEY_VALUE_NULL != (KeyNew))
                    {
                                                                                          s_KeyTimeCount = 0;
                                                                              key_continue = 0;
                                                                                          KeyReport = 0;
                        s_KeyState = KEY_STATE_WOBBLE;
                        KeyOld =         KeyNew;                                                                                       
                    }
                                                                                                   
                }
        break ;

        case KEY_STATE_WOBBLE:
                {
                                                                          if(KeyNew == KeyOld) {
                                                                                                if(++s_KeyTimeCount > 1) {
                                                                                                          s_KeyTimeCount = 0;
                            s_KeyState = KEY_STATE_PRESS;
                                                                                                }
                                                                                }
                    else         {
                                                                                    s_KeyState = KEY_STATE_INIT;
                                                                                }                                                                       
                }
        break ;

        case KEY_STATE_PRESS:
                {
                    if(KeyOld == KeyNew)
                    {                                                                                  
                        s_LastKey = KeyNew;
                                                                  s_LastKey &= ~KEY_FLAG_TRUE;
                                                                                          s_LastKey |= KEY_DOWN;
                        KeyReport = 1;
                        s_KeyState = KEY_STATE_LONG;
                    }
                    else
                    {
                        s_KeyState = KEY_STATE_INIT;
                    }
                }
        break ;

        case KEY_STATE_LONG :
                {
                    if( KeyOld == KeyNew )
                    {
                        if(++s_KeyTimeCount > KEY_LONG_PERIOD)
                        {   key_continue = s_KeyTimeCount;
                            s_KeyTimeCount = 0;
                                                                                                          s_LastKey &= ~KEY_FLAG_TRUE;
                            s_LastKey |= KEY_LONG;
                            KeyReport = 1;
                            s_KeyState = KEY_STATE_CONTINUE;
                        }
                    }
                    else
                    {
                        s_KeyState = KEY_STATE_RELEASE;
                    }
                }
        break ;

        case KEY_STATE_CONTINUE :
                {
                    if(KeyOld == KeyNew)
                    {
                        if(++s_KeyTimeCount > KEY_CONTINUE_PERIOD)
                        {
                                                                                                          key_continue = s_KeyTimeCount;
                            s_KeyTimeCount = 0 ;
                                                                                                          s_LastKey &= ~KEY_FLAG_TRUE;
                            s_LastKey |= KEY_CONTINUE;
                                                                                                          KeyReport = 1;                                                                                                                                
                        }
                    }
                    else
                    {
                        s_KeyState = KEY_STATE_RELEASE;
                    }
                }
        break ;

        case KEY_STATE_RELEASE :
                {
                                                                          s_LastKey &= ~KEY_UP;
                                                                          //s_LastKey &= ~KEY_FLAG_TRUE;
                    s_LastKey |= KEY_UP;
                                                                          KeyReport = 1;
                    s_KeyState = KEY_STATE_INIT;
                }
        break ;

        default :  s_KeyState = KEY_STATE_INIT;
                                        break ;
    }
                if(KeyReport) {
                            //OSMboxPost(Key_Box, (void *)s_LastKey);
          KeyReport = 0;
          Key_SetValue(s_LastKey, key_continue);
                }
               
          vTaskDelay(4);         /* 40 MS  */
               
        }while(1);
               
}
回復(fù)

使用道具 舉報(bào)

7#
ID:298123 發(fā)表于 2021-6-16 13:41 | 只看該作者
建議網(wǎng)上找找這個(gè)狀態(tài)機(jī)方式的按鍵程序,可以解決各種復(fù)雜功能。 用定時(shí)器40m掃描一次
回復(fù)

使用道具 舉報(bào)

8#
ID:519089 發(fā)表于 2021-7-14 20:16 | 只看該作者
狀態(tài)機(jī)就解決了,,,
回復(fù)

使用道具 舉報(bào)

9#
ID:142059 發(fā)表于 2021-7-18 12:07 | 只看該作者
回復(fù)

使用道具 舉報(bào)

10#
ID:954192 發(fā)表于 2021-7-18 16:06 | 只看該作者
學(xué)習(xí)了,謝謝
回復(fù)

使用道具 舉報(bào)

11#
ID:728915 發(fā)表于 2021-7-19 18:55 | 只看該作者
Angle145 發(fā)表于 2021-7-18 12:07
可以參考我寫的http://www.zg4o1577.cn/bbs/dpj-210244-1.html

謝謝!
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 午夜视频一区二区三区 | 久草视频在线播放 | 我爱操| 国产乱码精品1区2区3区 | jlzzxxxx18hd护士| 中文字幕亚洲一区 | 欧美成年人 | 国产精品日韩欧美一区二区三区 | 成人国产a | 色视频在线观看 | 啪一啪 | 久久久久久久国产精品 | 午夜精品久久久 | 亚洲福利视频一区二区 | 国产精品色综合 | 久久夜夜 | 一级毛片在线播放 | 免费在线成人 | 国产精品揄拍一区二区 | 超碰日本 | 久久久久国产精品一区二区 | 国产精品亚洲成在人线 | 四虎永久免费黄色影片 | 日韩精品在线观看一区二区 | 日本一区二区三区在线观看 | 午夜爱爱毛片xxxx视频免费看 | 黄久久久 | 国产一区二 | 久久久久国产成人精品亚洲午夜 | 国产剧情一区 | 在线免费观看黄a | 欧美日韩亚洲在线 | 天天干天天操天天射 | 日本黄色大片免费 | 一区二区精品在线 | 欧美久久不卡 | 精品久久久久久久久久久下田 | 毛片在线免费 | 天天操操操操操 | 99精品欧美一区二区三区综合在线 | 一级毛片免费视频观看 |