您的位置:首页 > 编程语言 > C语言/C++

回调函数_注册

2016-05-14 15:48 459 查看

C语言回调函数–注册

续接上一节

回调函数数组简介及运行思路

  回调函数的注册是把一个普通函数注册为一个回调函数的过程,本例中通过分析main函数执行过程,来详细了解回调函数注册思路。

main函数执行过程:

1、首先按照CBDemo格式声明结构体变量demo,用于注册回调函数,再对k赋值。

 按照Data格式声明结构体变量data,用于存储回调函数要用的数据,再对i,j赋值。

2、硬件初始化,包括LED、UART、Button。

3、使用RegisterCallback将Test函数注册为回调函数,传入参数为:注册回调函数的结构体demo、被注册函数Test、数据参数data。

注:RegisterCallback函数出传入三个重要参数;

  参数1:CBDemo *pDemo 是用于注册回调函数的结构体,该结构体包括CBTest类型回调函数和 void * 类型回调函数参数;

  参数2:CBTest Test为指向被注册函数的指针;

  参数3:void *p 传入回调函数被调用时使用的参数;

  在注册过程中将参数2即将被注册为回调的函数地址,赋值给参数1结构体中的–>cb元素;将参数3即回调函数被调用时使用的参数,赋值给参数1结构体中给的–>cbParam元素。

4、串口打印data中的i,j两个数据,由于只注册未执行,因此输出结果为:10,11。

5、通过demo.cb(demo.cbParam)调用回调函数,Test的到执行,因此输出结果为:11,12。

6、按照上述第3条步骤,使用RegisterCallback将Test2函数注册为回调函数.

7、串口打印demp中的k数据,由于只注册未执行,因此输出结果为:1。

8、通过demo.cb(demo.cbParam)调用回调函数,Test2的到执行,因此输出结果为:10。



一、首先使用typedef声明执行函数的指针类型,返回值类型、参数类型

格式:typedef void(*CBTest)(void *p); 即:返回值(指针名)(参数列表)

例:
typedef void(*CBTest)(void *p);


二、声明用于注册回调函数的结构体

格式:同正常结构体声明方法

例:

typedef struct _cbDemo CBDemo;

struct _cbDemo
{
CBTest cb;      //指向回调函数的指针
void * cbParam;     //指向参数的指针
int k;
};


三、声明用于存储函数数据成员变量的结构体

格式:同正常结构体声明

例:

typedef struct _Data Data;
struct _Data    //包含i、j两个整形成员变量
{
int i;
int j;
};


四、声明要作为回调函数的两个函数:Test()和Test2()

格式:void Test(void *p),同正常函数声明,传入参数为指针。

例:

void Test(void *p)
{
((Data*)p)->i++;
((Data*)p)->j++;
}
void Test2(void *p)
{
((CBDemo*)p)->k = 10;
}


五、声明用于注册回调函数的函数

格式:void RegisterCallback(CBDemo *pDemo,CBTest Test , void *p),同正常函数声明过程。参数:pDemo:用于注册回调函数的结构体;test:要注册的回调函数;p:回调函数被调用时使用的参数。

例:

void RegisterCallback(CBDemo *pDemo,CBTest Test , void *p)
{
pDemo ->cb = Test;  //结构体的cb指向回调函数
pDemo ->cbParam = p; //结构体的cbParam指向参数
}


介绍部分到此为止。附main.c代码

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nrf_gpio.h"
#include "nrf_adc.h"
#include "app_uart.h"
#include "nrf_delay.h"
#include "app_error.h"
#include "app_timer.h"
#include "app_button.h"

#define RX_PIN_NUMBER 11
#define TX_PIN_NUMBER 9
#define RTS_PIN_NUMBER 8
#define CTS_PIN_NUMBER 10
#define UART_TX_BUF_SIZE 128 /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 128

#define LED0 18
#define LED1 19
#define BUTTON0 16
#define BUTTON1 17
#define BUTTONS_NUMBER 2

#define APP_TIMER_PRESCALER 0
#define APP_TIMER_MAX_TIMERS 8
#define APP_TIMER_OP_QUEUE_SIZE 8

uint32_t err_code;
static void lfclk_config(void);
void uart_error_handle(app_uart_evt_t * p_event);
void uart_init(void);
void button_event_handler(uint8_t pin_no, uint8_t button_action);
void app_button_user_init(void);

typedef void(*CBTest)(void *p);
typedef struct _cbDemo CBDemo;
struct _cbDemo
{
CBTest cb;
void *cbParam;
int k;
};
typedef struct _Data Data;
struct _Data
{
int i;
int j;
};
void Test(void *p) { ((Data*)p)->i++; ((Data*)p)->j++; } void Test2(void *p) { ((CBDemo*)p)->k = 10; }void RegisterCallback(CBDemo *pDemo,CBTest Test,void *p)
{
pDemo->cb = Test;
pDemo->cbParam = p;
}

int main()
{
CBDemo demo;
Data data;
data.i = 10;
data.j = 11;
demo.k = 1;
nrf_gpio_cfg_output(LED0);
nrf_gpio_cfg_output(LED1);
lfclk_config();
uart_init();
app_button_user_init();

RegisterCallback(&demo,Test,&data);
printf("%d,%d\n\r",data.i,data.j);
nrf_delay_ms(10);
demo.cb(demo.cbParam);
printf("%d,%d\n\r",data.i,data.j);
nrf_delay_ms(10);
RegisterCallback(&demo,Test2,&demo);
printf("%d\n",demo.k);
nrf_delay_ms(10);
demo.cb(demo.cbParam);
printf("%d\n\r",demo.k);
nrf_delay_ms(10);
while(1)
{
}
}

void uart_error_handle(app_uart_evt_t * p_event)
{
if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR)
{
APP_ERROR_HANDLER(p_event->data.error_communication);
}
else if (p_event->evt_type == APP_UART_FIFO_ERROR)
{
APP_ERROR_HANDLER(p_event->data.error_code);
}
}

void uart_init(void)
{
const app_uart_comm_params_t comm_params =
{
RX_PIN_NUMBER,
TX_PIN_NUMBER,
RTS_PIN_NUMBER,
CTS_PIN_NUMBER,
APP_UART_FLOW_CONTROL_DISABLED,
false,
UART_BAUDRATE_BAUDRATE_Baud115200
};
APP_UART_FIFO_INIT(&comm_params,
UART_RX_BUF_SIZE,
UART_TX_BUF_SIZE,
uart_error_handle,
APP_IRQ_PRIORITY_LOW,
err_code);

APP_ERROR_CHECK(err_code);
}
void button_event_handler(uint8_t pin_no, uint8_t button_action)
{
static uint8_t i = 0;
printf("%d\n\r",i++);
}
void app_button_user_init(void)
{
uint32_t timer_ticks = APP_TIMER_TICKS(100, APP_TIMER_PRESCALER);
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
static app_button_cfg_t P_button[BUTTONS_NUMBER] =
{
{
BUTTON0,
APP_BUTTON_ACTIVE_LOW,
NRF_GPIO_PIN_NOPULL,
button_event_handler
},
{
BUTTON1,
APP_BUTTON_ACTIVE_LOW,
NRF_GPIO_PIN_NOPULL,
button_event_handler
}
};
err_code = app_button_init((app_button_cfg_t *)P_button,BUTTONS_NUMBER,timer_ticks);
err_code = app_button_enable();
}
static void lfclk_config(void)
{
NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
NRF_CLOCK->TASKS_LFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
{
//Do nothing.
}
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
}


个人见解,仅供参考,希望能够与诸位共同讨论分析
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数 c语言 结构