在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 牛人業(yè)話 > 開關檢測二三事:端口不足,濾波時間不同

            開關檢測二三事:端口不足,濾波時間不同

            作者:驢三 時間:2020-03-18 來源:電子產品世界 收藏

            熟悉灑家寫作風格的朋友們都知道,灑家行文一向生動活潑,甚而有時浮夸得沒個章法。但是,在這個全民戰(zhàn)疫的關鍵時刻,似乎任何的輕佻都是對前線戰(zhàn)士的不恭敬。故而,今天嚴肅緊張一把,跟大家開門見山,講一講開關檢測的問題。

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

            有的朋友可能會覺得,開關檢測對于每一個嵌入式工程師來講都是入門級別的問題,有什么好講的呢?好吧,對于你這種想法,我只能像春晚上曉明哥哥對祖兒妹妹講的那樣:

            我不要你覺得,我要我覺得!

            問你三個問題吧。第一,如果因為這樣或那樣的原因,您選用的MCU的IO口不夠,無法一一對應地處理那么多路開關信號,你該咋個辦?

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

            第三,是關于大家耳熟能詳的濾波問題,您可不要說只需要進行硬件濾波就夠了這種跌份的話哈。假設您的開關信號性質有所不同,它們需要的濾波時間也不一樣,你怎么以一種統(tǒng)一的方式去處理他們呢?

            今天灑家和大家分享的就是關于這三個問題的想法和解決方案。

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

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

            那么,IO口不夠呢?

            魯迅先生曾說:“希望是本無所謂有,無所謂無的。這正如地上的路,其實地上本沒有路,走的人多了,也便成了路?!?/p>

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

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

            在計算機剛剛出現(xiàn)的那個年代里,打印和繪圖是非常重要的應用。由于計算機速度的限制,串行傳輸速度相當有限,無法應對打印繪圖這種需要高速數據傳輸的應用,于是,并口大行其道數十載。說句不怕暴露年齡的話,筆者剛上班時,單位的臺式機和筆記本都是有并口的。

            當然,魚與熊掌不可兼得,并行傳輸也有其缺點,那就是需要的端口和線路遠高于串行傳輸,會消耗較高的電路板資源和軟件解析能力,所以,隨著計算機和串行傳輸速度的提升,并口也開始慢慢地退出了歷史的舞臺。

            觸類旁通,見微知著,大家是不是品出來什么了?

            對,在嵌入式設計中,一個MCU端口處理一路開關信號是“并行處理方式”,類比于計算機并口,需要消耗較多的端口。端口不夠的解決方案自然是“并行轉串行”,以串行的方式進行開關信號的檢測。

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

            話不多說,再來看第二個問題:怎么區(qū)分開關的“動作”和“狀態(tài)”?

            至于為什么要區(qū)分“動作”和“狀態(tài)”。是因為在嵌入式產品中,有一種很常見的應用邏輯:開關A、B、C處于閉合狀態(tài)且開關D、E、F處于斷開狀態(tài)時,按下或松開開關G,執(zhí)行某個操作。

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

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

            為了說明這一點,灑家跟大家分享一下自己設計的結構體和代碼實現(xià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;

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

            為了同時檢測開關狀態(tài)和動作,可以設置一個10ms的周期定時器,周期性地對每個SWITCH_ID對應的開關信號進行檢測,具體實現(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;

                    }

                }

            }

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

            所以,上面那種根據某些開關的狀態(tài)和動作執(zhí)行相關操作的邏輯的具體實現(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;

            }

            下面接著講第三個問題:怎么應對不同的濾波時間?

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

            那么,對于那些特殊的開關信號,也許需要采用較典型值長或者短的消抖時間,我們只需要針對該開關信號對應的那個SWITCH_ID表征的結構體變量,設置它的濾波次數filter_time(見上面那段程序)即可。

            講到這里,有些不愛看代碼的同學可能模糊了,這里,幫人幫到底,灑家不惜筆墨,詳細開展一番。

            首先,設定一個10ms的定時器,在它的中斷服務程序里,執(zhí)行開關信號檢測。

            對應在我們這里,可以認為它的中斷服務程序(ISR)執(zhí)行的就是下面這個IoInputDetect函數。(需要說明的是,一般情況下我們不會在中斷服務程序里執(zhí)行這種耗時較長的程序,這里只是為了方便大家理解)

            void IoInputDetect(void)

            {

                e_SwId sw_idx;

                ReadIoSwitch();

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

                    SwDetect(sw_idx);   

                } 

            }

            這個函數里面,在ReadIoSwitch函數里面讀取每個開關(以SWITCH_ID標識)的當前狀態(tài),賦給其cursw,需要注意的是,這里的cursw表示的是當下這一刻的開關狀態(tài),不是經過濾波處理后的穩(wěn)定開關狀態(tài)。

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

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

            當濾波時間不同時,顯然只需要將該switch_id對應的開關結構體的filter_time置為不同于典型值的特殊值即可。

            后記

            灑家在這篇文章里面分享的開關檢測方法,不止適用于數字IO形式的開關信號,還適用于其它信號。

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

            再舉一反三,無論是RF信號、模擬信號、數字信號、網絡信號,只要該輸入信號在邏輯上可以等價于物理開關,它就可以使用本文所述的方法處理。

            你覺得呢?



            關鍵詞:

            評論


            相關推薦

            技術專區(qū)

            關閉