精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一篇學會回調函數

開發 前端
關于回調函數,我的態度是:回調函數可以使我們的代碼更高效且更易于維護,降低耦合。明智地使用它們很重要,否則過度使用回調(函數指針)會使代碼難以進行排查和。

函數指針

學習回調函數,其實就是函數指針的應用,關于函數指針在之前的文章《??指針與函數??》中有詳細的講解,這里不再展開詳解,重新貼一下之前文章中函數指針的示例代碼:

#include <stdio.h>
void MyFun1(int x);
void MyFun2(int x);
void MyFun3(int x);
typedef void (*FunType)(int); /* ②. 定義一個函數指針類型FunType,與①函數類型一致 */
void CallMyFun(FunType fp, int x);
int main(int argc, char *argv[])
{
CallMyFun(MyFun1, 10); /* ⑤. 通過CallMyFun函數分別調用三個不同的函數 */
CallMyFun(MyFun2, 20);
CallMyFun(MyFun3, 30);
}
void CallMyFun(FunType fp, int x) /* ③. 參數fp的類型是FunType。*/
{
fp(x); /* ④. 通過fp的指針執行傳遞進來的函數,注意fp所指的函數是有一個參數的。 */
}
void MyFun1(int x) /* ①. 這是個有一個參數的函數,以下兩個函數也相同。 */
{
printf("MyFun1:%d\n", x);
}
void MyFun2(int x)
{
printf("MyFun2:%d\n", x);
}
void MyFun3(int x)
{
printf("MyFun3:%d\n", x);
}

運行結果如下:

為什么需要回調函數

這里先說一下軟件分層的問題,軟件分層的一般原則是:上層可以直接調用下層的函數,下層則不能直接調用上層的函數。這句話說來簡單,在現實中,下層常常要反過來調用上層的函數。

比如你在拷貝文件時,在界面層調用一個拷貝文件函數。界面層是上層,拷貝文件函數是下層,上層調用下層,理所當然。但是如果你想在拷貝文件時還要更新進度條,問題就來了。

一方面,只有拷貝文件函數才知道拷貝的進度,但它不能去更新界面的進度條。另外一方面,界面知道如何去更新進度條,但它又不知道拷貝的進度。怎么辦?

常見的做法,就是界面設置一個回調函數給拷貝文件函數,拷貝文件函數在適當的時候調用這個回調函數來通知界面更新狀態。

上面主要說的一個大型軟件分層理念,作為嵌入式開發程序員,特別是單片機的開發中,由于和硬件結合緊密且需要快速響應,軟件結構大部分是面向過程開發的,回調函數使用頻率并不高。但在軟件中使用回調函數,可以讓軟件更加模塊化。

上圖形象展示了回調函數的作用,上面說到了軟件分層,在嵌入式代碼中我們一般將和硬件交互的代碼稱為硬件層,業務邏輯代碼稱為應用層代碼,對于優秀的的嵌入式代碼,一般要求硬件層和應用層代碼分開。

一般的回調函數代碼結構如下:


typedef void (*ReceiveFarmDataFun)();

static CallbackReceive_t HandlerCompleted;

/*用來注冊回調函數的功能函數*/
void CallbackRegister (CallbackFunc_t callback_func) {
HandlerCompleted = callback_func;
}

串口應用

在嵌入式應用中,串口通信是很經典且常用的外設,舉一個簡單的栗子,接收的串口數據幀頭是@,幀尾是*。中間數據不可能出現@和*。那么一般情況下代碼如下編寫。


/*串口中斷函數*/
uint8_t receive_flg = 0;
uint8_t receive_data[100];
uint8_t USART1_data = 0;
uint8_t USART1_data_len = 0;
uint8_t USART1_receive_sta = 0;
void USART1_IRQHandler(void)
{
uint8_t data_tmp;
if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE))
{
data_tmp = USART_ReceiveData(USART1);
if((data_tmp == '*')&&(USART1_receive_sta == 1))
{
receive_flg = 1;
USART1_receive_sta = 0;
receive_data[USART1_data_len++] = data_tmp;
}
if(receive_flg == 0){
if(data_tmp == '@')
{
USART1_receive_sta = 1;
USART1_data_len = 0;
}
if(USART1_receive_sta)
receive_data[USART1_data_len++] = data_tmp;
if(USART1_data_len > (100-1))
{
receive_flg = 0;
USART1_receive_sta = 0;
}
}
USART_ClearFlag(USART1, USART_FLAG_RXNE);
}
}
/*應用層代碼,簡單化->在main函數*/
void main()
{
/*省略其他代碼*/
while(1)
{
if(receive_flg == 1)//通過檢查receive_data判斷是否接收到函數
{
/*通過receive_data數組處理數據*/
receive_flg = 0;
}
}
}

這樣實現功能是沒有問題的,在我接觸到很多的項目中的確是類似的架構,但是它的移植性較差。

還有一種情況,那就是如果你接到需求把硬件層封裝給客戶使用,不讓客戶看到源碼,封裝成庫,起到"保護通訊協議"的目的,那么你要告訴客戶,需要判斷receive_flg變量,然后讀取receive_data數組的內容???

不得不說,你這樣干是可以的,但是大部分公司不會這樣干的。這時候可以使用回調函數來解決這個問題。

/*開放給客戶的頭文件*/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
typedef void (*ReceiveFarmDataFun)(uint8_t *buff,uint32_t bufferlen);
extern void CallbackRegister (CallbackFunc_t callback_func)

/*封裝的函數*/
static CallbackReceive_t HandlerCompleted;
void CallbackRegister (CallbackFunc_t callback_func) {
HandlerCompleted = callback_func;
}
uint8_t receive_flg = 0;
uint8_t receive_data[100];
uint8_t USART1_data = 0;
uint8_t USART1_data_len = 0;
uint8_t USART1_receive_sta = 0;
void USART1_IRQHandler(void)
{
uint8_t data_tmp;
if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE))
{
data_tmp = USART_ReceiveData(USART1);
if((data_tmp == '*')&&(USART1_receive_sta == 1))
{
receive_flg = 1;
USART1_receive_sta = 0;
HandlerCompleted(receive_data,USART1_data_len);
}
if(receive_flg == 0){
if(data_tmp == '@')
{
USART1_receive_sta = 1;
USART1_data_len = 0;
}
if(USART1_receive_sta)
receive_data[USART1_data_len++] = data_tmp;
if(USART1_data_len > (100-1))
{
receive_flg = 0;
USART1_receive_sta = 0;
}
}
USART_ClearFlag(USART1, USART_FLAG_RXNE);
}
}

那么客戶拿到的有用信息如下:

typedef void (*ReceiveFarmDataFun)(uint8_t *buff,uint32_t bufferlen);
extern void CallbackRegister (CallbackFunc_t callback_func)

客戶可以寫如下代碼:

void uartdatadeal(uint8_t *buff,uint32_t bufferlen)
{
/*buff指針存儲了串口數據,bufferlen存儲數據長度*/
/*客戶的應用層代碼*/
}
void main()
{
/*省略其他代碼*/
CallbackRegister (uartdatadeal);
while(1)
{
}
}

這樣的話,就可以解決上述問題,客戶只要注冊一下串口接收的函數,當接收到有效數據后,就可以跳轉到用戶的代碼,而你可以將自己的硬件層封裝起來。

看到這里可能有嵌入式大佬意識到某些問題了,這樣寫代碼,數據處理的函數就等于在中斷里了,這是不合理的啊。

是的,是有這個問題,所以給客戶的庫文件必須說明這一點,讓客戶自行選擇,客戶不想在中斷中執行,可以再按照我們一開始的邏輯寫啊,如下:

void uartdatadeal(uint8_t *buff,uint32_t bufferlen)
{
/*buff指針存儲了串口數據,bufferlen存儲數據長度*/
receive_flg = 1;
}
void main()
{
/*省略其他代碼*/
CallbackRegister (uartdatadeal);
while(1)
{
if(receive_flg == 1)
{
/*處理數據*/
receive_flg = 0;
}
}
}

事實上,芯片/模塊廠家寫SDK經常這樣做,一些大型的開源庫也會這樣用,典型的如lwip庫。

后記

讀到這里的同學可能覺得這完全是“脫褲子放屁”啊,這屬于“炫技”啊,沒什么用啊。誠然在很多應用中,特別是一些單片機項目中,代碼量不大,使用類似receive_flg全局變量控制,代碼結構也清晰啊。

并且項目不需封裝庫給客戶,一個單片機軟件開發工程師可以吃透整個項目的代碼,根本不需要這樣的“騷操作”。

關于回調函數,我的態度是:回調函數可以使我們的代碼更高效且更易于維護,降低耦合。明智地使用它們很重要,否則過度使用回調(函數指針)會使代碼難以進行排查和調試。

責任編輯:武曉燕 來源: 知曉編程
相關推薦

2021-04-07 13:28:21

函數程序員異步

2021-12-01 11:33:21

函數Min

2022-03-02 11:37:57

參數性能調優

2022-01-02 08:43:46

Python

2022-02-07 11:01:23

ZooKeeper

2021-07-06 08:59:18

抽象工廠模式

2023-11-28 08:29:31

Rust內存布局

2023-01-03 08:31:54

Spring讀取器配置

2021-07-02 09:45:29

MySQL InnoDB數據

2022-08-23 08:00:59

磁盤性能網絡

2021-05-11 08:54:59

建造者模式設計

2022-08-26 09:29:01

Kubernetes策略Master

2021-07-05 22:11:38

MySQL體系架構

2021-07-16 22:43:10

Go并發Golang

2021-07-02 08:51:29

源碼參數Thread

2021-04-29 10:18:18

循環依賴數組

2021-10-27 09:59:35

存儲

2023-03-13 21:38:08

TCP數據IP地址

2022-03-11 10:21:30

IO系統日志

2023-11-01 09:07:01

Spring裝配源碼
點贊
收藏

51CTO技術棧公眾號

亚洲人午夜精品免费| 亚洲柠檬福利资源导航| 热re91久久精品国99热蜜臀| 男人舔女人下部高潮全视频| 国产国产一区| 亚洲综合一区二区三区| 欧美一区激情视频在线观看| 国产毛片久久久久| 在线视频亚洲| 久久精品久久久久久| 日韩精品视频一区二区| 四虎4545www国产精品| 亚洲精品国产成人久久av盗摄| 精品视频一区在线| 国产探花精品一区二区| 亚洲一区国产| 另类色图亚洲色图| 免费在线观看污| 中文字幕区一区二区三| 欧美亚洲动漫另类| 男女视频网站在线观看| 九七久久人人| 久久亚洲春色中文字幕久久久| 国产在线观看精品一区二区三区| 日韩网红少妇无码视频香港| 91精品91| 中文字幕欧美专区| 免费在线观看成年人视频| 国产免费av国片精品草莓男男| 色综合中文字幕国产| 大荫蒂性生交片| 欧美黄色激情| 国产免费成人在线视频| 久久久久久a亚洲欧洲aⅴ| 国产福利第一页| 久久国产婷婷国产香蕉| 日韩免费精品视频| 日韩激情在线播放| 欧美午夜a级限制福利片| 日韩最新在线视频| 国产精品久久久视频| 欧美理论电影在线精品| 亚洲第一免费播放区| 中文字幕乱妇无码av在线| 亚洲狼人综合| 在线成人免费观看| www.激情小说.com| 99re66热这里只有精品4| 黑人巨大精品欧美一区二区三区 | 国产美女精品视频| 无码人妻精品一区二区三区不卡| 国产精品老牛| 91av在线视频观看| 西西44rtwww国产精品| 在线欧美亚洲| 97国产一区二区精品久久呦| 五月天综合在线| 国产真实久久| 国产综合在线看| 久久久久久久伊人| 亚洲乱码视频| 欧美专区日韩视频| 一级黄色在线观看| 免播放器亚洲一区| 成人激情春色网| 国产精品久久久久久久免费看| 久久精品国产99国产| 成人免费网站在线| 精品人妻av一区二区三区| 国产乱理伦片在线观看夜一区| 成人动漫在线观看视频| 国产91麻豆视频| 99久久伊人精品| 欧美一区二区影视| 日本中文字幕伦在线观看| 18成人在线视频| 国产 欧美 日本| caoporn视频在线观看| 精品国产1区2区| 成年人在线观看视频免费| 国产精品第一国产精品| 91精品国产手机| 白丝校花扒腿让我c| 看全色黄大色大片免费久久久| 精品视频久久久| 18精品爽国产三级网站| 亚洲高清资源在线观看| 午夜精品免费视频| 国产午夜麻豆影院在线观看| 激情综合网av| 精品日本一区二区三区| av资源种子在线观看| 亚洲精品中文字幕在线观看| 欧美深夜福利视频| 国产亚洲精彩久久| 亚洲加勒比久久88色综合| 国产三级av在线播放| 一本一道久久a久久精品蜜桃| 午夜精品一区二区三区在线视频 | 新67194成人永久网站| 国产欧美欧洲在线观看| 色噜噜在线播放| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ原创 | 一区二区不卡视频在线观看| 成人激情视频网站| 亚洲人久久久| 夜鲁夜鲁夜鲁视频在线播放| 91.com视频| 3d动漫精品啪啪一区二区下载| 91精品国产自产拍在线观看蜜 | 日本丰满少妇黄大片在线观看| 免费h在线看| 日韩一级二级三级精品视频| 性猛交ⅹxxx富婆video| 国内精品亚洲| 成人激情综合网| 蝌蚪视频在线播放| 亚洲午夜一区二区| 亚洲欧美日韩三级| 精品国产精品| 91精品国产高清久久久久久久久| 99久久精品国产一区色| 国产精品热久久久久夜色精品三区| 青娱乐自拍偷拍| 免费精品一区| 久久精品夜夜夜夜夜久久| 日韩一级在线视频| 91蜜桃臀久久一区二区| 国产偷国产偷亚洲清高网站| 久久久久久久久久久久久女过产乱| 久久天堂精品| 久久精品第九区免费观看 | 日韩肉感妇bbwbbwbbw| 国产精品传媒| 欧美黑人一级爽快片淫片高清| 在线视频免费观看一区| 日本一区二区三区免费乱视频| 大肉大捧一进一出好爽视频| 国产精品视屏| 色综合视频一区中文字幕| 国产又色又爽又黄又免费| 国产女主播视频一区二区| 国产超级av在线| 日韩精品免费一区二区夜夜嗨 | 成人全视频免费观看在线看| 亚洲欧洲国产一区| 好吊色在线视频| 久久久久综合网| 黄色国产精品视频| 亚洲人成伊人成综合图片| 欧美一区二区.| 日韩在线免费看| 欧美视频一二三| aa一级黄色片| 爽好久久久欧美精品| 日韩福利二区| 巨大黑人极品videos精品| 中文欧美日本在线资源| 中文字幕av免费观看| 国产精品电影一区二区三区| 欧美成人福利在线观看| 国产精品国内免费一区二区三区| 成人激情视频小说免费下载| av网址在线播放| 日韩欧美一级特黄在线播放| 久久免费视频播放| 99精品一区二区三区| 国产a视频免费观看| 嫩草一区二区三区| 国产精品一区二区电影| 超碰个人在线| 精品久久久久久亚洲综合网| 一级片中文字幕| 国产女主播视频一区二区| www.污污视频| 亚洲三级网站| 日韩欧美亚洲在线| 欧洲亚洲精品| 欧美激情中文字幕乱码免费| 毛片在线免费| 欧美精品vⅰdeose4hd| 精品午夜福利视频| 久久新电视剧免费观看| 日本高清久久久| 激情成人综合| 日本高清久久一区二区三区| 四虎精品一区二区免费| 午夜精品久久久久久久男人的天堂 | 免费精品视频一区二区三区| 免费视频成人| 91精品国产高清久久久久久91| 成年人在线观看网站| 日韩美一区二区三区| 亚洲欧美日韩激情| 亚洲乱码精品一二三四区日韩在线| 手机在线成人av| 久久97超碰国产精品超碰| 91免费国产精品| 欧美色爱综合| 亚洲自拍偷拍色片视频| 黑人巨大亚洲一区二区久| 久久视频免费观看| 欧美成人综合在线| 精品三级在线观看| 中文字幕日本人妻久久久免费| 亚洲一区二区三区四区的| 免费一级黄色录像| 94色蜜桃网一区二区三区| 91亚洲精品久久久蜜桃借种| 国产欧美大片| 黄色录像特级片| 国产传媒欧美日韩成人精品大片| 春色成人在线视频| 免费成人黄色网| 国产精品999| a'aaa级片在线观看| 久久精品国产91精品亚洲| 你懂的免费在线观看| 精品国产99国产精品| 国产精品久久777777换脸| 色欧美日韩亚洲| 全部毛片永久免费看| 亚洲激情图片小说视频| 国产wwwwxxxx| 国产视频在线观看一区二区三区| 国产十八熟妇av成人一区| 国产精品主播直播| 久国产精品视频| 免费观看成人av| 国产精品69页| 美女国产精品| 国产成人亚洲精品无码h在线| 黄色av一区| 色婷婷777777仙踪林| 国产韩日影视精品| 亚洲欧美国产不卡| 国产91精品对白在线播放| 韩国成人一区| 另类ts人妖一区二区三区| 成人欧美一区二区| 欧美电影在线观看一区| 亚洲一区二区中文字幕| 免费精品一区二区三区在线观看| 91免费观看网站| av一级久久| 91影视免费在线观看| 成人久久精品| 91视频99| jizz性欧美23| 精品网站在线看| 亚洲区小说区图片区qvod| 欧美一区二区三区四区夜夜大片 | 欧美特黄aaaaaa| 天天做天天摸天天爽国产一区 | 永久免费毛片在线观看| 国产亲近乱来精品视频| 超碰人人人人人人人| 国产精品久久久久久久久免费相片 | 亚洲少妇一区二区三区| 成人黄色av网站在线| 日本护士做爰视频| 久久在线观看免费| 国产精品免费无码| 中文字幕亚洲区| 日本妇女毛茸茸| 亚洲午夜免费视频| 成人免费视频毛片| 欧美午夜不卡视频| 国产喷水福利在线视频| 欧美tk—视频vk| 日韩av资源站| 日韩在线观看免费全集电视剧网站| 男人在线资源站| 久久久免费观看| 视频二区不卡| 91手机视频在线观看| 成人免费直播在线| 日产中文字幕在线精品一区| 天天av综合| 少妇av一区二区三区无码| 欧美专区一区二区三区| 国产精品自在自线| 9人人澡人人爽人人精品| 成人黄色免费网址| 亚洲美女屁股眼交3| 黄色片视频网站| 欧美日韩视频专区在线播放| www.桃色av嫩草.com| 亚洲美女av在线播放| 久cao在线| 91精品国产91久久久久久吃药 | 亚洲男人影院| 亚洲另类第一页| 99久久久国产精品| 日韩免费av一区| 天天操天天干天天综合网| 中文字幕永久在线观看| 精品国产制服丝袜高跟| 福利在线播放| 欧美精品videosex极品1| 制服诱惑亚洲| 国产精品国产三级国产专区53 | 无码人妻丰满熟妇区五十路百度| 精品无人码麻豆乱码1区2区 | 日本一本在线视频| 国产午夜精品美女毛片视频| 久久午夜无码鲁丝片午夜精品| 欧洲亚洲国产日韩| 免费看黄色一级视频| xxx一区二区| 丝袜美腿诱惑一区二区三区| 国产精品亚洲综合| 牛夜精品久久久久久久99黑人| 黄色av免费在线播放| 成人aaaa免费全部观看| 黑鬼狂亚洲人videos| 欧美日韩一本到| 欧美伦理影视网| 91高潮在线观看| 国产乱人伦丫前精品视频| 色哟哟免费网站| 狠狠色狠狠色合久久伊人| 丰满的亚洲女人毛茸茸| 一本大道综合伊人精品热热| 蜜桃av噜噜一区二区三区麻豆| 久久精品国产91精品亚洲| 精品国产黄a∨片高清在线| 日本三级中国三级99人妇网站| 亚洲经典在线| 黄色激情在线观看| 樱桃国产成人精品视频| 国产精品久久久久久免费| 色噜噜狠狠狠综合曰曰曰88av| 毛片无码国产| 欧美久久久久久一卡四| 国产一区二区三区的电影| 理论片大全免费理伦片| 亚洲尤物视频在线| 亚洲乱码在线观看| 欧美激情网站在线观看| 免费观看在线一区二区三区| 男人的天堂视频在线| 国产一区二区三区黄视频 | 美女看a上一区| 日本黄色小视频在线观看| 色婷婷精品久久二区二区蜜臂av| 三级视频网站在线| 国产成人久久久精品一区| 同性恋视频一区| 欧美极品欧美精品欧美图片| 久久久国产精华| 国产美女www| 中文字幕欧美日韩| 99视频这里有精品| 欧美性潮喷xxxxx免费视频看| 懂色一区二区三区免费观看| 国产在线观看免费视频今夜| 亚洲成色www8888| 在线观看网站免费入口在线观看国内| 狠狠色综合色区| 久久亚洲精选| 999福利视频| 日韩三级视频在线观看| 激情影院在线| 玛丽玛丽电影原版免费观看1977| 丝袜国产日韩另类美女| 亚洲色图27p| 日韩一级欧美一级| 碰碰在线视频| 亚洲女人毛片| 国产jizzjizz一区二区| 中国一级特黄毛片| 伊人久久综合97精品| 国产精品麻豆| 男女啪啪免费视频网站| 久久精品免费在线观看| 国产精品久久久久久免费免熟| 美女av一区二区三区| 亚欧日韩另类中文欧美| 久久久久国产一区| 亚洲成人中文在线| 国产高清视频在线观看| 97av自拍| 三级亚洲高清视频| 国产探花在线免费观看| 精品视频一区在线视频| 四虎国产精品成人免费影视| 欧美午夜性视频| 中文幕一区二区三区久久蜜桃| 亚洲成人777777| 国产成人免费av电影| 在线观看日韩| 久久精品—区二区三区舞蹈| 日韩亚洲欧美综合| 欧美一级大黄| 日本黄大片在线观看| 国产日韩欧美精品综合| 人妻无码中文字幕免费视频蜜桃| 国产精品高潮粉嫩av| 亚洲高清av|