回调函数是异步返回的,满足某种条件后系统将调用此函数,以便于程序进行处理。
其实有点类似于消息,但是比消息好用,因为消息可能被中途截获或篡改,而回调函数没办法截获,比较安全。
同时,消息一旦多了之后,时序很容易发生问题,用回调函数要好一些
回调函数必有的三要素:
(1)函数指针的定义;(类似定义了一种类型 比如int char等)
(2)函数指针的函数赋予;(这个函数指针指向了谁,谁就是回调后要执行的动作)
(3)函数指针的参数输入:(此时开始执行相应的动作)
A
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 },
};