首頁>技術>

本文章我們再談談微控制器程式碼的模組化設計思想是如何設計的。之前的【微控制器裸機程式碼框架設計思路】文章為了儘量簡潔的表達,我幾乎所有程式碼都放在了main.c中,這個在實際專案中,或者說當任務比較多的時候,幾乎是不太現實的。

模組化設計的目的是讓程式碼高內聚,低耦合,是為了降低程式複雜度,使程式設計、除錯和維護等操作簡單化

第一點:單獨的功能模組各自獨立建立xxx.c和xxx.h檔案

這一點相信大家可能都知道,因為51微控制器的書都有講,如果您已經知道了,請跳過第一點。

下面以之前的文章微控制器裸機程式碼為例進行說明:如下圖所示

我把功能程式碼分成了4大塊:

定時器功能程式碼:timer0.c、timer0.hTask裸機框架功能程式碼:task.c、task.h中斷函式功能程式碼:interrupt.c、interrupt.h(任務很少,也可以不分出來,看具體情況)公共函式功能程式碼:public.c、public.h(存放一些公共的函式和全域性變數)

(1)定時器功能程式碼:timer0.c、timer0.h

可以看出:timer0.c包含了3個常用函式,和1個定時器結構體變數,定時器中斷是放在interrupt.c裡面

timer0.h包含一些常用的宏定義,和結構體變數型別定義,對於常用的2ms/5ms/10ms定義初始值,可以使用宏定義,修改起來就會很方便,如下所示,這是一個小技巧

為什麼使用TIMER_VALUE來代替T5ms時,是因為如果不使用這個宏,那麼定時器初始化的時候要給TL0/TH0賦值T5ms,在定時器中斷函式中還要賦值一次,我需要改動兩個地方,中斷賦值很容易被忽略掉,所以使用TIMER_VALUE宏定義程式碼,我就可以只需要改T5ms就可以一次性更改定時器中斷的時間。

(2)Task裸機框架功能程式碼:task.c、task.h

task.c包含裸機程式碼框架中功能所有程式碼,心跳函式,初始化任務,啟動任務,停止任務還有任務處理函式

task.h程式碼如下:包含任務的陣列定義等等

(3)中斷函式功能程式碼:interrupt.c、interrupt.h

這個範例程式碼比較簡單,只有1個定時器的中斷函式,如下所示

(4)公共函式功能程式碼:public.c、public.h

存放公共函式,比如禁止總中斷,使能總中斷,軟體延時函式等等

要特別提到的一點,這是一個小技巧:public.h包含所有外設的標頭檔案和常用的C語言庫標頭檔案,這樣做的好處是,只需要修改這一個地方,其餘.c檔案只需要包含一條include "public.h"就可以了。

第二點:結構化封裝外設

這個才是本文章我想提到的重點,對於一般初學者而言,可能寫的最多的就是Timer0_Init(); 然後和Timer0_ISR() 函式,然後main.c呼叫就完事了。這種寫法的確簡單,也好理解,但是如果你的外設特別多,如果還有ADC,感測器,等等,你需要定義全域性變數傳遞引數時,外設越多,那麼全域性變數就越多,後續修改起來,你就會發現太痛苦了,能把功能實現就不錯了。

我們現在把定時器0就當做一個外設,

[1]、在外設對應標頭檔案中,比如timer0.h中,宣告一個結構體變數型別,如下圖圖所示,裡面包含了3個函式指標,也可以在結構體中定義變數,比如浮點數,比如陣列等等。不過定時器用不著。這裡就只有函式指標了。

[2]、在外設對應的原始檔中,比如timer0.c中,定義一個Timer0_t型別的結構體變數,並同時賦值,注意順序不能錯,因為前面定義的是函式指標,所以我們只需要用對應的函式名稱賦值就好,這種做法,也可以稱呼為註冊回撥函式.這些回撥函式因為是透過結構體變數來呼叫,所以前面請加static修飾,表示只能在本檔案中使用,如果是其他檔案要使用,請直接透過結構體變數來呼叫,這就達到了封裝的目的。

很多人不明白回撥函式,這裡簡單提一下,將函式名稱作為引數傳遞給函式指標,透過函式指標來呼叫該函式的功能,賦值的過程,就是註冊回撥函式.如果不註冊,那麼函式指標為null,指向空地址,就會出問題,我們定義的這個函式就是回撥函式。

[3]、在外設對應標頭檔案中,請一定寫上 externTimer0_t timer0,表示外部檔案可以呼叫 timer0結構體。

[4]、如果需要呼叫定時器的這些函式,只需要透過timer0結構來呼叫,如下所示,timer0.Init(TIMER_VALUE),

另外,VS Code的智慧補全非常棒,你只需要輸入結構體變數timer0.裡面的函式或變數全部都出來了,如果這樣封裝,那麼編輯程式碼體驗也很棒。

根據結構體封裝的思想,我再多舉兩個例子,假如對DHT11溫溼度感測器進行封裝,封裝哪些會比較合理呢?如下所示

計算的溼度和溫度浮點數,必不可少。

單匯流排40bits源資料,根據實際需求,如果你是和上位機通訊,也必須傳送這個源資料,那麼就封裝在這裡,如果不需要,可以不封裝。

讀取溼度和溫度的函式必須要封裝.

呼叫的時候,就可以透過如下方式,透過串列埠打印出源資料和計算後的溫溼度資料

18
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • oracle冷備份遷移資料庫工作筆記