##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;
}
个人见解,仅供参考,希望能够与诸位共同讨论分析