回调函数的总结

回调函数是异步返回的,满足某种条件后系统将调用此函数,以便于程序进行处理。
其实有点类似于消息,但是比消息好用,因为消息可能被中途截获或篡改,而回调函数没办法截获,比较安全。
同时,消息一旦多了之后,时序很容易发生问题,用回调函数要好一些

回调函数必有的三要素: 

    (1)函数指针的定义;(类似定义了一种类型 比如int  char等)

    (2)函数指针的函数赋予;(这个函数指针指向了谁,谁就是回调后要执行的动作)

    (3)函数指针的参数输入:(此时开始执行相应的动作)

    typedef void (*PRIME_NOTIRY_CB)(unsigned char evt, unsigned char * dat);  /首先有定义(*PRIME_NOTIRY_CB)

                                          这样PRIME_NOTIRY_CB就是一种类型了,类似(int,char等)

                                        可以用它PRIME_NOTIRY_CB来定义同样的变量比如下面

   PRIME_NOTIRY_CB pNotifierCb; //那么pNotifierCb也是指向此类函数的指针 void (unsigned char evt, unsigned char * dat); 

prime_init(prime_notify_callback);

int  prime_init(PRIME_NOTIRY_CB notifierFunc)///
{
    HAL_Init(NULL);
 // must be after HAL_Init(NULL)!
    UTIL_Lock();
  memset(&g_tVar, 0, sizeof(TPrimeIF));
 g_tVar.pNotifierCb = notifierFunc;/给指针函数赋予函数,在这里就把prime_notify_callback赋予了pNotifierCb

                                                     /也就是说pNotifierCb已经指向了一个函数,下次在pNotifierCb填入输入参数后即可执行指向的函数  prime_notify_callback,
TIMER_SetDelay_ms(&g_tVar.tChkStateTm, PRIME_CHK_STATE_MAX_WAIT);
 TIMER_Start(&g_tVar.tChkStateTm);
 UTIL_Unlock();
return 0;
}

static void prime_notify_callback(unsigned char evt, unsigned char * buf)
{
    int node_process=-1;
int addr_buff;
    unsigned char * eui49_p;
char log_text[256];
struct tm eventTm;
time_t now = time(NULL);
mlocaltime(now, &eventTm);
    tkinfo.task_live[1]=1;
//printf("**************************有上线的或掉线的回调******************************\r\n");

if (evt == PRIME_IF_EVT_JOIN_IND)
{
printf("**************************有电表主动上线***************\r\n");
for(int i=0;i<32;i++)       
{            
 {            
  printf("%02x ",buf[i]);         
 }      
   }   

         }

   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

}

 if (g_tVar.pNotifierCb != NULL)
            {
                TempBuf[0] = (TU8)((ST7590_Status.LastDA >> 8) & 0xFF);
                TempBuf[1] = (TU8)((ST7590_Status.LastDA) & 0xFF);
                g_tVar.pNotifierCb(PRIME_IF_EVT_LEAVE_IND, TempBuf);//pNotifierCb填入输入参数后即执行指向的函数//Prime_notify_callback(PRIME_IF_EVT_LEAVE_IND, TempBuf) 
            }

B 简易的回调函数

//协议回调函数:>0 成功;<0  失败
typedef int (*prot_callback)(void* args);   //定义prot_callback函数指针可以执行此类的函数  int (void* args);

prot_callback  collection_callback =NULL;  // 指针先指向空;  collection_callback 是全局函数指针

set_collection_task_callback((prot_callback)add_system_timer_task);  

//任务下装回调
void set_collection_task_callback(prot_callback callback)   ///通过此句就初始化了函数指针collection_callback  指向了add_system_timer_task
{
collection_callback =callback;
}

........................................

后续就等如果后面加了相应的参数了,就相当于执行add_system_timer_task

if(collection_callback !=NULL)collection_callback(&task);  


void add_system_timer_task(COLLECTION_TASK_PTR  ptask )
{
if(ptask ==NULL) return ;
TI  ti =ptask->freq;
TimerConfig  timeconfig ={.curtime =time(0),0,ti.interval,ti.unit,.type =ptask->task_type};
time_t t =datetime2time(&ptask->start_time);
uint sec =ti2second(ptask->delay_ti);
t+=sec;
//存在延时
localtime_user(&t,&timeconfig.basetime);
log_print(TASK,"add task to system timer, taskno =%d ,ti ={unit =%d,interval =%d},delay_ti ={unit =%d,interval =%d} taskpriority =%d  \n",
ptask->task_no,ti.unit,ti.interval,ptask->delay_ti.unit,ptask->delay_ti.interval,ptask->task_priority);
SysAddRTimer(ptask->task_no,&timeconfig, get_timer_proc(ti.unit), ptask->task_no);
}


C  较为复杂的

*获取类包含的数据项

 */

typedef const OOPItem*  (*oopitem_list)(byte apdu_flag);     //在这里定义了oopitem_list,他是typedef const OOPItem*    (byte apdu_flag)此类型函数的指针,返回的是OOPItem* 指针类型。

struct  oopitem
{
ushort oi;
ushort prop;
uint cfg;
oopitem_func opf;
};


typedef struct
{
ClassID id;
byte  OIA[10];
oopitem_list item_list;/前面已经定义过oopitem_list ,这里直接用(可以看做 char int等等只是一个类型)
param_addr_funcparam_addr_func;
apdu_operation  request;
apdu_operationresponse;
}ClassOperation;

OOPItem* getOOPItem(byte apdu_flag,uint oad)
{
OOPItem *pitem =NULL;
const ClassOperation* p =get_class_operation(oad>>16);///比如取出的采集监控类 P指向了class_oprs[] 数组的这行

/{collection_id,{0x60},collection_item_list,get_collection_param_addr},
if(p ==NULL) return NULL;


pitem = (OOPItem*)(p->item_list(apdu_flag));重点:在此就(p->item_list )就相当于函数指针了,  指向了collection_item_list,相当于执行collection_item_list,
后面如果如果有添加相应的输入参数,就开始执行指向的函数collection_item_list

其实这一句话隐含了一个操作就是  p->item_list=collection_item_list;因为参数传递

while (pitem != NULL && pitem->oi != END_LIST_ITEM)
{
uint o =OAD(pitem->oi,pitem->prop);
if(oad == o) return pitem;
else if(((oad>>8) ==(o>>8)) && ((o&0xff) ==0xff))
{
return pitem;
}
pitem++;
}
return NULL;
}

const OOPItem* collection_item_list(byte apdu_flag)
{
if(apdu_flag ==ACTION_APDU)
return oop_oprs;
else
return oopitems;
}

const static ClassOperation class_oprs[] =
{
//数据
{data_id, {0x20,0x21,0x22}, tmnldata_item_list,},
//事件
{event_id, {0x30,0x31,0x32,0x33}, event_item_list,NULL,event_operator},
//参数
{ param_id, {0x40,0x41,0x042},param_item_list,get_tmnl_param_addr },
//设备
{device_id, {0x43}, device_item_list,get_device_param_addr},
//应用链接
{connect_id,    {0x44},                 connect_item_list,          get_connect_param_addr},
//采集监控接口类
{collection_id,{0x60},collection_item_list,get_collection_param_addr},
//ESAM接口类
{esam_id, {0xf1}, esam_item_list,get_esam_param_addr},
//总加组类
{total_group_id,{0x23},total_item_list},
//脉冲类
{pulse_id, {0x24}, pulse_item_list},
//控制类
{control_id, {0x80,0x81}, control_item_list},
//以太网通信接口类(包含GPRS)
{network_id, {0x45}, class26_network_item_list},
//输入输出接口
{io_id, {0xf2}, io_item_list},
//冻结接口
{freeze_id, {0x50}, freeze_item_list},
//文件传输
{ file_id, {0xf0 }, file_item_list },
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值