CANOpen数据存档文件

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 16:20   2154   0

数据存档文件,用于保存所有从节点的字典配置。

在从节点初始化时,从节点将上报boot_up报文。主节点收到boot_up报文后,将对从节点的字典和数据存档文件进行对比,如果不匹配,则需要通过sdo报文对从节点字典进行重新配置,并根据配置决定是否命令从节点将新的配置存入非易失性存储器。

主站可以为每个从站配置一个节点数据存档文件,节点数据存档文件的格式如图:


/* DCF入口 */
typedef struct 
{
 UNS16 Index;  //索引
 UNS8 Subindex; //子索引
 UNS32 Size;   //字节数
 UNS8 *Data;   //数据指针
}dcf_entry_t;

void SaveNode(CO_Data *d, UNS8 nodeId);
static UNS8 read_consise_dcf_next_entry(CO_Data *d, UNS8 nodeId);
static UNS8 write_consise_dcf_next_entry(CO_Data *d, UNS8 nodeId);
UNS8 init_consise_dcf(CO_Data *d,UNS8 nodeId);

#ifdef _MSC_VER
#define inline _inline
#endif

/* 启动节点 */
void start_node(CO_Data *d, UNS8 nodeId)
{
 /* 节点开始运行 */
 masterSendNMTstateChange(d, nodeId, NMT_Start_Node);
 /* 节点进入运行状态 */
 d->NMTable[nodeId] = Operational;
}

/* 该函数被post_SlaveBootup函数调用,检查是否要获取数据存档文件并启动节点 */
UNS8 check_and_start_node(CO_Data *d, UNS8 nodeId)
{
 /* 如果该节点的数据存档文件正在初始化,则直接退出 */
 if(d->dcf_status != DCF_STATUS_INIT)
  return 0;

 /* 初始化节点nodeId的数据存档文件,并读取该节点的数据存档文件中配置的所有条目的数据 */
 if((init_consise_dcf(d, nodeId) == 0) || (read_consise_dcf_next_entry(d, nodeId) == 0))
 {
  /* 如果没有配置该节点数据存档文件,则直接启动该节点 */
  start_node(d, nodeId);

  return 1;
 }
 /* 开始读取该节点的数据存档文件后,将状态设置为读取检查 */
 d->dcf_status = DCF_STATUS_READ_CHECK;

 return 2;
}

/* 启动该节点并检查是否有节点还未进入运行态 */
void start_and_seek_node(CO_Data *d, UNS8 nodeId)
{
  UNS8 node;
  
 /* 启动该节点 */
 start_node(d, nodeId);
 
 /* 检查是否有节点还未进入运行态,如果有则检查是否要获取数据存档文件并启动节点 */
 for(node = 0; node < NMT_MAX_NODE_ID; node++)
 {
  if(d->NMTable[node] != Initialisation)
   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;
 UNS32 size = 4;
 
 /* 如果状态为读取检查,说明已经开始读取 */
 if(d->dcf_status == DCF_STATUS_READ_CHECK)
 {
  /* 获取sdo读取到的结果 */
  if(getReadResultNetworkDict(d, nodeId, buf, &size, &abortCode) != SDO_FINISHED)
   goto dcferror;
  
  /* 检查读取到的大小和本地配置的是否匹配 */
  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)
   {
    /* 开始并检查节点 */
    start_and_seek_node(d, nodeId);
   }
  }
  /* 如果读取的数据存档文件和配置的数据存档文件不匹配,则将配置数据存档文件写到节点字典中 */
  else 
  {
   /* 初始化节点nodeId的数据存档文件,写数据存档指针指向的条目数据并将指针偏移到下一个条目 */
   if((init_consise_dcf(d, nodeId) == 0) || (write_consise_dcf_next_entry(d, nodeId) == 0))
    goto dcferror;                
   
   /* 将状态配置为写 */
   d->dcf_status = DCF_STATUS_WRITE;
  }
 }
 /* 如果状态为写 */
 else if(d->dcf_status == DCF_STATUS_WRITE)
 {
  /* 检查写字典结果是否成功 */
  if(getWriteResultNetworkDict(d, nodeId, &abortCode) != SDO_FINISHED)
   goto dcferror;
  
  /* 写该节点数据存档文件中指针指向的条目的数据,并将指针偏移到该节点配置的下一个条目 */
  if(write_consise_dcf_next_entry(d, nodeId) == 0)
  {
#ifdef DCF_SAVE_NODE
   /* 所有条目都写完,通知从站保存字典到非易失性存储器 */
   SaveNode(d, nodeId);
   /* 将状态设置为保存 */
   d->dcf_status = DCF_STATUS_SAVED;
#else
   /* 所有条目都写完,将状态设置为初始化 */
   d->dcf_status = DCF_STATUS_INIT;
   /* 启动该节点并检查是否有其它节点还未进入运行态,如果有则检查是否要获取数据存档文件并启动其它节点 */
   start_c@RI]
N]\NB:`&.f9ke,:gg$)9fj
SJ]H
SRY
BS]S]H	N
MM]	N]S]XXRJRYLLK


I[\]KX[YK
NY]
HTPL
	]\]S]XXRI]
NBOO
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP