您好,登錄后才能下訂單哦!
這篇文章主要介紹“c語言回調函數的作用是什么及怎么使用”,在日常操作中,相信很多人在c語言回調函數的作用是什么及怎么使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”c語言回調函數的作用是什么及怎么使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
掌握程序架構的核心理念或需求。掌握回調函數的作用掌握回調函數的程序編寫掌握回調函數在產品中的應用
很多人可能會說一個好的程序架構啊,就是代碼很緊湊、執行效率也很高。
其實這個說的很片面,不完全對,這只能說明你程序算法寫的好,但架構不一定做的好。
即然是架構,那自然是以從”大局”為重,思維不能局限于當下的產品功能,還要考慮到以后功能的增加和裁剪,那么對于單片機開發來說,我認為一個好的程序架構至少要達到以下要求:
硬件層和應用層的程序代碼分開,相互之間的控制和通訊使用接口,而且不會共享的全局變量或數組。
這里呢,我就這個要求,別小看這一個要求,因為這個要求里面蘊藏著很多學問的,比如用專業稱為可移植性、可擴展性。
那么我們來想象一下我們通常寫單片機代碼的方式啊,在51的時候基本一個.c文件解決,包括寄存器配置啊,產品功能啊。
這種就是沒有架構的程序,然后我們進化到STM32這個單片機以后,程序大了,慢慢也會在工程文件里加幾個文件夾目錄把硬件層和應用層代碼分開了。
于是我們會把一些不同的外設功能,比如Led、按鍵、串口等外設功能代碼分別寫在不同的.c文件里,然后統一用函數接口去調用它。
比方說控制一個LED燈亮,直接在led.c文件里寫一個驅動led燈狀態的函數然后給外部調用就好了。
那我們我們看這種Led的控制函數確實也是滿足程序架構的需求的,硬件層和應用層代碼分開,應用層用硬件層提供的接口來控制,而且又不會有硬件層和應用層共享的全部變量或數組。像這種是不是很簡單?
那么不知道你們有沒有碰到另外一種情況,就是應用程序需要采集硬件層的數據,比如串口接收數據,按鍵采集、ADC值采集。
這種硬件層的數據怎么通知應用層來拿,或者怎么主動給它?
我們以往最簡單粗暴的方式是不是就是用一個全局變量,比方說硬件層串口接收到數據來了,那么我們把數據丟到數組里,然后把接收完成全局變量標志位置1。
比方說全局變量名為RcvFlag,然后應用層程序會輪詢判斷RcvFlag==1?是的話就開始把數組里的數據取出來解析。
很多人就會說了,你看我用這種方法照樣能實現功能啊,為什么還要學習別的架構。
這樣做當然可以實現功能,但是會存在移植性很差的問題。
比如說你們老板讓你把這個串口的硬件層封裝起來給客戶用,但不能讓客戶看到你實現的源代碼,只提供接口(函數名)給對方用。
那么這時候難道你要告訴客戶先判斷哪個變量為1,然后再取哪個數組的數據這么LOW的做法嗎?
那么如果是懂行的客戶一定會懷疑你們公司的技術實力是不是小學生水平。
那怎樣做才會既方便又專業呢? 這里我們就需要用到回調函數啦。
那么在講回調函數之前呢,對于函數調用呢我一般分為2種類型:
不知道大家有沒有用過C語言自帶的一些庫函數,比如說sizeof()獲取數據長度的函數,memcpy()是內存拷貝函數,我們調用這個函數之后呢就能完成相應的功能。
還有我們基于單片機的一些程序函數,比方說控制LED點亮熄滅、繼電器吸合斷開、LCD驅動等等。
那么這些呢,我一般稱為輸出型的函數。
輸出型函數我們是主導的角色,我們知道什么時候該調用它。
輸入型呢,也稱為的是響應式的函數。
什么叫響應式的函數呢?
比方說接收串口的數據,我們不知道什么數據什么時候來。
再比方說,我們按鍵檢測的函數,我們不知道什么時候會按下按鍵,那么這些就要定義成響應式函數來實現,而響應式函數就可以用回調函數來實現。
所以通過這兩個種類型的分析啊,我們就可以知道,回調函數基本是用在輸入型的處理中。
比方說串口數據接收,那么數據是輸入到單片機里面的,單片機是處于從機角色。
按鍵檢測,按鍵狀態是輸入到單片機里的。
再比方說ADC值采集,ADC值也是輸入到單片機里的。
那么它們輸入的時間節點都是未知的,這些就能夠用回調函數來處理。
具體怎么處理后面我們會用代碼來給大家舉例。
回調函數還有一個作用就是為了封裝代碼。
比如說做芯片或者模組的廠家,我們拿典型的STM32來舉例,像外部中斷、定時器、串口等中斷函數都是屬于回調函數,這種函數的目的是把采集到的數據傳遞給用戶,或者說應用層。
所以回調函數的核心作用是:
1.把數據從一個.c文件傳遞到另一個.c文件,而不用全局變量共享數據這么LOW的方法。
2.對于這種數據傳遞方式,回調函數更利于代碼的封裝。
前面說了很多概念性的東西,可能大家也比較難理解,回調函數最終呢是靠函數指針來實現的。
那么我這里通過一些模擬按鍵的例子來演示下怎么回通過調函數來處理它們。
下面是我們的c-free工程,用這個來模擬方便點:
從模塊化編程的思想來看,整個工程分為2個部分,應用層main.c文件,硬件層key.c和key.h文件。
不管再怎么復雜的程序,我們都要先從main函數一步步往下挖,main函數代碼如下。
int main(int argc, char *argv[]) { KeyInit(); KeyScanCBSRegister(KeyScanHandle); KeyPoll(); return 0; }
KeyInit();是key.c文件的按鍵初始化函數
KeyScanCBSRegister(KeyScanHandle);是key.c的函數指針注冊函數。
這個函數可能大家會有點蒙,請跟進我們的節奏,下面開始燒腦環節,也是寫回調函數的必須步驟,
想理解這個回調函數注冊函數,我們要先從硬件層(key.h)頭文件的函數指針定義說起,具體看下圖。
這里自定義了一個函數指針類型,帶兩個形參。
然后,我們在key.c這個文件里定義了一個函數指針變量。
重點來了,我們就是通過這個函數指針,指向應用層的函數地址(函數名)。
具體怎么實現指向呢?就是通過函數指針注冊函數。
這個函數是在main函數里調用,使用這種注冊函數的方式注冊靈活性也很高,你想要在哪個.c文件使用按鍵功能就在哪里調用。
這里要注意,main.c這個文件要定義一個函數來接收硬件層(key.c)過來的數據。
這里定義也不是亂定義的,一定要和那個自定義函數指針類型返回值、形參一致。
然后把這個函數名字直接復制給KeyScanCBSRegister函數的形參就可以了。
這樣調用后,我們key.c文件的pKeyScanCBS這個指針其實就是指向的KeyScanHandle函數。
也就是說執行pKeyScanCBS的時候,就是執行KeyScanHandle函數。
那具體檢測按鍵的功能就是KeyPoll函數,這個在main函數里調用。
當檢測到鍵盤有輸入以后,最終會調用pKeyScanCBS。
最終執行的是main.c文件的KeyScanHandle函數。
所以,我們來看下輸出結果。
到此,關于“c語言回調函數的作用是什么及怎么使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。