簡(jiǎn)介:
嵌入式函數(shù)回調(diào)注冊(cè)機(jī)制是一種常用的解耦技術(shù),它通過(guò)在應(yīng)用程序中注冊(cè)回調(diào)函數(shù)的方式來(lái)實(shí)現(xiàn)模塊之間的通信,從而使系統(tǒng)更加靈活、可擴(kuò)展和易于維護(hù)。函數(shù)回調(diào)注冊(cè)機(jī)制可以通過(guò)函數(shù)指針和回調(diào)函數(shù)來(lái)實(shí)現(xiàn)。
的地址存儲(chǔ)到函數(shù)指針中,我們可以實(shí)現(xiàn)將回調(diào)函數(shù)注冊(cè)到事件源中。
本篇我就根據(jù)STM32單片機(jī)這方面進(jìn)行一個(gè)說(shuō)明其他單片機(jī)或微控制器的用法是一樣的。了解大致的思路、方式方法。
什么是函數(shù)回調(diào)注冊(cè)機(jī)制?
函數(shù)回調(diào)注冊(cè)機(jī)制是一種常見(jiàn)的編程技術(shù),它允許我們?cè)诔绦蜻\(yùn)行時(shí)動(dòng)態(tài)地注冊(cè)函數(shù)回調(diào),并在適當(dāng)?shù)臅r(shí)候調(diào)用這些回調(diào)函數(shù)。回調(diào)函數(shù)通常用于實(shí)現(xiàn)事件處理、狀態(tài)通知、消息傳遞等功能,可以極大地提高程序的靈活性和可擴(kuò)展性。
函數(shù)回調(diào)注冊(cè)機(jī)制的基本思想是:將一個(gè)函數(shù)的指針作為參數(shù)傳遞給另一個(gè)函數(shù),然后在需要調(diào)用這個(gè)函數(shù)時(shí),直接調(diào)用它的指針即可。通過(guò)這種方式,我們可以將函數(shù)的調(diào)用權(quán)交給其他函數(shù),從而實(shí)現(xiàn)動(dòng)態(tài)的、靈活的、可擴(kuò)展的程序設(shè)計(jì)。
在函數(shù)回調(diào)注冊(cè)機(jī)制中,通常會(huì)定義一個(gè)回調(diào)函數(shù)類(lèi)型,用于指定回調(diào)函數(shù)的參數(shù)和返回值類(lèi)型。然后,我們可以定義一個(gè)函數(shù),用于注冊(cè)回調(diào)函數(shù),將回調(diào)函數(shù)的指針保存在全局變量中。在需要調(diào)用回調(diào)函數(shù)的地方,我們可以檢查回調(diào)函數(shù)指針是否為 NULL,如果不為 NULL,則調(diào)用回調(diào)函數(shù)。
函數(shù)回調(diào)注冊(cè)機(jī)制在嵌入式系統(tǒng)中得到廣泛應(yīng)用,特別是在處理事件和中斷時(shí)。通過(guò)動(dòng)態(tài)注冊(cè)回調(diào)函數(shù),我們可以更靈活地處理不同類(lèi)型的事件和中斷,從而提高系統(tǒng)的可靠性和效率。
實(shí)現(xiàn)的大致步驟
定義回調(diào)函數(shù)類(lèi)型
首先需要定義一個(gè)回調(diào)函數(shù)類(lèi)型,用于指定回調(diào)函數(shù)的參數(shù)和返回值類(lèi)型。例如:
typedef void (*callback_func_t)(int arg1, float arg2);
上述代碼定義了一個(gè)回調(diào)函數(shù)類(lèi)型 'callback_func_targ1和浮點(diǎn)型arg2,返回值為void。
定義回調(diào)函數(shù)
根據(jù)定義的回調(diào)函數(shù)類(lèi)型,需要定義相應(yīng)的回調(diào)函數(shù)。例如:
void callback_function(int arg1, float arg2)
{
// 回調(diào)函數(shù)的具體實(shí)現(xiàn)
}
上述代碼定義了一個(gè)名為 'callbackcallback_func_t類(lèi)型相匹配,可以作為回調(diào)函數(shù)使用。
定義回調(diào)函數(shù)注冊(cè)函數(shù)
定義一個(gè)函數(shù),用于注冊(cè)回調(diào)函數(shù),將回調(diào)函數(shù)的指針保存在全局變量中。例如
void register_callback(callback_func_t callback)
{
// 保存回調(diào)函數(shù)指針到全局變量中
global_callback = callback;
}
調(diào)用回調(diào)函數(shù)
在需要調(diào)用回調(diào)函數(shù)的地方,可以檢查回調(diào)函數(shù)指針是否為 NULL,如果不為 NULL,則調(diào)用回調(diào)函數(shù)。例如:
if (global_callback != NULL) {
global_callback(10, 3.14f);
}
完整的:
1#include
2
3typedef void (*callback_func_t)(int arg1, float arg2);
4
5callback_func_t global_callback = NULL;
6
7void callback_function(int arg1, float arg2) {
8 printf("callback_function: arg1=%d, arg2=%f\\n", arg1, arg2);
9}
10
11void register_callback(callback_func_t callback) {
12 global_callback = callback;
13}
14
15int main() {
16 register_callback(callback_function);
17
18 if (global_callback != NULL) {
19 global_callback(10, 3.14f);
20 }
21
22 return 0;
23}
在單片機(jī)中的應(yīng)用舉例
回調(diào)函數(shù)是一個(gè)指向函數(shù)的指針,它可以在某個(gè)事件發(fā)生時(shí)被調(diào)用。在嵌入式系統(tǒng)中,回調(diào)函數(shù)通常用于響應(yīng)外部事件或中斷,例如定時(shí)器中斷、UART接收中斷等。使用回調(diào)函數(shù),可以將事件處理的邏輯與事件源分離開(kāi)來(lái),從而提高代碼的可維護(hù)性和可重用性。
函數(shù)回調(diào)注冊(cè)機(jī)制通常由兩部分組成:注冊(cè)函數(shù)和回調(diào)函數(shù)。注冊(cè)函數(shù)用于將回調(diào)函數(shù)注冊(cè)到事件源中,以便在事件發(fā)生時(shí)調(diào)用回調(diào)函數(shù)。回調(diào)函數(shù)則用于處理事件,它通常被實(shí)現(xiàn)為一個(gè)短小精悍的函數(shù),只執(zhí)行必要的操作,以便盡快地返回到事件源中。
我們可以使用函數(shù)指針來(lái)實(shí)現(xiàn)回調(diào)函數(shù)的注冊(cè)。函數(shù)指針是指向函數(shù)的指針變量,它可以存儲(chǔ)一個(gè)函數(shù)的地址,并且可以被傳遞和調(diào)用。通過(guò)將回調(diào)函數(shù)
1#include "stm32f4xx.h"
2
3// 定義一個(gè)回調(diào)函數(shù)類(lèi)型
4typedef void (*irq_callback_t)(void);
5
6// 定義一個(gè)全局變量,用于保存中斷回調(diào)函數(shù)
7irq_callback_t irq_callback = NULL;
8
9// 定義一個(gè)中斷處理函數(shù)
10void EXTI0_IRQHandler(void) {
11 // 調(diào)用中斷回調(diào)函數(shù)
12 if (irq_callback) {
13 irq_callback();
14 }
15
16 // 清除中斷標(biāo)志位
17 EXTI_ClearITPendingBit(EXTI_Line0);
18}
19
20// 定義一個(gè)函數(shù),用于注冊(cè)中斷回調(diào)函數(shù)
21void register_irq_callback(irq_callback_t cb) {
22 irq_callback = cb;
23}
24
25int main() {
26 // 初始化GPIO和中斷
27 // ...
28
29 // 注冊(cè)中斷回調(diào)函數(shù)
30 register_irq_callback(my_irq_handler);
31
32 // 啟用中斷
33 NVIC_EnableIRQ(EXTI0_IRQn);
34
35 while (1) {
36 // 主循環(huán)
37 // ...
38 }
39
40 return 0;
41}
42
43// 定義一個(gè)中斷回調(diào)函數(shù)
44void my_irq_handler(void) {
45 // 處理中斷事件
46 // ...
47}
在上面的示例程序中,我們首先定義了一個(gè)回調(diào)函數(shù)類(lèi)型irq_callback_t ,它指向一個(gè)參數(shù)為 void,返回類(lèi)型為void的函數(shù)。接著,我們定義了一個(gè)全局變量irq_callback,用于保存中斷回調(diào)函數(shù)。在中斷處理函數(shù)EXTI0_IRQHandler中,我們首先判斷irq_callback是否為NULL,如果不為NULL,則調(diào)用中斷回調(diào)函數(shù)。在函數(shù)register_irq_callback中,我們將中斷回調(diào)函數(shù)指針保存在全局變量irq_callback 中。在 main函數(shù)中,我們注冊(cè)了中斷回調(diào)函數(shù) ,并啟用了中斷。在中斷回調(diào)函數(shù)my_irq_handler中,我們可以處理中斷事件。
注意:,函數(shù)回調(diào)注冊(cè)機(jī)制在嵌入式系統(tǒng)中雖然常見(jiàn),但也需要注意線(xiàn)程安全、內(nèi)存管理等方面的問(wèn)題,以保證程序的正確性和可靠性。此外,函數(shù)回調(diào)注冊(cè)機(jī)制還可以用于實(shí)現(xiàn)定時(shí)器事件。定時(shí)器通常用于周期性地生成定時(shí)中斷,并在中斷處理函數(shù)中調(diào)用注冊(cè)的回調(diào)函數(shù)。
下面是一個(gè)使用定時(shí)器的例子:
1#include "stm32f4xx.h"
2
3// 定義一個(gè)回調(diào)函數(shù)類(lèi)型
4typedef void (*timer_callback_t)(void);
5
6// 定義一個(gè)全局變量,用于保存定時(shí)器回調(diào)函數(shù)
7timer_callback_t timer_callback = NULL;
8
9// 定義一個(gè)定時(shí)器中斷處理函數(shù)
10void TIM2_IRQHandler(void) {
11 // 調(diào)用定時(shí)器回調(diào)函數(shù)
12 if (timer_callback) {
13 timer_callback();
14 }
15
16 // 清除中斷標(biāo)志位
17 TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
18}
19
20// 定義一個(gè)函數(shù),用于注冊(cè)定時(shí)器回調(diào)函數(shù)
21void register_timer_callback(timer_callback_t cb) {
22 timer_callback = cb;
23}
24
25int main() {
26 // 初始化定時(shí)器和中斷
27 // ...
28
29 // 注冊(cè)定時(shí)器回調(diào)函數(shù)
30 register_timer_callback(my_timer_handler);
31
32 // 啟用定時(shí)器
33 TIM_Cmd(TIM2, ENABLE);
34
35 while (1) {
36 // 主循環(huán)
37 // ...
38 }
39
40 return 0;
41}
42
43// 定義一個(gè)定時(shí)器回調(diào)函數(shù)
44void my_timer_handler(void) {
45 // 處理定時(shí)器事件
46 // ...
47}
-
單片機(jī)
+關(guān)注
關(guān)注
6032文章
44521瀏覽量
633106 -
UART接口
+關(guān)注
關(guān)注
0文章
124瀏覽量
15268 -
STM32F4
+關(guān)注
關(guān)注
3文章
194瀏覽量
27995 -
定時(shí)器中斷
+關(guān)注
關(guān)注
0文章
49瀏覽量
11165
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論