2.canfestivel-回调函数

本文详细介绍了如何在从站接收到主站发送的RPDO数据后,通过注册回调函数来执行特定操作的方法。主要讲解了回调函数的定义、注册过程及自定义操作的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当从站收到主站发来的RPDO数据之后,怎么去执行特定的操作呢?

只需要编写回调函数并注册到相应的索引对象就可以。

索引回调函数的原型在objdictdef.h定义,如下所示

typedef UNS32 (*ODCallback_t)(CO_Data* d, const indextable *, UNS8 bSubindex);

typedef struct td_subindex
{
    UNS8                    bAccessType;
    UNS8                    bDataType; /* Defines of what datatype the entry is */
    UNS32                   size;      /* The size (in Byte) of the variable */
    void*                   pObject;   /* This is the pointer of the Variable */
	ODCallback_t            callback;  /* Callback function on write event */
} subindex;

定义RPDO1的回调函数如下

UNS32 _cb_RPDO1(CO_Data* d, const indextable *table, UNS8 bSubindex)
{
	//关联变量:Write_Outputs_8_Bit
	uint32_t ret = 0;
	uint8_t doOut = *(uint8_t*)table->pSubindex[bSubindex].pObject;
	for(int channel=0;channel<8;channel++)
	{
		JC_do_output(channel+1,(doOut>>channel)&0x01);
	}
	return ret;
}

函数里可以直接操作关联的变量Write_Outputs_8_Bit的,直接操作还简单一点。

注册回调函数的函数在objacces.c中定义

UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
{
  UNS32 errorCode;
  const indextable *odentry;

  odentry = d->scanIndexOD (d, wIndex, &errorCode);
  if(errorCode == OD_SUCCESSFUL &&  bSubindex < odentry->bSubCount) 
    odentry->pSubindex[bSubindex].callback = Callback;
  return errorCode;
}

这个函数很简单也很好理解,只需要调用它把自定义的回调函数注册到对应索引的对象就可以了

RegisterSetODentryCallBack(	&A46Slave_Data,0x6200,0x01,_cb_RPDO1);

这样当收到RPDO1的数据之后,协议栈在处理完数据之后会自动调用自定义的回调函数_cb_RPDO1,自定义的操作得以执行。

有些RPDO可能会有多个子索引,我们可以在每个子索引都注册回调函数,也可以只在最后的那个子索引注册回调函数,对之前的子索引统一操作。

除了能自定义回调函数,协议栈还预定义了其他一些回调函数,但是都是空实现,我们可以根据自己的实际需求去实现

/***********************************************************************
**callbacks frome canfestival  start
**这些回调看需求实现
***********************************************************************/
//states.c
void _initialisation(CO_Data* d)
{
	_ledState = d->nodeState;
}

void _preOperational(CO_Data* d)
{
	_ledState = d->nodeState;
    if (!(*(d->iam_a_slave)))
    {
        masterSendNMTstateChange (d, 0, NMT_Reset_Node);
    }
}

void _operational(CO_Data* d)
{
	_ledState = d->nodeState;
}

void _stopped(CO_Data* d)
{
	_ledState = d->nodeState;
}

//emcy.c
void _post_emcy(CO_Data* d, UNS8 nodeID, UNS16 errCode, UNS8 errReg, const UNS8 errSpec[5])
{
	(void)d;
	(void)nodeID;
	(void)errCode;
	(void)errReg;
	(void)errSpec;
}

//lifegrd.c
void _heartbeatError(CO_Data* d, UNS8 heartbeatID)
{
	(void)d;
	(void)heartbeatID;
}

void _post_SlaveBootup(CO_Data* d, UNS8 SlaveID)
{
	(void)d;
	(void)SlaveID;
}

void _post_SlaveStateChange(CO_Data* d, UNS8 nodeId, e_nodeState newNodeState)
{
	(void)d;
	(void)nodeId;
	(void)newNodeState;
}

void _nodeguardError(CO_Data* d, UNS8 id)
{
	(void)d;
	(void)id;
}

//objacces.c
UNS32 _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex)
{
  (void)d;
  (void)wIndex;
  (void)bSubindex;
  return OD_SUCCESSFUL;
}

//sync.c
void _post_sync(CO_Data* d)
{
	(void)d;
}
void _post_TPDO(CO_Data* d)
{
	(void)d;
}

void canChangeBaudRate(CAN_PORT canhandle, char* baudrate)
{
	return;
}

/***********************************************************************
**callbacks from canfestival  end
***********************************************************************/

这些函数有的在初始化字典编辑器自动生成的A46Slave_Data变量(CO_Data类型)的时候,成为了A46Slave_Data的一个元素。

CO_Data A46Slave_Data = CANOPEN_NODE_DATA_INITIALIZER(A46Slave);

/* A macro to initialize the data in client app.*/
/* CO_Data structure */
#define CANOPEN_NODE_DATA_INITIALIZER(NODE_PREFIX) {\
	/* Object dictionary*/\
	& NODE_PREFIX ## _bDeviceNodeId,     /* bDeviceNodeId */\
	NODE_PREFIX ## _objdict,             /* objdict  */\
	NODE_PREFIX ## _PDO_status,          /* PDO_status */\
	NULL,                                /* RxPDO_EventTimers */\
	_RxPDO_EventTimers_Handler,          /* RxPDO_EventTimers_Handler */\
	& NODE_PREFIX ## _firstIndex,        /* firstIndex */\
	& NODE_PREFIX ## _lastIndex,         /* lastIndex */\
	& NODE_PREFIX ## _ObjdictSize,       /* ObjdictSize */\
	& NODE_PREFIX ## _iam_a_slave,       /* iam_a_slave */\
	NODE_PREFIX ## _valueRangeTest,      /* valueRangeTest */\
	\
	/* SDO, structure s_transfer */\
	{\
          REPEAT_SDO_MAX_SIMULTANEOUS_TRANSFERS_TIMES(s_transfer_Initializer)\
	},\
	\
	/* State machine*/\
	Unknown_state,      /* nodeState */\
	/* structure s_state_communication */\
	{\
		0,          /* csBoot_Up */\
		0,          /* csSDO */\
		0,          /* csEmergency */\
		0,          /* csSYNC */\
		0,          /* csHeartbeat */\
		0,           /* csPDO */\
		0           /* csLSS */\
	},\
	_initialisation,     /* initialisation */\
	_preOperational,     /* preOperational */\
	_operational,        /* operational */\
	_stopped,            /* stopped */\
	NULL,                /* NMT node reset callback */\
	NULL,                /* NMT communications reset callback */\
	\
	/* NMT-heartbeat */\
	& NODE_PREFIX ## _highestSubIndex_obj1016, /* ConsumerHeartbeatCount */\
	NODE_PREFIX ## _obj1016,                   /* ConsumerHeartbeatEntries */\
	NODE_PREFIX ## _heartBeatTimers,           /* ConsumerHeartBeatTimers  */\
	& NODE_PREFIX ## _obj1017,                 /* ProducerHeartBeatTime */\
	TIMER_NONE,                                /* ProducerHeartBeatTimer */\
	_heartbeatError,           /* heartbeatError */\
	\
	{REPEAT_NMT_MAX_NODE_ID_TIMES(NMTable_Initializer)},\
                                                   /* is  well initialized at "Unknown_state". Is it ok ? (FD)*/\
	\
	/* NMT-nodeguarding */\
	TIMER_NONE,                                /* GuardTimeTimer */\
	TIMER_NONE,                                /* LifeTimeTimer */\
	_nodeguardError,           /* nodeguardError */\
	& NODE_PREFIX ## _obj100C,                 /* GuardTime */\
	& NODE_PREFIX ## _obj100D,                 /* LifeTimeFactor */\
	{REPEAT_NMT_MAX_NODE_ID_TIMES(nodeGuardStatus_Initializer)},\
	\
	/* SYNC */\
	TIMER_NONE,                                /* syncTimer */\
	& NODE_PREFIX ## _obj1005,                 /* COB_ID_Sync */\
	& NODE_PREFIX ## _obj1006,                 /* Sync_Cycle_Period */\
	/*& NODE_PREFIX ## _obj1007, */            /* Sync_window_length */\
	_post_sync,                 /* post_sync */\
	_post_TPDO,                 /* post_TPDO */\
	_post_SlaveBootup,			/* post_SlaveBootup */\
  _post_SlaveStateChange,			/* post_SlaveStateChange */\
	\
	/* General */\
	0,                                         /* toggle */\
	NULL,                   /* canSend */\
	NODE_PREFIX ## _scanIndexOD,                /* scanIndexOD */\
	_storeODSubIndex,                /* storeODSubIndex */\
    /* DCF concise */\
    NULL,       /*dcf_odentry*/\
	NULL,		/*dcf_cursor*/\
	1,		/*dcf_entries_count*/\
	0,		/* dcf_status*/\
    0,      /* dcf_size */\
    NULL,   /* dcf_data */\
	\
	/* EMCY */\
	Error_free,                      /* error_state */\
	sizeof(NODE_PREFIX ## _obj1003) / sizeof(NODE_PREFIX ## _obj1003[0]),      /* error_history_size */\
	& NODE_PREFIX ## _highestSubIndex_obj1003,    /* error_number */\
	& NODE_PREFIX ## _obj1003[0],    /* error_first_element */\
	& NODE_PREFIX ## _obj1001,       /* error_register */\
    & NODE_PREFIX ## _obj1014,       /* error_cobid */\
	/* error_data: structure s_errors */\
	{\
	REPEAT_EMCY_MAX_ERRORS_TIMES(ERROR_DATA_INITIALIZER)\
	},\
	_post_emcy,              /* post_emcy */\
	/* LSS */\
	lss_Initializer\
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值