最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c語言中回調(diào)函數(shù)的使用以及實(shí)際作用詳析

 更新時間:2021年07月18日 08:46:40   作者:無際單片機(jī)編程  
回調(diào)函數(shù)就是一個通過函數(shù)指針調(diào)用的函數(shù),如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當(dāng)這個指針被用來調(diào)用其所指向的函數(shù)時,我們就說這是回調(diào)函數(shù),這篇文章主要給大家介紹了關(guān)于c語言中回調(diào)函數(shù)的使用以及實(shí)際作用的相關(guān)資料,需要的朋友可以參考下

前言

今天給大家講一下芯片/模塊廠家寫SDK必須會使用的一種技術(shù):回調(diào)函數(shù)。

回調(diào)函數(shù)這個知識點(diǎn)其實(shí)并不是很難,難是難在網(wǎng)上很多講解回調(diào)函數(shù)的都說的太學(xué)術(shù)化了化了,一點(diǎn)也不親民。

很多人即使知道怎么寫回調(diào)函數(shù)也根本就搞不懂它們在實(shí)際產(chǎn)品中也有什么用,什么時候用。

所以這節(jié)課呢我們會以程序架構(gòu)的需求為出發(fā)點(diǎn),講解回調(diào)函數(shù)是怎么滿足它這個需求的。

為了方便大家理解,這篇內(nèi)容也對應(yīng)有一篇文章,大家可以找無際單片機(jī)編程獲取。

一、通過這節(jié)課程你能掌握以下知識:

掌握程序架構(gòu)的核心理念或需求。掌握回調(diào)函數(shù)的作用掌握回調(diào)函數(shù)的程序編寫掌握回調(diào)函數(shù)在產(chǎn)品中的應(yīng)用

二、程序架構(gòu)的核心理念和需求

很多人可能會說一個好的程序架構(gòu)啊,就是代碼很緊湊、執(zhí)行效率也很高。

其實(shí)這個說的很片面,不完全對,這只能說明你程序算法寫的好,但架構(gòu)不一定做的好。

即然是架構(gòu),那自然是以從”大局”為重,思維不能局限于當(dāng)下的產(chǎn)品功能,還要考慮到以后功能的增加和裁剪,那么對于單片機(jī)開發(fā)來說,我認(rèn)為一個好的程序架構(gòu)至少要達(dá)到以下要求:

硬件層和應(yīng)用層的程序代碼分開,相互之間的控制和通訊使用接口,而且不會共享的全局變量或數(shù)組。

這里呢,我就這個要求,別小看這一個要求,因為這個要求里面蘊(yùn)藏著很多學(xué)問的,比如用專業(yè)稱為可移植性、可擴(kuò)展性。

那么我們來想象一下我們通常寫單片機(jī)代碼的方式啊,在51的時候基本一個.c文件解決,包括寄存器配置啊,產(chǎn)品功能啊。

這種就是沒有架構(gòu)的程序,然后我們進(jìn)化到STM32這個單片機(jī)以后,程序大了,慢慢也會在工程文件里加幾個文件夾目錄把硬件層和應(yīng)用層代碼分開了。

于是我們會把一些不同的外設(shè)功能,比如Led、按鍵、串口等外設(shè)功能代碼分別寫在不同的.c文件里,然后統(tǒng)一用函數(shù)接口去調(diào)用它。

比方說控制一個LED燈亮,直接在led.c文件里寫一個驅(qū)動led燈狀態(tài)的函數(shù)然后給外部調(diào)用就好了。

那我們我們看這種Led的控制函數(shù)確實(shí)也是滿足程序架構(gòu)的需求的,硬件層和應(yīng)用層代碼分開,應(yīng)用層用硬件層提供的接口來控制,而且又不會有硬件層和應(yīng)用層共享的全部變量或數(shù)組。像這種是不是很簡單?

那么不知道你們有沒有碰到另外一種情況,就是應(yīng)用程序需要采集硬件層的數(shù)據(jù),比如串口接收數(shù)據(jù),按鍵采集、ADC值采集。

這種硬件層的數(shù)據(jù)怎么通知應(yīng)用層來拿,或者怎么主動給它?

我們以往最簡單粗暴的方式是不是就是用一個全局變量,比方說硬件層串口接收到數(shù)據(jù)來了,那么我們把數(shù)據(jù)丟到數(shù)組里,然后把接收完成全局變量標(biāo)志位置1。

比方說全局變量名為RcvFlag,然后應(yīng)用層程序會輪詢判斷RcvFlag==1?是的話就開始把數(shù)組里的數(shù)據(jù)取出來解析。

很多人就會說了,你看我用這種方法照樣能實(shí)現(xiàn)功能啊,為什么還要學(xué)習(xí)別的架構(gòu)。

這樣做當(dāng)然可以實(shí)現(xiàn)功能,但是會存在移植性很差的問題。

比如說你們老板讓你把這個串口的硬件層封裝起來給客戶用,但不能讓客戶看到你實(shí)現(xiàn)的源代碼,只提供接口(函數(shù)名)給對方用。

那么這時候難道你要告訴客戶先判斷哪個變量為1,然后再取哪個數(shù)組的數(shù)據(jù)這么LOW的做法嗎?

那么如果是懂行的客戶一定會懷疑你們公司的技術(shù)實(shí)力是不是小學(xué)生水平。

那怎樣做才會既方便又專業(yè)呢? 這里我們就需要用到回調(diào)函數(shù)啦。

三、回調(diào)函數(shù)的作用

那么在講回調(diào)函數(shù)之前呢,對于函數(shù)調(diào)用呢我一般分為2種類型:

1.輸出型

不知道大家有沒有用過C語言自帶的一些庫函數(shù),比如說sizeof()獲取數(shù)據(jù)長度的函數(shù),memcpy()是內(nèi)存拷貝函數(shù),我們調(diào)用這個函數(shù)之后呢就能完成相應(yīng)的功能。

還有我們基于單片機(jī)的一些程序函數(shù),比方說控制LED點(diǎn)亮熄滅、繼電器吸合斷開、LCD驅(qū)動等等。

那么這些呢,我一般稱為輸出型的函數(shù)。

輸出型函數(shù)我們是主導(dǎo)的角色,我們知道什么時候該調(diào)用它。

2.輸入型

輸入型呢,也稱為的是響應(yīng)式的函數(shù)

什么叫響應(yīng)式的函數(shù)呢?

比方說接收串口的數(shù)據(jù),我們不知道什么數(shù)據(jù)什么時候來。

再比方說,我們按鍵檢測的函數(shù),我們不知道什么時候會按下按鍵,那么這些就要定義成響應(yīng)式函數(shù)來實(shí)現(xiàn),而響應(yīng)式函數(shù)就可以用回調(diào)函數(shù)來實(shí)現(xiàn)。

所以通過這兩個種類型的分析啊,我們就可以知道,回調(diào)函數(shù)基本是用在輸入型的處理中。

比方說串口數(shù)據(jù)接收,那么數(shù)據(jù)是輸入到單片機(jī)里面的,單片機(jī)是處于從機(jī)角色。

按鍵檢測,按鍵狀態(tài)是輸入到單片機(jī)里的。

再比方說ADC值采集,ADC值也是輸入到單片機(jī)里的。

那么它們輸入的時間節(jié)點(diǎn)都是未知的,這些就能夠用回調(diào)函數(shù)來處理。

具體怎么處理后面我們會用代碼來給大家舉例。

回調(diào)函數(shù)還有一個作用就是為了封裝代碼

比如說做芯片或者模組的廠家,我們拿典型的STM32來舉例,像外部中斷、定時器、串口等中斷函數(shù)都是屬于回調(diào)函數(shù),這種函數(shù)的目的是把采集到的數(shù)據(jù)傳遞給用戶,或者說應(yīng)用層。

所以回調(diào)函數(shù)的核心作用是:

1.把數(shù)據(jù)從一個.c文件傳遞到另一個.c文件,而不用全局變量共享數(shù)據(jù)這么LOW的方法。

2.對于這種數(shù)據(jù)傳遞方式,回調(diào)函數(shù)更利于代碼的封裝。

四、掌握回調(diào)函數(shù)的程序編寫

前面說了很多概念性的東西,可能大家也比較難理解,回調(diào)函數(shù)最終呢是靠函數(shù)指針來實(shí)現(xiàn)的。

那么我這里通過一些模擬按鍵的例子來演示下怎么回通過調(diào)函數(shù)來處理它們。

下面是我們的c-free工程,用這個來模擬方便點(diǎn):

從模塊化編程的思想來看,整個工程分為2個部分,應(yīng)用層main.c文件,硬件層key.c和key.h文件。

不管再怎么復(fù)雜的程序,我們都要先從main函數(shù)一步步往下挖,main函數(shù)代碼如下。

int main(int argc, char *argv[])
{
KeyInit();
KeyScanCBSRegister(KeyScanHandle);
KeyPoll();
 
return 0;
}

KeyInit();是key.c文件的按鍵初始化函數(shù)

KeyScanCBSRegister(KeyScanHandle);是key.c的函數(shù)指針注冊函數(shù)。

這個函數(shù)可能大家會有點(diǎn)蒙,請跟進(jìn)我們的節(jié)奏,下面開始燒腦環(huán)節(jié),也是寫回調(diào)函數(shù)的必須步驟,

想理解這個回調(diào)函數(shù)注冊函數(shù),我們要先從硬件層(key.h)頭文件的函數(shù)指針定義說起,具體看下圖。

這里自定義了一個函數(shù)指針類型,帶兩個形參。

然后,我們在key.c這個文件里定義了一個函數(shù)指針變量。

重點(diǎn)來了,我們就是通過這個函數(shù)指針,指向應(yīng)用層的函數(shù)地址(函數(shù)名)。

具體怎么實(shí)現(xiàn)指向呢?就是通過函數(shù)指針注冊函數(shù)。

這個函數(shù)是在main函數(shù)里調(diào)用,使用這種注冊函數(shù)的方式注冊靈活性也很高,你想要在哪個.c文件使用按鍵功能就在哪里調(diào)用。

這里要注意,main.c這個文件要定義一個函數(shù)來接收硬件層(key.c)過來的數(shù)據(jù)。

這里定義也不是亂定義的,一定要和那個自定義函數(shù)指針類型返回值、形參一致。

然后把這個函數(shù)名字直接復(fù)制給KeyScanCBSRegister函數(shù)的形參就可以了。

這樣調(diào)用后,我們key.c文件的pKeyScanCBS這個指針其實(shí)就是指向的KeyScanHandle函數(shù)。

也就是說執(zhí)行pKeyScanCBS的時候,就是執(zhí)行KeyScanHandle函數(shù)。

那具體檢測按鍵的功能就是KeyPoll函數(shù),這個在main函數(shù)里調(diào)用。

當(dāng)檢測到鍵盤有輸入以后,最終會調(diào)用pKeyScanCBS。

最終執(zhí)行的是main.c文件的KeyScanHandle函數(shù)。

所以,我們來看下輸出結(jié)果。

如果還是有點(diǎn)模糊,下面我再給大家捋一捋編寫和使用回調(diào)函數(shù)的流程:

  1. 自定義函數(shù)指針,形參作為硬件層要傳到應(yīng)用層的數(shù)據(jù)。
  2. 硬件層定義一個函數(shù)指針和函數(shù)指針注冊函數(shù)。
  3. 應(yīng)用層定義一個函數(shù),返回值和形參都要和函數(shù)指針一致。
  4. 應(yīng)用層調(diào)用函數(shù)指針注冊函數(shù),把定義好的函數(shù)名稱作為形參傳入。

Ok,這就是回調(diào)函數(shù)的使用。

如果還看不懂建議多看兩遍。

下面請大家思考一下,這個程序雖然簡單,但是不是架構(gòu)還不錯?應(yīng)用層和硬件層完全獨(dú)立?

總結(jié)

到此這篇關(guān)于c語言中回調(diào)函數(shù)的使用以及實(shí)際作用的文章就介紹到這了,更多相關(guān)c語言回調(diào)函數(shù)使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

开平市| 扶余县| 淮阳县| 双流县| 宁安市| 临澧县| 洛扎县| 青海省| 阜城县| 金乡县| 天祝| 安吉县| 丹棱县| 兴仁县| 来宾市| 隆德县| 阿坝| 呼和浩特市| 贵定县| 修水县| 四平市| 峨边| 南宁市| 政和县| 靖江市| 彰化县| 永昌县| 揭阳市| 南皮县| 伊吾县| 乌兰浩特市| 五寨县| 惠州市| 泾川县| 当涂县| 中宁县| 遂昌县| 靖边县| 阳原县| 商城县| 稷山县|