首頁 / 數字電子技術 / 單片機的設計原理(單片機的設計思路)

        單片機的設計原理(單片機的設計思路)

        Time:2024-02-22 20:22:10 Read:548 作者:CEO

        層次思維

        分層的想法並不神秘。事實上,許多從事項目的工程師自己都使用它。看了很多帖子,發現都沒有提到這個東西。不過,層次結構確實是一個非常有用的東西。了解之後,你會有一種恍然大悟的感覺。如果我不知道如何驅動LCD,那很簡單。我可以看看datasheet,參考別人的程序,很快就能做出來。但如果你不了解編程的思想,就會給你在項目過程中帶來很多困惑。我參考過市麵上各種嵌入式書籍,包括MCS-51、AVR、ARM等,但沒有找到任何介紹設計思想的書籍,即使有也是鳳毛麟角。寫程序並不難,但是如何又好又快地寫出程序需要一定的經驗。結構化模塊化編程的思想是最基本的要求。但如何將這個抽象的概念應用到工程實踐中呢?這就需要在做項目的過程中曆盡艱辛,總結一些東西,把抽象升華為理論,這對於經驗的積累和技術的傳播都有很大的好處。所以我要炫耀一下我的屈辱並總結一些事情。從我個人的經驗來看,有兩個設計思路非常重要。一是“時間片輪的設計思想”,對於實際中解決多任務問題非常有用。這個東西通常可以用來判斷一個人是單片機學習者還是單片機工程師。這個一定要掌握。 (下麵介紹)。

        單片機的設計原理(單片機的設計思路)

        二是“分層屏蔽的設計思想”,即分層思想。下麵以鍵盤掃描程序示例為介紹,介紹一下我今天要講的內容。

        問題陳述

        為了簡單起見,MCU學習板一般都會將按鍵分配得很好。比如整個4*4鍵盤矩陣分配給P1口,有8根控製線,剛剛好。這樣的話,程序也很容易寫了。隻需要簡單的:

        KEY_DAT=P1;

        端口數據被讀入。誠然,現實中並沒有這樣的好事。在實際的項目應用中,單片機引腳的複用是相當強大的,這和那些所謂的單片機學習板有很大不同。

        另一個原因是,在一般設計中,它是一個“軟件匹配硬件”的設計過程。簡單來說就是先確定硬件原理圖和硬件接線,最後開發軟件,因為修改硬件比較麻煩。據說修改軟件比較容易。這就是中國傳統的陰陽平衡哲學原理。硬件設計和軟件設計本質上是魚與熊掌的關係,不能兩者兼得。它方便了硬件設計,但可能給軟件編寫帶來很多麻煩。另一方麵,如果軟件設計方便的話,硬件設計就會相當麻煩。如果硬件設計和軟件設計都方便的話,就隻有兩種可能。一是設計非常簡單,二是設計者達到了非常高的水平。我們不考慮那麼多情況,簡單地從常見的實際應用的角度來看待問題。

        為了接線方便,硬件常常將IO口分配給不同的端口。例如,在上麵提到的4*4鍵盤中,8行分別分配給P0 P1 P2 P3。那麼,開發板上的那些鍵盤掃描程序就見鬼去吧。如何滑動按鈕?想起剛開始學習時的經曆,分成3個很相似的程序,逐個掃描……

        也許有人不願意說:“這些東西我花了很長時間才學,用得很好,怎麼能說不需要呢?”雖然有點殘酷,但我還是想說:“兄弟,接受現實吧,現實就是殘酷……”

        然而,人類與低等動物的不同之處在於,人類在遇到困難時能夠創造並找到解決方案,於是我們開始冥想……

        最後我們引入初中數學中的“映射”概念來解決這個問題。基本思想是將不同端口上的密鑰映射到同一端口。

        如何將按鍵掃描程序分為3層

        最底層是硬件層,完成端口掃描、20ms延時去抖,並將端口數據映射到一個KEY_DAT寄存器。 KEY_DAT 作為上層驅動層的接口。

        中間層是驅動層,隻對KEY_DAT寄存器的值進行操作。簡單來說,無論底層硬件如何連線,我們在驅動層都不需要關心。我們隻需要關心KEY_DAT寄存器的值。這樣做的間接效果就是“屏蔽了底層硬件的差異”,因此驅動層編寫的程序可以通用。

        驅動層的另一個作用是為上層提供消息接口。我們使用類似於窗口程序消息的概念。這裏可以提供一些按鍵消息,例如:按下消息、釋放消息、長按消息、長按按鍵時的步驟消息等。

        應用層屬於頂層程序。這裏根據不同的項目分別編寫關鍵功能程序。它使用驅動層提供的消息接口。在應用層編寫程序的想法是,我不關心下層如何工作,我隻關心按鍵消息。當關鍵消息到來時,我執行該函數。當沒有消息傳來時,我什麼都不做。

        下麵用一個簡單且常用的例子來說明我們的設計思想的使用。

        調整秒表時間時,需要按住某個按鈕,使時間不斷向上增加。這個東西很實用,在實際家電中有很多用途。

        在看下麵的事情之前,你可以想一想,這件事難嗎?相信大家都會響亮地回答:“不難!”,但我再問:“這東西麻煩嗎?”相信很多人肯定會說“好麻煩!”這讓我想起了我開始學習單片機的時候。編寫這種按鈕的程序結構比較混亂。不信的話,大家可以用51自己寫一下,這樣可以更好的理解本文提到的層次結構的優點。項目需求:給P10和P20分配兩個按鈕,分別是“加”和“減”按鈕。要求實現按鍵長按時連續加、連續減的功能。實戰:假設按鈕被拉起。當沒有按鈕時,電平為高,當有按鈕時,電平為低。另外,為了突出問題,這裏就不寫延時debounce程序了。實際項目中需要添加。 C語言中傳遞函數參數的方法有很多種。這裏以最簡單的全局變量為例來傳遞參數。當然,你也可以使用unsigned charReadPort(void) 返回一個讀取按鍵結果,甚至void ReadPort(unsigned char* pt) 使用指針變量傳遞地址來直接修改變量。方法有很多種,具體取決於每個人的編程風格。 1)開始編寫硬件層程序並完成映射

        C語言應該很容易理解吧?如果按下KEY_PLUS,P10口讀到低電平,則P1 KEY_PLUS的結果為0(xxxx xxx0 0000 0001),滿足if的條件。輸入KeyDat |=0x01 表示將KeyDat 的bit0 設置為1,即設置KEY_PLUS 映射到KeyDat 的bit0。 KEY_MIN 以同樣的方式映射到KeyDat 的bit1。如果KeyDat的bit0為1,則表示KEY_PLUS被按下,反之亦然。

        沒必要想得玄乎,映射就是這樣。如果還有其他鍵,使用同樣的方法將它們全部映射到KeyDat。

        2)驅動層編程如果把KeyDat想象成P1口,那麼這不是和學習板的標準掃描程序一樣嗎?是的,這就是底層映射的目的。

        3)應用層編程根據消息,硬件層必須分離。但對於驅動層和應用層的要求就沒有那麼嚴格了。事實上,對於一些簡單的項目來說,沒有必要將這兩層分開。可根據實際應用靈活運用。處理一下吧。其實這樣寫程序對於移植來說是非常方便的。隻需根據不同的板卡適當修改硬件層的ReadPort函數即可。驅動層和應用層的很多代碼無需修改就可以直接使用,可以大大提高開發效率。當然,這種按鈕程序會存在一定的問題,尤其是常閉按鈕和觸摸按鈕混合使用時。這留給大家思考。不管怎樣,問題總有解決的辦法,盡管方法可能好也可能壞。時間輪的設計思想首先用一個小例子來介紹今天的主題。想象一下,一個基本的家用電器控製麵板肯定會或多或少地包含:LED或數碼管顯示器、按鈕、繼電器或晶閘管輸出。 3 部分。數碼管需要10ms到20ms的動態掃描,按鍵也需要20ms左右的延時來消除抖動。您是否意識到這些時間實際上是同時發生的。回想一下我們的教科書是如何教授按鈕延遲和抖動消除的?沒錯,死循環絕對是原地踏步的死循環,用指令來計時。這自然會產生一個疑問。如果微控製器陷入無限循環,我們應該如何處理其他任務?數碼管動態掃描怎麼辦?繼續的唯一方法是等待按鈕被掃描。這樣一來,數碼管肯定會閃爍。掃描時間太長。縮短按鈕去抖時間並不是解決方案。想象一下,如果我們有許多其他任務需要同時完成。呢絨?解決方案之一就是今天的主題,分時掃描的思想。當然這不是唯一的方式,但是我一直在使用,認為這是一個非常好的想法,可以解決很多實際問題。我大膽地說,分時掃描的思想也是單片機編程的核心思想。信不信由你自己判斷。核心思想的實現過程:首先,利用RTC中斷來計時。 RTC 中斷時間較短。我習慣了125us。這個時候就需要了解紅外遙控代碼了。 RTC 計時相當準確,因此請嚐試利用它。

        其次,在RTC中斷服務程序中放入3個(自定義數量)定時器(說白了就是計數器)。我的習慣是2ms、5ms、500ms。這3個作為整個係統調用的基準時間。所以它必須是準確的。用示波器調整一下就可以了。這並不難。

        第三,在主程序的循環中放置一個專門用於處理時間的子程序。 (注:單片機不會停止,一直循環運行,這好像和我在學校學到的有點不一樣,麵試的時候就被問到了這個問題.)把所有的時間處理放在時間處理中子程序。這非常方便。一個單片機係統至少需要處理10到20個不同的時間和10到20個定時器,並且相當一部分需要同時異步工作。如果每一個都是分開的,就相當麻煩了。

        第四,“程序運行並等待,而不是站著等待”。這似乎有點神秘。和我一起加入公司的一位工程師在討論的時候提到了這個問題。我想這也是一個分時係統。這是一個比較重要的思想,所以也叫這個。下麵詳細說明。

        第五,下麵用程序說話,注釋盡量詳細。不需要看代碼,直接看注釋就可以了。

        首先中斷服務程序部分

        每125us 中斷一次,生成多個參考時間。

        (1)ref_2ms寄存器繼續減1,每次中斷減1,一共16次,所以這裏經過的時間是125us16=2ms,這就是所謂的定時器/計數器。這樣,我們就可以依靠係統的RTC中斷來實現我們需要的多次定時。

        (2) 設置2ms定時結束標誌。這被提供給時間處理程序。這是一個定時器框架。接下來的5ms時序完全一樣。

        這個程序也采用了block框架,比較方便,不過和今天的主題無關。等我鬱悶的時候再寫這個吧。上述程序是中斷服務程序中的定時器,分別定時為2ms、5ms、500ms。計時後的溢出由flag_TIme標誌記錄。程序通過讀取該標誌即可知道計時時間是否已到。我們看一下統一授時子程序

        上麵以20ms 按鈕去抖動定時器為例。如果你理解了,你可以發現我們完全可以模仿那個定時器,在下麵放很多很多定時器。然後每5ms 來一次,並且每個計時器將同時開啟。計數,誰先完成計算,誰就先把自己關掉,設置相應的標誌,供其他程序調用,對其他定時器完全沒有影響!這樣,我們就可以在這裏放置很多定時器了。一般來說,十個、二十個定時器是沒有問題的,完全可以滿足單片機係統多次的需要。

        單個定時器的結構非常簡單。它首先判斷允許計時標誌是否進入計時,然後由專用寄存器加或減1。加/減相應的值後,相應的時間到了。關閉定時器並設置相應的定時器。要使用的標誌。

        我們快到了。隻要有需要,我們就可以出來。這不是很方便嗎?我們來看看這段時間單片機都做了什麼?隻有當中斷定時足夠5ms或500ms時,溢出標誌才有效,才能進入上述定時程序。剩下的時間都花在做其他事情上。而且進入上麵的定時器的時候,可以看到並不是死循環,隻是對寄存器進行加減運算然後退出。整個過程隻需要很少的時間。這取決於代碼,大約5us到20us吧。對主程序的執行沒有影響。

        我們來看看如何調用它

        我們一開始談到了處理按鈕去抖時間的問題,現在我們就用上麵介紹的方法來看看如何解決這個問題。

        大概是這樣的:判斷什麼時候有key,如果沒有就跳出,如果有就開始延遲debounce時機。當第二次進來的時候,直接通過標誌位來控製,來判斷什麼時候時間夠了。

        同樣是等待,這裏是最後提到的一點。我們是跑來等待,而不是站著等待。與無限循環計時相比,在計時沒有達到20ms的這段時間裏,單片機在做什麼呢?如果是死循環的話,肯定會在原地等待,什麼也不做。但如果你看上麵的程序,它隻是判斷時間是否足夠。具體計時是在統一的時間子程序中完成的。如果判斷時間未到,就會跳出。繼續運行其他程序,直到時間到,單片機判斷flag_delay和key_flow滿足條件,開始進入按鍵處理程序。在此期間,單片機正在做其他事情,隻是一個主循環運行回來判斷一次,所以單片機完全有時間運行其他程序,而不是把所有的時間都花在消除抖動上。

        主程序循環體

        這是使用的循環體。所有的函數都被做成子程序。您可以在需要時將它們掛起來。比較方便。有了這樣一個通用的循環體,微控製器就不斷地執行這個循環體。如果整個程序都采用上麵提到的分時掃描的思想的話,一周循環回來的時間是相當短的。其實,是不是有點類似於計算機的思想呢?

        計算機的速度再快,它也無法同時處理多個任務,而是一次處理一個任務,然後以非常快的速度循環處理,讓我們感覺它在同時處理多個程序。我想,我最終想要表達的就是如此。在這個思想的支持下,單片機程序變得更加容易使用。剩下的就是集中精力用程序來實現我們的想法了。當然,這隻是一種可行的方法,並不是唯一的方法。

        編寫程序是一門藝術。寫好字很容易,寫好字卻很難。

        更多信息可以在這裏獲取==電子技術應用-AET

        Copyright © 2002-2024 應用電子技術網 版權所有 
        備案號:

        免責聲明: 1、本站部分內容係互聯網收集或編輯轉載,並不代表本網讚同其觀點和對其真實性負責。 2、本頁麵內容裏麵包含的圖片、視頻、音頻等文件均為外部引用,本站一律不提供存儲。 3、如涉及作品內容、版權和其它問題,請在30日內與本網聯係,我們將在第一時間刪除或斷開鏈接! 4、本站如遇以版權惡意詐騙,我們必奉陪到底,抵製惡意行為。 ※ 有關作品版權事宜請聯係客服郵箱:478923*qq.com(*換成@)