回调函数_注册

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;
}

个人见解,仅供参考,希望能够与诸位共同讨论分析

猜你喜欢

转载自blog.csdn.net/u010333084/article/details/51406405