<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 牛人業(yè)話 > 開(kāi)關(guān)檢測(cè)二三事:端口不足,濾波時(shí)間不同

          開(kāi)關(guān)檢測(cè)二三事:端口不足,濾波時(shí)間不同

          作者:驢三 時(shí)間:2020-03-18 來(lái)源:電子產(chǎn)品世界 收藏

          熟悉灑家寫(xiě)作風(fēng)格的朋友們都知道,灑家行文一向生動(dòng)活潑,甚而有時(shí)浮夸得沒(méi)個(gè)章法。但是,在這個(gè)全民戰(zhàn)疫的關(guān)鍵時(shí)刻,似乎任何的輕佻都是對(duì)前線戰(zhàn)士的不恭敬。故而,今天嚴(yán)肅緊張一把,跟大家開(kāi)門(mén)見(jiàn)山,講一講開(kāi)關(guān)檢測(cè)的問(wèn)題。

          本文引用地址:http://www.ex-cimer.com/article/202003/411046.htm

          有的朋友可能會(huì)覺(jué)得,開(kāi)關(guān)檢測(cè)對(duì)于每一個(gè)嵌入式工程師來(lái)講都是入門(mén)級(jí)別的問(wèn)題,有什么好講的呢?好吧,對(duì)于你這種想法,我只能像春晚上曉明哥哥對(duì)祖兒妹妹講的那樣:

          我不要你覺(jué)得,我要我覺(jué)得!

          問(wèn)你三個(gè)問(wèn)題吧。第一,如果因?yàn)檫@樣或那樣的原因,您選用的MCU的IO口不夠,無(wú)法一一對(duì)應(yīng)地處理那么多路開(kāi)關(guān)信號(hào),你該咋個(gè)辦?

          第二,如何區(qū)分開(kāi)關(guān)的“動(dòng)作”和“狀態(tài)”?按下和彈起的動(dòng)作一閃即逝,狀態(tài)卻長(zhǎng)期保持,怎么區(qū)分并處理?

          第三,是關(guān)于大家耳熟能詳?shù)臑V波問(wèn)題,您可不要說(shuō)只需要進(jìn)行硬件濾波就夠了這種跌份的話哈。假設(shè)您的開(kāi)關(guān)信號(hào)性質(zhì)有所不同,它們需要的濾波時(shí)間也不一樣,你怎么以一種統(tǒng)一的方式去處理他們呢?

          今天灑家和大家分享的就是關(guān)于這三個(gè)問(wèn)題的想法和解決方案。

          要想逃避現(xiàn)實(shí),最好的方式就是深深介入現(xiàn)實(shí)之中。

          嵌入式工程師的日常工作不是在錦繡河山里做文章,而是在螺絲殼里做道場(chǎng)。在日復(fù)一日的工作中,工程師逐漸積累了豐富的實(shí)戰(zhàn)經(jīng)驗(yàn)。比如硬件不夠可以用軟件來(lái)湊,內(nèi)存不足可以犧牲實(shí)時(shí)性,以時(shí)間換空間。

          那么,IO口不夠呢?

          魯迅先生曾說(shuō):“希望是本無(wú)所謂有,無(wú)所謂無(wú)的。這正如地上的路,其實(shí)地上本沒(méi)有路,走的人多了,也便成了路?!?/p>

          勇敢的嵌入式工程師是遇山開(kāi)路、遇水搭橋的開(kāi)拓者,面對(duì)無(wú)路之境,自會(huì)以大無(wú)畏的霹靂手段趟出一條路來(lái)。IO口不夠,MCU又不能換(想一想老板那冷颼颼的目光),自然也會(huì)另辟蹊徑,柳暗花明,不至于山窮水復(fù),找不到出路的。

          聰明的小伙伴們應(yīng)該已經(jīng)躍躍欲試,準(zhǔn)備搶答了。不過(guò),授人以魚(yú)不如授人以漁,在直接給出答案之前,大家可以先想一個(gè)問(wèn)題:為什么現(xiàn)在大家用的計(jì)算機(jī),基本上沒(méi)有并口了呢?

          在計(jì)算機(jī)剛剛出現(xiàn)的那個(gè)年代里,打印和繪圖是非常重要的應(yīng)用。由于計(jì)算機(jī)速度的限制,串行傳輸速度相當(dāng)有限,無(wú)法應(yīng)對(duì)打印繪圖這種需要高速數(shù)據(jù)傳輸?shù)膽?yīng)用,于是,并口大行其道數(shù)十載。說(shuō)句不怕暴露年齡的話,筆者剛上班時(shí),單位的臺(tái)式機(jī)和筆記本都是有并口的。

          當(dāng)然,魚(yú)與熊掌不可兼得,并行傳輸也有其缺點(diǎn),那就是需要的端口和線路遠(yuǎn)高于串行傳輸,會(huì)消耗較高的電路板資源和軟件解析能力,所以,隨著計(jì)算機(jī)和串行傳輸速度的提升,并口也開(kāi)始慢慢地退出了歷史的舞臺(tái)。

          觸類(lèi)旁通,見(jiàn)微知著,大家是不是品出來(lái)什么了?

          對(duì),在嵌入式設(shè)計(jì)中,一個(gè)MCU端口處理一路開(kāi)關(guān)信號(hào)是“并行處理方式”,類(lèi)比于計(jì)算機(jī)并口,需要消耗較多的端口。端口不夠的解決方案自然是“并行轉(zhuǎn)串行”,以串行的方式進(jìn)行開(kāi)關(guān)信號(hào)的檢測(cè)。

          在具體的實(shí)現(xiàn)上,需要選擇“多路開(kāi)關(guān)檢測(cè)接口芯片”,這種芯片可以檢測(cè)多路開(kāi)關(guān)量輸入信號(hào),并將檢測(cè)到的開(kāi)關(guān)狀態(tài)通過(guò)SPI發(fā)送給MCU。這種方式可以極大地節(jié)省MCU的IO口資源,比如說(shuō)檢測(cè)16路開(kāi)關(guān),并行方式需要16個(gè)MCU IO端口,串行方式只需要一個(gè)SPI端口就可以了。

          話不多說(shuō),再來(lái)看第二個(gè)問(wèn)題:怎么區(qū)分開(kāi)關(guān)的“動(dòng)作”和“狀態(tài)”?

          至于為什么要區(qū)分“動(dòng)作”和“狀態(tài)”。是因?yàn)樵谇度胧疆a(chǎn)品中,有一種很常見(jiàn)的應(yīng)用邏輯:開(kāi)關(guān)A、B、C處于閉合狀態(tài)且開(kāi)關(guān)D、E、F處于斷開(kāi)狀態(tài)時(shí),按下或松開(kāi)開(kāi)關(guān)G,執(zhí)行某個(gè)操作。

          在這種邏輯里,“按下”和“松開(kāi)”是兩種動(dòng)作,“閉合”和“斷開(kāi)”是兩種狀態(tài)。用電路的知識(shí)來(lái)類(lèi)比的話,動(dòng)作是沿跳變,狀態(tài)是電平。

          “動(dòng)作”是一閃即逝的花火,狀態(tài)是千年不變的承諾。我們做區(qū)分為的是,讓動(dòng)作“閱后即焚”,不至于成為反復(fù)觸發(fā)操作的脈搏。

          為了說(shuō)明這一點(diǎn),灑家跟大家分享一下自己設(shè)計(jì)的結(jié)構(gòu)體和代碼實(shí)現(xiàn),這部分也可以用在對(duì)第三個(gè)問(wèn)題的解答上。

          typedef struct{

               unsigned switch_state:1;

               unsigned swon_event:1;

               unsigned swoff_event:1;

               unsigned cursw:1;

               unsigned detect_cnt:4;

               e_SwId   switch_id;

          }s_Switch;

          在這個(gè)結(jié)構(gòu)體的成員變量里面,switch_id標(biāo)識(shí)開(kāi)關(guān)節(jié)點(diǎn),大家可以用“解釋性”很強(qiáng)的枚舉來(lái)表示它。這里的switch_state表示的是開(kāi)關(guān)信號(hào)的狀態(tài),swon_event和swoff_event分別表示開(kāi)關(guān)從斷開(kāi)到閉合和從閉合到斷開(kāi)的變化,即上述的“動(dòng)作”。 cursw和detect_cnt用于開(kāi)關(guān)信號(hào)采集的軟件消抖功能。

          為了同時(shí)檢測(cè)開(kāi)關(guān)狀態(tài)和動(dòng)作,可以設(shè)置一個(gè)10ms的周期定時(shí)器,周期性地對(duì)每個(gè)SWITCH_ID對(duì)應(yīng)的開(kāi)關(guān)信號(hào)進(jìn)行檢測(cè),具體實(shí)現(xiàn)為:

          void SwDetect(e_SwId sw_id)  

          {

              uint8_t filter_time;

              filter_time = SW_DETECT_TIMES;

              if(SWITCH_OFF == Sw[sw_id].switch_state){

                  if(IOVALID == Sw[sw_id].cursw){

                      if(Sw[sw_id].detect_cnt < filter_time){

                          Sw[sw_id].detect_cnt++;   

                      }else{                                          

                          Sw[sw_id].switch_state = SWITCH_ON;       

                          Sw[sw_id].detect_cnt = 0;                      

                          Sw[sw_id].swon_event = 1;          

                      }

                  }else{

                      Sw[sw_id].detect_cnt = 0;

                  }

              }else{

                  if(IOINVALID == Sw[sw_id].cursw){

                      if(Sw[sw_id].detect_cnt < filter_time){

                          Sw[sw_id].detect_cnt++;

                      }else{                                                        

                          Sw[sw_id].switch_state = SWITCH_OFF;

                          Sw[sw_id].swoff_event = 1;

                          Sw[sw_id].detect_cnt = 0;

                      }

                  }else{

                      Sw[sw_id].detect_cnt = 0;

                  }

              }

          }

          當(dāng)開(kāi)關(guān)動(dòng)作發(fā)生時(shí),swon_event和swoff_event置一,在執(zhí)行完相關(guān)操作之后,將swon_event和swoff_event清零,就完成了讓動(dòng)作“閱后即焚”。

          所以,上面那種根據(jù)某些開(kāi)關(guān)的狀態(tài)和動(dòng)作執(zhí)行相關(guān)操作的邏輯的具體實(shí)現(xiàn)為:

          If(Switch[SWITCH_ID_1].swon_event == 1)

          {

          If(Switch[SWITCH_ID_2].switch_state == “ON”){

              操作1;

          }

          Switch[SWITCH_ID_1].swon_event = 0;

          }

          下面接著講第三個(gè)問(wèn)題:怎么應(yīng)對(duì)不同的濾波時(shí)間?

          正如上面講過(guò)的那樣,對(duì)于一般的開(kāi)關(guān)節(jié)點(diǎn),設(shè)計(jì)一10ms的定時(shí)器周期性地讀取開(kāi)關(guān)當(dāng)前狀態(tài)cursw,然后根據(jù)其維持當(dāng)前狀態(tài)的周期次數(shù)(根據(jù)不同應(yīng)用場(chǎng)景,可以設(shè)置為5次或者10次,分別對(duì)應(yīng)50ms或100ms的濾波時(shí)間)以判斷switch_state、swon_event、swoff_event。

          那么,對(duì)于那些特殊的開(kāi)關(guān)信號(hào),也許需要采用較典型值長(zhǎng)或者短的消抖時(shí)間,我們只需要針對(duì)該開(kāi)關(guān)信號(hào)對(duì)應(yīng)的那個(gè)SWITCH_ID表征的結(jié)構(gòu)體變量,設(shè)置它的濾波次數(shù)filter_time(見(jiàn)上面那段程序)即可。

          講到這里,有些不愛(ài)看代碼的同學(xué)可能模糊了,這里,幫人幫到底,灑家不惜筆墨,詳細(xì)開(kāi)展一番。

          首先,設(shè)定一個(gè)10ms的定時(shí)器,在它的中斷服務(wù)程序里,執(zhí)行開(kāi)關(guān)信號(hào)檢測(cè)。

          對(duì)應(yīng)在我們這里,可以認(rèn)為它的中斷服務(wù)程序(ISR)執(zhí)行的就是下面這個(gè)IoInputDetect函數(shù)。(需要說(shuō)明的是,一般情況下我們不會(huì)在中斷服務(wù)程序里執(zhí)行這種耗時(shí)較長(zhǎng)的程序,這里只是為了方便大家理解)

          void IoInputDetect(void)

          {

              e_SwId sw_idx;

              ReadIoSwitch();

              for(sw_idx = MIN_SWITCH;sw_idx < MAX_SWITCH;sw_idx++){

                  SwDetect(sw_idx);   

              } 

          }

          這個(gè)函數(shù)里面,在ReadIoSwitch函數(shù)里面讀取每個(gè)開(kāi)關(guān)(以SWITCH_ID標(biāo)識(shí))的當(dāng)前狀態(tài),賦給其cursw,需要注意的是,這里的cursw表示的是當(dāng)下這一刻的開(kāi)關(guān)狀態(tài),不是經(jīng)過(guò)濾波處理后的穩(wěn)定開(kāi)關(guān)狀態(tài)。

          第二步:根據(jù)每個(gè)開(kāi)關(guān)的當(dāng)前狀態(tài)cursw,判斷其穩(wěn)定的開(kāi)關(guān)狀態(tài)switch_state、開(kāi)關(guān)動(dòng)作swon_event和swoff_event。即上面在for循環(huán)中執(zhí)行的SwDetect函數(shù)。

          SwDetect函數(shù)語(yǔ)句在第二節(jié)中,它的核心思想就是判斷開(kāi)關(guān)當(dāng)前狀態(tài)cursw是否持續(xù)穩(wěn)定在SWITCH_ON或者SWITCH_OFF狀態(tài)。當(dāng)前的switch_state為ON的狀態(tài)下,如果持續(xù)filter_time個(gè)10ms,cursw一直為OFF狀態(tài),則將switch_state賦為OFF狀態(tài),同時(shí),將swoff_event賦為1。反之亦然。

          當(dāng)濾波時(shí)間不同時(shí),顯然只需要將該switch_id對(duì)應(yīng)的開(kāi)關(guān)結(jié)構(gòu)體的filter_time置為不同于典型值的特殊值即可。

          后記

          灑家在這篇文章里面分享的開(kāi)關(guān)檢測(cè)方法,不止適用于數(shù)字IO形式的開(kāi)關(guān)信號(hào),還適用于其它信號(hào)。

          比如通過(guò)RF方式接收的遙控信號(hào),雖然是一種射頻性質(zhì)的信號(hào),但是這種信號(hào)對(duì)應(yīng)的是遙控器上的物理按鍵,它在邏輯上自然也等價(jià)于本文講的開(kāi)關(guān)信號(hào),所以,可以用上述那個(gè)結(jié)構(gòu)體和那些代碼判斷遙控信號(hào),解析出某個(gè)遙控按鍵按下、松開(kāi)的動(dòng)作和狀態(tài),同時(shí)對(duì)它進(jìn)行濾波處理。

          再舉一反三,無(wú)論是RF信號(hào)、模擬信號(hào)、數(shù)字信號(hào)、網(wǎng)絡(luò)信號(hào),只要該輸入信號(hào)在邏輯上可以等價(jià)于物理開(kāi)關(guān),它就可以使用本文所述的方法處理。

          你覺(jué)得呢?



          關(guān)鍵詞:

          評(píng)論


          相關(guān)推薦

          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();