**
**
// 启动节点函数
inline void start_node(CO_Data* d, UNS8 nodeId){
/* Ask slave node to go in operational mode */
masterSendNMTstateChange (d, nodeId, NMT_Start_Node); //主机发送网络命令启动从机
d->NMTable[nodeId] = Operational; //修改状态为运行状态
}
// 检查dcf状态并启动节点
UNS8 check_and_start_node(CO_Data* d, UNS8 nodeId)
{
if(d->dcf_status != DCF_STATUS_INIT)
return 0; //如果dcf状态不为初始化状态直接返回0并退出
if((init_consise_dcf(d, nodeId) == 0) || (read_consise_dcf_next_entry(d, nodeId) == 0)){
start_node(d, nodeId); //如果dcf配置正确,则启动节点
return 1;
}
d->dcf_status = DCF_STATUS_READ_CHECK;
return 2; //修改dcf状态为读查状态, 并返回2
}
// 启动并查找节点
inline void start_and_seek_node(CO_Data* d, UNS8 nodeId){
UNS8 node;
start_node(d,nodeId); //启动节点
/* Look for other nodes waiting to be started /
for(node = 0 ; node
continue; //如果网络节点不是初始化状态则继续循环
if(check_and_start_node(d, node) == 2)
return; //如果检查节点为读查状态, 直接退出
}
/
setState(d, Operational); //设置节点状态为运行状态
}
// 检查SDO并继续
static void CheckSDOAndContinue(CO_Data* d, UNS8 nodeId)
{
UNS32 abortCode = 0;
UNS8 buf[4], match = 0, node;
UNS32 size=4;
if(d->dcf_status == DCF_STATUS_READ_CHECK){ //如果dcf状态为读查状态则执行以下代码
// printf(“DCF_STATUS_READ_CHECK \n”);
if(getReadResultNetworkDict (d, nodeId, buf, &size, &abortCode) != SDO_FINISHED)
goto dcferror; //获取网络工作字典状态,如果SDO没有完成, 则跳去dcferror
/* Check if data received match the DCF /
if(size == d->dcf_size){
match = 1;
while(size–)
if(buf[size] != d->dcf_data[size])
match = 0;
} //循环比较接收的数据是否匹配
if(match) { //如果上一步匹配结果正确则执行下面代码
if(read_consise_dcf_next_entry(d, nodeId) == 0){ //如果dcf配置正确则继续执行下面代码
start_and_seek_node(d, nodeId); //启动并搜索节点
}
}
else { / Data received does not match : start rewriting all */
if((init_consise_dcf(d, nodeId) == 0) || (write_consise_dcf_next_entry(d, nodeId) == 0))
goto dcferror; //如果dcf配置正确或写dcf下一入口配置正确则跳去dcf error
d->dcf_status = DCF_STATUS_WRITE; //修改dcf状态为写状态
}
}
else if(d->dcf_status == DCF_STATUS_WRITE){ //如果dcf状态为写状态则执行下面语句
// printf(“DCF_STATUS_WRITE \n”);
if(getWriteResultNetworkDict (d, nodeId, &abortCode) != SDO_FINISHED)
goto dcferror; //如果SDO未完成则跳去dcf error
if(write_consise_dcf_next_entry(d, nodeId) == 0){ //如果写dcf下一入口正确 则执行下面语句
#ifdef DCF_SAVE_NODE
SaveNode(d, nodeId); //保存节点信息
d->dcf_status = DCF_STATUS_SAVED; //改变dcf状态为保存状态
#else //DCF_SAVE_NODE
d->dcf_status = DCF_STATUS_INIT; //改变dcf状态为初始状态
start_and_seek_node(d,nodeId); //启动并查找节点
#endif //DCF_SAVE_NODE
}
}
else if(d->dcf_status == DCF_STATUS_SAVED){ //如果dcf状态为保存状态则执行下面语句
// printf(“DCF_STATUS_SAVED \n”);
if(getWriteResultNetworkDict (d, nodeId, &abortCode) != SDO_FINISHED)
goto dcferror; //如果SDO未完成则跳去dcf error
masterSendNMTstateChange (d, nodeId, NMT_Reset_Node); //发送nmt命令重置网络节点
d->dcf_status = DCF_STATUS_INIT; //改变dcf状态为初始状态
d->NMTable[nodeId] = Unknown_state; //设置nmt状态为未知状态
}
return;
dcferror:
MSG_ERR(0x1A01, “SDO error in consise DCF”, abortCode);
MSG_WAR(0x2A02, "server node : ", nodeId);
d->NMTable[nodeId] = Unknown_state; //设置nmt状态为未知状态
}
//初始化简洁dcf
UNS8 init_consise_dcf(CO_Data* d,UNS8 nodeId)
{
/* Fetch DCF OD entry /
UNS32 errorCode;
ODCallback_t Callback;
UNS8 dcf;
d->dcf_odentry = (d->scanIndexOD)(0x1F22, &errorCode, &Callback); //调用函数指针并返回对象字典入口地址
/ If DCF entry do not exist… Nothing to do./
if (errorCode != OD_SUCCESSFUL) goto DCF_finish; //设备配置文件入口不存在则进行强制跳转
/* Fix DCF table overflow /
if(nodeId > d->dcf_odentry->bSubCount) goto DCF_finish; //设备配置文件表溢出则进行强制跳转
/ If DCF empty… Nothing to do /
if(! d->dcf_odentry->pSubindex[nodeId].size) goto DCF_finish; //子索引长度为0则进行强制跳转
dcf = (UNS8)d->dcf_odentry->pSubindex[nodeId].pObject; //初始化设备配置文件指针
// printf("%.2x %.2x %.2x %.2x\n",dcf[0],dcf[1],dcf[2],dcf[3]);
d->dcf_cursor = dcf + 4; //设备配置文件光标偏移 4
d->dcf_entries_count = 0; //设备配置文件入口计数置0
d->dcf_status = DCF_STATUS_INIT; //设备配置文件状态改初始化
return 1;
DCF_finish:
return 0;
}
//获取 下一个设备配置文件数据
UNS8 get_next_DCF_data(CO_Data* d, dcf_entry_t dcf_entry, UNS8 nodeId)
{
UNS8 dcfend;
UNS32 nb_entries;
UNS32 szData;
UNS8* dcf;
if(!d->dcf_odentry)
return 0; //设备配置文件入口地址不存在退出
if(nodeId > d->dcf_odentry->bSubCount)
return 0; //设备配置文件计数溢出则退出
szData = d->dcf_odentry->pSubindex[nodeId].size; //读取子索引长度
dcf = (UNS8*)d->dcf_odentry->pSubindex[nodeId].pObject; //初始化设备配置文件指针
nb_entries = UNS32_LE(((UNS32)dcf)); //
dcfend = dcf + szData; //计算设备配置文件结束
if((UNS8*)d->dcf_cursor + 7 < (UNS8*)dcfend && d->dcf_entries_count < nb_entries){ //判断设备配置文件指针和计数正确
/* DCF data may not be 32/16b aligned,
* we cannot directly dereference d->dcf_cursor
* as UNS16 or UNS32
* Do it byte per byte taking care on endianess*/
#ifdef CANOPEN_BIG_ENDIAN
dcf_entry->Index = *(d->dcf_cursor++) << 8 |
*(d->dcf_cursor++);
#else
memcpy(&dcf_entry->Index, d->dcf_cursor,2);
d->dcf_cursor+=2; //复制设备配置文件光标到入口索引并将光标+2
#endif
dcf_entry->Subindex = *(d->dcf_cursor++); //给子索引赋值
#ifdef CANOPEN_BIG_ENDIAN
dcf_entry->Size = *(d->dcf_cursor++) << 24 | //
*(d->dcf_cursor++) << 16 |
*(d->dcf_cursor++) << 8 |
*(d->dcf_cursor++);
#else
memcpy(&dcf_entry->Size, d->dcf_cursor,4);
d->dcf_cursor+=4;
#endif
d->dcf_data = dcf_entry->Data = d->dcf_cursor; //对设备配置文件数据进行赋值
d->dcf_size = dcf_entry->Size; //设备配置文件长度
d->dcf_cursor += dcf_entry->Size; //设备配置文件光标偏移一个文件长度
d->dcf_entries_count++; //设备配置文件入口计数加一
return 1;
}
return 0;
}
//写简洁设备配置文件下一入口
static UNS8 write_consise_dcf_next_entry(CO_Data* d, UNS8 nodeId)
{
UNS8 Ret;
dcf_entry_t dcf_entry;
if(!get_next_DCF_data(d, &dcf_entry, nodeId))
return 0; //获取下一设备配置文件数据失败则退出
Ret = writeNetworkDictCallBackAI(d, /* CO_Data* d*/ //写网络字典
nodeId, /* UNS8 nodeId*/
dcf_entry.Index, /* UNS16 index*/
dcf_entry.Subindex, /* UNS8 subindex*/
(UNS8)dcf_entry.Size, /* UNS8 count*/
0, /* UNS8 dataType*/
dcf_entry.Data,/* void data/
CheckSDOAndContinue,/* Callback*/
0, /* no endianize*/
0); /* no block mode */
if(Ret)
MSG_ERR(0x1A02,“Erreur writeNetworkDictCallBackAI”,Ret);
return 1;
}
//读简洁设备配置文件下一入口
static UNS8 read_consise_dcf_next_entry(CO_Data* d, UNS8 nodeId)
{
UNS8 Ret;
dcf_entry_t dcf_entry;
if(!get_next_DCF_data(d, &dcf_entry, nodeId)) //获取下一设备配置文件数据失败则退出
return 0;
Ret = readNetworkDictCallbackAI(d, /* CO_Data* d*/ //读网络字典
nodeId, /* UNS8 nodeId*/
dcf_entry.Index, /* UNS16 index*/
dcf_entry.Subindex, /* UNS8 subindex*/
0, /* UNS8 dataType*/
CheckSDOAndContinue,/* Callback*/
0); /* no block mode */
if(Ret)
MSG_ERR(0x1A03,“Erreur readNetworkDictCallbackAI”,Ret);
return 1;
}
//保存节点
void SaveNode(CO_Data* d, UNS8 nodeId)
{
UNS8 Ret;
UNS32 data=0x65766173;
Ret = writeNetworkDictCallBackAI(d, /* CO_Data* d*/ //写网络字典
nodeId, /* UNS8 nodeId*/
0x1010, /* UNS16 index*/
1, /* UNS8 subindex*/
4, /* UNS8 count*/
0, /* UNS8 dataType*/
(void )&data,/ void data/
CheckSDOAndContinue,/* Callback*/
0, /* no endianize*/
0); /* no block mode */
if(Ret)
MSG_ERR(0x1A04,“Erreur writeNetworkDictCallBackAI”,Ret);
}