小记——基于STM32F103平台的canfestival移植

一、准备工作

1、源码下载

        canfestival源码下载地址:

https://hg.beremiz.org/canfestival/archive/tip.zip

         下表为源码各文件目录说明:

文件路径说明
/src与处理器无关的canopen协议栈标准源代码
/include针对各处理器的头文件
/driver针对各硬件的驱动
/examples测试程序
/objdictgen带有图形界面的对象字典编辑器
/doc说明文档

2、基于stm32F103平台的基础工程

        我自己是基于f103平台开发的,这里就不详细说明了。

3、测试工具

        can分析仪及上位机软件。

二、源码移植

1、工程目录

        在自己的工程目录下面创建Canfestival文件夹用来存放源码相关文件,文件目录参考如下。

2、源码文件移植

        a)下载完的源码解压后,将src文件夹下面所有源文件(除红框圈定外)复制到我们自己基础工程的Festival/Src目录下。

        b) 将源码目录中include文件夹下所有被红框圈中的头文件,复制到我们自己基础工程的Festival/Inc目录下。

        c)将源码目录中include/AVR文件夹下applicfg.h、config.h、timescfg.h总共三个头文件,复制到我们自己基础工程的Festival/Inc/stm目录下。

        d)源码目录中include/AVR文件夹下还有一个canfestival.h的头文件也需要,我这里把这个文件放到我自己工程目录下的Festival/driver目录下了,这个目录的内容后面再说。

        至此,我们所有关于canfestival源码移植的文件操作已经完成了,接下来就是对源码文件中具体代码内容的修改和添加了,后面也是在我们自己的基础工程中进行。

3、源码修改

        a)在config.h中文件中将如下被红框圈的部分注释掉,消除编译报错。

        b) 在timerscfg.h中有三个宏的定义需要注意,分别是TIMEVAL_MAX、MS_TO_TIMEVAL和US_TO_TIMEVAL, 我下载的源码里面宏定义如下。

       TIMEVAL_MAX和你定时器的重载值有关系。

        MS_TO_TIMEVAL和US_TO_TIMEVAL我在这里把单位改成10us了,如下图所示。这个需要和自己定时器频率对应,当然也可以根据这个宏去定义自己的定时器。

        

        c)在Canfestival/driver目录下新建canfestival.c文件,在文件包含头文件canfestival.h,并定义如下函数。可以先定义成空函数,等到编译都通过了之后,再往里面添加内容,这几个函数都是定义来供canfestival源码调用的,如果找不到这几个函数编译会报错。

        ·setTimer是用户层提供给源码用来更新硬件定时器重载值的,用于模拟canopen中各个软件定时器,如PDO周期发送或SDO超时检测。

        ·getElapsedTime是用户层提供给源码用来查询定时器事件触发的时间差。

        ·cansend是用户层提供给源码发送can数据包的接口。

void setTimer(TIMEVAL value)
{
	halTime_setTimer(value);
}

TIMEVAL getElapsedTime(void)
{
	return halTime_getElapsedTime();
}

UNS8 canSend(CAN_PORT notused, Message *m)
{
	uint8_t isRemote = 0;
	uint8_t ret = 0;
	if(m->rtr)
		isRemote = CAN_RTR_REMOTE;
	else
		isRemote = CAN_RTR_DATA;
	ret =  halCan_write(m->cob_id, isRemote , m->data , m->len);
	return ret;
}

        d)调试阶段如果想输出源码的打印信息,可以在applicfg.h文件中打开如下宏定义即可通过串口输出源码的日志信息。

 

        e)其它记不太清还有什么修改的了,时间有点久了,反正编译报错的问题逐个解决就行了。

三、底层驱动适配

1、hal库can驱动

        a)hal库实现can底层驱动初始化

int MX_CAN_Init(uint8_t nodeID, E_CAN_BAUDRATE rate)
{

    /* USER CODE BEGIN CAN_Init 0 */
	HAL_StatusTypeDef HAL_Status = HAL_OK;
	CAN_FilterTypeDef hCAN_Filter;
    /* USER CODE END CAN_Init 0 */

    /* USER CODE BEGIN CAN_Init 1 */

    /* USER CODE END CAN_Init 1 */
    hcan.Instance = CAN1;
    hcan.Init.Mode = CAN_MODE_NORMAL;
    hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
	//baudrate=APB1Clock/((1+bs1+bs2)*Prescaler)
	switch(rate)
	{
	case BAUDRATE_125K:
		hcan.Init.Prescaler = 18;
		hcan.Init.TimeSeg1 = CAN_BS1_13TQ;
		hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
		break;
	case BAUDRATE_250K:
		hcan.Init.Prescaler = 12;
		hcan.Init.TimeSeg1 = CAN_BS1_9TQ;
		hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
		break;
	case BAUDRATE_500K:
		hcan.Init.Prescaler = 8;
		hcan.Init.TimeSeg1 = CAN_BS1_7TQ;
		hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
		break;
	default://500k
		hcan.Init.Prescaler = 8;
		hcan.Init.TimeSeg1 = CAN_BS1_7TQ;
		hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
		break;
	}
    hcan.Init.TimeTriggeredMode = DISABLE;
    hcan.Init.AutoBusOff = DISABLE;
    hcan.Init.AutoWakeUp = DISABLE;
    hcan.Init.AutoRetransmission = DISABLE;
    hcan.Init.ReceiveFifoLocked = DISABLE;
    hcan.Init.TransmitFifoPriority = DISABLE;
    HAL_Status |= HAL_CAN_Init(&hcan);
    /* USER CODE BEGIN CAN_Init 2 */

    fifo_init(&canRcvFifo, CANRCV_FIFOSIZE);
    /* USER CODE END CAN_Init 2 */

    uint16_t canFilterListStdId1 = 0x600 + nodeID; //SDO
    uint8_t canFilterListRTR1 = 0;

    uint16_t canFilterListStdId2 = 0x80; //sync
    uint8_t canFilterListRTR2 = 0;

    uint16_t canFilterListStdId3 = 0x700 + nodeID; //nmt
    uint8_t canFilterListRTR3 = 1;

    uint16_t canFilterListStdId4 = 0x0; //nmt
    uint8_t canFilterListRTR4 = 0;

	hCAN_Filter.FilterBank = 0;
	hCAN_Filter.FilterMode = CAN_FILTERMODE_IDLIST;
	hCAN_Filter.FilterScale = CAN_FILTERSCALE_16BIT;
	hCAN_Filter.FilterIdHigh = ((canFilterListStdId1 << 5) | (canFilterListRTR1 << 4));
	hCAN_Filter.FilterIdLow = ((canFilterListStdId2 << 5) | (canFilterListRTR2 << 4));;
	hCAN_Filter.FilterMaskIdHigh = ((canFilterListStdId3 << 5) | (canFilterListRTR3 << 4));;
	hCAN_Filter.FilterMaskIdLow = ((canFilterListStdId4 << 5) | (canFilterListRTR4 << 4));;
	hCAN_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
	hCAN_Filter.FilterActivation = ENABLE;
	hCAN_Filter.SlaveStartFilterBank = 0;
    HAL_Status |= HAL_CAN_ConfigFilter(&hcan, &hCAN_Filter);

    uint16_t canFilterListStdId5 = 0x200 + nodeID; //PDO1
    uint8_t canFilterListRTR5 = 0;

    uint16_t canFilterListStdId6 = 0x300 + nodeID; //PDO2
    uint8_t canFilterListRTR6 = 0;

    uint16_t canFilterListStdId7 = 0x400 + nodeID; //PDO3
    uint8_t canFilterListRTR7 = 1;

    uint16_t canFilterListStdId8 = 0x500 + nodeID; //PDO4
    uint8_t canFilterListRTR8 = 0;
	hCAN_Filter.FilterBank = 1;
	hCAN_Filter.FilterMode = CAN_FILTERMODE_IDLIST;
	hCAN_Filter.FilterScale = CAN_FILTERSCALE_16BIT;
	hCAN_Filter.FilterIdHigh = ((canFilterListStdId5 << 5) | (canFilterListRTR5 << 4));
	hCAN_Filter.FilterIdLow = ((canFilterListStdId6 << 5) | (canFilterListRTR6 << 4));;
	hCAN_Filter.FilterMaskIdHigh = ((canFilterListStdId7 << 5) | (canFilterListRTR7 << 4));;
	hCAN_Filter.FilterMaskIdLow = ((canFilterListStdId8 << 5) | (canFilterListRTR8 << 4));;
	hCAN_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
	hCAN_Filter.FilterActivation = ENABLE;
	hCAN_Filter.SlaveStartFilterBank = 0;
    HAL_Status |= HAL_CAN_ConfigFilter(&hcan, &hCAN_Filter);
    /*-3- 启动CAN ---------------------------------------------------*/
	HAL_Status |= HAL_CAN_Start(&hcan);

    /*-4- 使能中断通知 ----------------------------------------------*/
    HAL_Status = HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
	if(HAL_Status != HAL_OK)
	{
		printf("halCan init fail\r\n");
	}
	return 0;
}

        b)can接收中断及回调函数(candispatch是源码中一个非常重要的函数,供用户层调用,此函数主要就是来解析收到各种不同类型的不同报文帧,然后根据canopen协议进行解析和处理)

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    uint8_t aRxData[8];
    struct CAN_MSG_S msg;
	CAN_RxHeaderTypeDef RxHeader;
    if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, aRxData) == HAL_OK)
    {
//    	printf("halCan receive a msg successfully\r\n");
    	if (RxHeader.IDE == CAN_ID_EXT)
    	{
    		return;
    	}
    	if (RxHeader.RTR)
    	{
    		msg.isRemote = 1;
    	}
    	else
    	{
    		msg.isRemote = 0;
    	}
        msg.cobId = RxHeader.StdId;
        msg.len = RxHeader.DLC;
        memcpy(msg.data, aRxData, sizeof(aRxData));
        canDispatch(&slaveTest_Data, &msg); //slaveTest_Data后面再说
    }
}

         c)can发送函数halCan_write实现如下:

int halCan_write(uint16_t cobeId, uint8_t isRemote, uint8_t* aTxData, uint8_t len)
{
	CAN_TxHeaderTypeDef TxHeader;
    uint32_t Tx_MailBox;
    TxHeader.StdId = cobeId;
    TxHeader.ExtId = 0;
    if (isRemote)
    {
        TxHeader.RTR = CAN_RTR_REMOTE;
    }
    else
    {
        TxHeader.RTR = CAN_RTR_DATA;
    }
    TxHeader.IDE = CAN_ID_STD;
    TxHeader.DLC = len;
    TxHeader.TransmitGlobalTime = ENABLE;
    if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, &aTxData[0], &Tx_MailBox) != HAL_OK)
    {
    	printf("halCan transmit Failed!!!\r\n");
    	return 1;
    }
	return 0;
}

 2、hal库定时器驱动

        熟悉canopen的都知道(可能也有人不熟悉)。。哈哈。由于canopen里面如同步信号、心跳报文或SDO超时信号等需要一系列定时信号来提醒系统进行这些工作,所以CANopen节点必须得有定时功能。CanFestival在timer.c中执行了一个微型调度程序,他需要使用一个定时器使该调度建立并管理一个警报表,并且在规定的时间发出信号。所以使用Canfestival需要开启一个硬件定时器,通过设置不同的定时时间来产生定时任务,实现不同时间事件的管理。我这里用的Tim3。

         a)定时器初始化,我的F103时钟是72MHZ,时钟基数需要和上述对应设置为10us,所以这里分频系数设置为720-1,TIM3_PERIOD为65536。

void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */
  HAL_StatusTypeDef HAL_Status = HAL_OK;
  /* USER CODE END TIM3_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 720 - 1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = TIM3_PERIOD - 1;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  HAL_Status |= HAL_TIM_Base_Init(&htim3);

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  HAL_Status |= HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_Status |= HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);

  /* USER CODE BEGIN TIM3_Init 2 */
  if(HAL_Status != HAL_OK)
  {
    printf("halTim8 init fail\r\n");
  }
  /* USER CODE END TIM3_Init 2 */

}

         b)定时器中断及回调函数实现(定时器中断回调函数中需要调用TimeDispatch,canfestival里面起这个timer机制有时间结合源码再来详解)

/**
  * @brief This function handles TIM3 global interrupt.
  */
void TIM3_IRQHandler(void)
{
  /* USER CODE BEGIN TIM3_IRQn 0 */

  /* USER CODE END TIM3_IRQn 0 */
  HAL_TIM_IRQHandler(&htim3);
  /* USER CODE BEGIN TIM3_IRQn 1 */

  /* USER CODE END TIM3_IRQn 1 */
}
static uint32_t last_counter_val = 0;
static uint32_t elapsed_time = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM3)
    {
    	last_counter_val = 0;
    	elapsed_time = 0;
    	TimeDispatch();
    }
}

        c)halTime_setTimer函数实现如下

void halTime_setTimer(uint32_t value)
{
  	uint32_t timer =  __HAL_TIM_GET_COUNTER(&htim3);
	elapsed_time += timer - last_counter_val;
    last_counter_val = TIM3_PERIOD - value;
    __HAL_TIM_SET_COUNTER(&htim3, TIM3_PERIOD - value);
    HAL_TIM_Base_Start_IT(&htim3);
}

         d)halTime_getElapsedTime函数实现如下

uint32_t halTime_getElapsedTime(void)
{
    uint32_t timer = __HAL_TIM_GET_COUNTER(&htim3);

    if(timer < last_counter_val)
    {
        timer += TIM3_PERIOD;
    }

    uint32_t elapsed = timer - last_counter_val + elapsed_time;
    return elapsed;
}

四、字典工具

1、环境搭建

        对象字典工具的搭建可以参考Canfestival源码中的手册(manual_en.pdf),文件在objdictgen/doc文件下面,具体位置在3.1.1节。

        其中Python和wxPython的安装包需要自己在网上下载,Gnosix在canfestival源码包中已经提供,在objdictgen文件目录下。

a) 安装python

        我安装的是python-2.7.15.amd64,网上其它帖子我看说python3可能有问题,我没有测试。

        Python的安装需要注意两点:1.以管理员身份运行; 2.添加(环境变量)路径。

b)安装wxPython

        我下载版本的是wxPython3.0-win64-3.0.2.0-py27,

 下载链接:https://sourceforge.net/projects/wxpython/files/wxPython/3.0.2.0/

c)安装gnosis 

         将 Gnosis_Utils-current.tar压缩包解压,后 在 Gnosis_Utils-current\Gnosis_Utils-1.2.2中 有个 gnosis文件夹,将其拷贝 ,复制到objdictgen目录中即可。

 

d)环境验证

        在canfestival源码路径中到odjdictgen文件下,双击objdictedit.py文件,出现以下界面就可以了。

2、建立词典

        我这里测试的是建立的是一个支持ds-401协议(canopen协议栈中针对一般IO设备的子协议)的从站节点,在profile栏选择DS-401,具体的子协议根据自己需求来选择。

        根据canopen标准对象字典分段,在指定区段添加自己的对象字典。 

​        这里我在通信参数区段添加了一个心跳(0x1017-00),心跳周期为100ms。节点会以固定的设置频率来周期性发送当前节点状态。

        标准设备子协议区段,因为前面我选择的是DS-401(通用IO设备自协议) ,这里添加两个对象字典分别是0x6000-01和0x6200-01(关于有写权限的对象字典这里补充一点,在添加对象字典时可以把有回访的选项框勾选上,这样可以在用户代码层通过RegisterSetODentryCallBack接口注册相关对象字典的回调函数,当该对象字典数据被其它节点通过PDO或者SDO写入时,可以直接通过回调函数实现用户层的代码逻辑)。

​ 

        接下来是PDO映射,TPDO1(相对于自己的节点)这里映射的是0x6000-01,发送节点读取的输入信号状态。

         TPDO1通讯参数设置,cob-ID不用修改(如果不用当前PDO可以把cob-ID的最高置1),传输方式配置为异步传输,禁止时间为10ms,异步传输周期为100ms。

        RPDO1 映射对象字典0x6200-01,接收需要节点去设置的输出信号状态。

         所有配置设置完成后,就可以在菜单栏——文件下拉选项中生成EDS文件和词典了。这里贴一下生成slaveTest.h和salveTest.c(这两个文件也需要放到我们的工程里面,可以放在Festival/driver目录下)。


/* File generated by gen_cfile.py. Should not be modified. */

#ifndef SLAVETEST_H
#define SLAVETEST_H

#include "data.h"

/* Prototypes of function provided by object dictionnary */
UNS32 slaveTest_valueRangeTest (UNS8 typeValue, void * value);
const indextable * slaveTest_scanIndexOD (UNS16 wIndex, UNS32 * errorCode, ODCallback_t **callbacks);

/* Master node data struct */
extern CO_Data slaveTest_Data;
extern UNS8 Read_Inputs_8_Bit[1];		/* Mapped at index 0x6000, subindex 0x01 - 0x01 */
extern UNS8 Write_Outputs_8_Bit[1];		/* Mapped at index 0x6200, subindex 0x01 - 0x01 */

#endif // SLAVETEST_H

/* File generated by gen_cfile.py. Should not be modified. */

#include "slaveTest.h"

/**************************************************************************/
/* Declaration of mapped variables                                        */
/**************************************************************************/
UNS8 Read_Inputs_8_Bit[] =		/* Mapped at index 0x6000, subindex 0x01 - 0x01 */
  {
    0x0	/* 0 */
  };
UNS8 Write_Outputs_8_Bit[] =		/* Mapped at index 0x6200, subindex 0x01 - 0x01 */
  {
    0x0	/* 0 */
  };

/**************************************************************************/
/* Declaration of value range types                                       */
/**************************************************************************/

#define valueRange_EMC 0x9F /* Type for index 0x1003 subindex 0x00 (only set of value 0 is possible) */
UNS32 slaveTest_valueRangeTest (UNS8 typeValue, void * value)
{
  switch (typeValue) {
    case valueRange_EMC:
      if (*(UNS8*)value != (UNS8)0) return OD_VALUE_RANGE_EXCEEDED;
      break;
  }
  return 0;
}

/**************************************************************************/
/* The node id                                                            */
/**************************************************************************/
/* node_id default value.*/
UNS8 slaveTest_bDeviceNodeId = 0x00;

/**************************************************************************/
/* Array of message processing information */

const UNS8 slaveTest_iam_a_slave = 1;

TIMER_HANDLE slaveTest_heartBeatTimers[1];

/*
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

                               OBJECT DICTIONARY

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
*/

/* index 0x1000 :   Device Type. */
                    UNS32 slaveTest_obj1000 = 0x0;	/* 0 */
                    subindex slaveTest_Index1000[] = 
                     {
                       { RO, uint32, sizeof (UNS32), (void*)&slaveTest_obj1000 }
                     };

/* index 0x1001 :   Error Register. */
                    UNS8 slaveTest_obj1001 = 0x0;	/* 0 */
                    subindex slaveTest_Index1001[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_obj1001 }
                     };

/* index 0x1003 :   Pre-defined Error Field */
                    UNS8 slaveTest_highestSubIndex_obj1003 = 0; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1003[] = 
                    {
                      0x0	/* 0 */
                    };
                    ODCallback_t slaveTest_Index1003_callbacks[] = 
                     {
                       NULL,
                       NULL,
                     };
                    subindex slaveTest_Index1003[] = 
                     {
                       { RW, valueRange_EMC, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1003 },
                       { RO, uint32, sizeof (UNS32), (void*)&slaveTest_obj1003[0] }
                     };

/* index 0x1005 :   SYNC COB ID. */
                    UNS32 slaveTest_obj1005 = 0x0;	/* 0 */
                    ODCallback_t slaveTest_Index1005_callbacks[] = 
                     {
                       NULL,
                     };
                    subindex slaveTest_Index1005[] = 
                     {
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1005 }
                     };

/* index 0x1006 :   Communication / Cycle Period. */
                    UNS32 slaveTest_obj1006 = 0x0;	/* 0 */
                    ODCallback_t slaveTest_Index1006_callbacks[] = 
                     {
                       NULL,
                     };
                    subindex slaveTest_Index1006[] = 
                     {
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1006 }
                     };

/* index 0x100C :   Guard Time */ 
                    UNS16 slaveTest_obj100C = 0x0;   /* 0 */

/* index 0x100D :   Life Time Factor */ 
                    UNS8 slaveTest_obj100D = 0x0;   /* 0 */

/* index 0x1014 :   Emergency COB ID. */
                    UNS32 slaveTest_obj1014 = 0x80;	/* 128 */
                    subindex slaveTest_Index1014[] = 
                     {
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1014 }
                     };

/* index 0x1016 :   Consumer Heartbeat Time */
                    UNS8 slaveTest_highestSubIndex_obj1016 = 0;
                    UNS32 slaveTest_obj1016[]={0};

/* index 0x1017 :   Producer Heartbeat Time. */
                    UNS16 slaveTest_obj1017 = 0x64;	/* 100 */
                    ODCallback_t slaveTest_Index1017_callbacks[] = 
                     {
                       NULL,
                     };
                    subindex slaveTest_Index1017[] = 
                     {
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1017 }
                     };

/* index 0x1018 :   Identity. */
                    UNS8 slaveTest_highestSubIndex_obj1018 = 4; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1018_Vendor_ID = 0x0;	/* 0 */
                    UNS32 slaveTest_obj1018_Product_Code = 0x0;	/* 0 */
                    UNS32 slaveTest_obj1018_Revision_Number = 0x0;	/* 0 */
                    UNS32 slaveTest_obj1018_Serial_Number = 0x0;	/* 0 */
                    subindex slaveTest_Index1018[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1018 },
                       { RO, uint32, sizeof (UNS32), (void*)&slaveTest_obj1018_Vendor_ID },
                       { RO, uint32, sizeof (UNS32), (void*)&slaveTest_obj1018_Product_Code },
                       { RO, uint32, sizeof (UNS32), (void*)&slaveTest_obj1018_Revision_Number },
                       { RO, uint32, sizeof (UNS32), (void*)&slaveTest_obj1018_Serial_Number }
                     };

/* index 0x1200 :   Server SDO Parameter. */
                    UNS8 slaveTest_highestSubIndex_obj1200 = 2; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1200_COB_ID_Client_to_Server_Receive_SDO = 0x600;	/* 1536 */
                    UNS32 slaveTest_obj1200_COB_ID_Server_to_Client_Transmit_SDO = 0x580;	/* 1408 */
                    subindex slaveTest_Index1200[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1200 },
                       { RO, uint32, sizeof (UNS32), (void*)&slaveTest_obj1200_COB_ID_Client_to_Server_Receive_SDO },
                       { RO, uint32, sizeof (UNS32), (void*)&slaveTest_obj1200_COB_ID_Server_to_Client_Transmit_SDO }
                     };

/* index 0x1400 :   Receive PDO 1 Parameter. */
                    UNS8 slaveTest_highestSubIndex_obj1400 = 6; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1400_COB_ID_used_by_PDO = 0x200;	/* 512 */
                    UNS8 slaveTest_obj1400_Transmission_Type = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1400_Inhibit_Time = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1400_Compatibility_Entry = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1400_Event_Timer = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1400_SYNC_start_value = 0x0;	/* 0 */
                    subindex slaveTest_Index1400[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1400 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1400_COB_ID_used_by_PDO },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1400_Transmission_Type },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1400_Inhibit_Time },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1400_Compatibility_Entry },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1400_Event_Timer },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1400_SYNC_start_value }
                     };

/* index 0x1401 :   Receive PDO 2 Parameter. */
                    UNS8 slaveTest_highestSubIndex_obj1401 = 6; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1401_COB_ID_used_by_PDO = 0x300;	/* 768 */
                    UNS8 slaveTest_obj1401_Transmission_Type = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1401_Inhibit_Time = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1401_Compatibility_Entry = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1401_Event_Timer = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1401_SYNC_start_value = 0x0;	/* 0 */
                    subindex slaveTest_Index1401[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1401 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1401_COB_ID_used_by_PDO },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1401_Transmission_Type },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1401_Inhibit_Time },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1401_Compatibility_Entry },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1401_Event_Timer },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1401_SYNC_start_value }
                     };

/* index 0x1402 :   Receive PDO 3 Parameter. */
                    UNS8 slaveTest_highestSubIndex_obj1402 = 6; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1402_COB_ID_used_by_PDO = 0x400;	/* 1024 */
                    UNS8 slaveTest_obj1402_Transmission_Type = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1402_Inhibit_Time = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1402_Compatibility_Entry = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1402_Event_Timer = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1402_SYNC_start_value = 0x0;	/* 0 */
                    subindex slaveTest_Index1402[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1402 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1402_COB_ID_used_by_PDO },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1402_Transmission_Type },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1402_Inhibit_Time },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1402_Compatibility_Entry },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1402_Event_Timer },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1402_SYNC_start_value }
                     };

/* index 0x1403 :   Receive PDO 4 Parameter. */
                    UNS8 slaveTest_highestSubIndex_obj1403 = 6; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1403_COB_ID_used_by_PDO = 0x500;	/* 1280 */
                    UNS8 slaveTest_obj1403_Transmission_Type = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1403_Inhibit_Time = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1403_Compatibility_Entry = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1403_Event_Timer = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1403_SYNC_start_value = 0x0;	/* 0 */
                    subindex slaveTest_Index1403[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1403 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1403_COB_ID_used_by_PDO },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1403_Transmission_Type },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1403_Inhibit_Time },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1403_Compatibility_Entry },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1403_Event_Timer },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1403_SYNC_start_value }
                     };

/* index 0x1600 :   Receive PDO 1 Mapping. */
                    UNS8 slaveTest_highestSubIndex_obj1600 = 8; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1600[] = 
                    {
                      0x62000108,	/* 1644167432 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0	/* 0 */
                    };
                    subindex slaveTest_Index1600[] = 
                     {
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1600 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1600[0] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1600[1] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1600[2] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1600[3] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1600[4] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1600[5] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1600[6] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1600[7] }
                     };

/* index 0x1601 :   Receive PDO 2 Mapping. */
                    UNS8 slaveTest_highestSubIndex_obj1601 = 8; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1601[] = 
                    {
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0	/* 0 */
                    };
                    subindex slaveTest_Index1601[] = 
                     {
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1601 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1601[0] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1601[1] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1601[2] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1601[3] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1601[4] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1601[5] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1601[6] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1601[7] }
                     };

/* index 0x1602 :   Receive PDO 3 Mapping. */
                    UNS8 slaveTest_highestSubIndex_obj1602 = 8; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1602[] = 
                    {
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0	/* 0 */
                    };
                    subindex slaveTest_Index1602[] = 
                     {
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1602 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1602[0] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1602[1] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1602[2] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1602[3] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1602[4] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1602[5] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1602[6] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1602[7] }
                     };

/* index 0x1603 :   Receive PDO 4 Mapping. */
                    UNS8 slaveTest_highestSubIndex_obj1603 = 8; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1603[] = 
                    {
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0	/* 0 */
                    };
                    subindex slaveTest_Index1603[] = 
                     {
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1603 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1603[0] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1603[1] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1603[2] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1603[3] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1603[4] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1603[5] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1603[6] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1603[7] }
                     };

/* index 0x1800 :   Transmit PDO 1 Parameter. */
                    UNS8 slaveTest_highestSubIndex_obj1800 = 6; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1800_COB_ID_used_by_PDO = 0x180;	/* 384 */
                    UNS8 slaveTest_obj1800_Transmission_Type = 0xFF;	/* 255 */
                    UNS16 slaveTest_obj1800_Inhibit_Time = 0xA;	/* 10 */
                    UNS8 slaveTest_obj1800_Compatibility_Entry = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1800_Event_Timer = 0x64;	/* 100 */
                    UNS8 slaveTest_obj1800_SYNC_start_value = 0x0;	/* 0 */
                    ODCallback_t slaveTest_Index1800_callbacks[] = 
                     {
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                     };
                    subindex slaveTest_Index1800[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1800 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1800_COB_ID_used_by_PDO },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1800_Transmission_Type },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1800_Inhibit_Time },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1800_Compatibility_Entry },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1800_Event_Timer },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1800_SYNC_start_value }
                     };

/* index 0x1801 :   Transmit PDO 2 Parameter. */
                    UNS8 slaveTest_highestSubIndex_obj1801 = 6; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1801_COB_ID_used_by_PDO = 0x280;	/* 640 */
                    UNS8 slaveTest_obj1801_Transmission_Type = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1801_Inhibit_Time = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1801_Compatibility_Entry = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1801_Event_Timer = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1801_SYNC_start_value = 0x0;	/* 0 */
                    ODCallback_t slaveTest_Index1801_callbacks[] = 
                     {
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                     };
                    subindex slaveTest_Index1801[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1801 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1801_COB_ID_used_by_PDO },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1801_Transmission_Type },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1801_Inhibit_Time },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1801_Compatibility_Entry },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1801_Event_Timer },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1801_SYNC_start_value }
                     };

/* index 0x1802 :   Transmit PDO 3 Parameter. */
                    UNS8 slaveTest_highestSubIndex_obj1802 = 6; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1802_COB_ID_used_by_PDO = 0x380;	/* 896 */
                    UNS8 slaveTest_obj1802_Transmission_Type = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1802_Inhibit_Time = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1802_Compatibility_Entry = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1802_Event_Timer = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1802_SYNC_start_value = 0x0;	/* 0 */
                    ODCallback_t slaveTest_Index1802_callbacks[] = 
                     {
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                     };
                    subindex slaveTest_Index1802[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1802 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1802_COB_ID_used_by_PDO },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1802_Transmission_Type },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1802_Inhibit_Time },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1802_Compatibility_Entry },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1802_Event_Timer },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1802_SYNC_start_value }
                     };

/* index 0x1803 :   Transmit PDO 4 Parameter. */
                    UNS8 slaveTest_highestSubIndex_obj1803 = 6; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1803_COB_ID_used_by_PDO = 0x480;	/* 1152 */
                    UNS8 slaveTest_obj1803_Transmission_Type = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1803_Inhibit_Time = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1803_Compatibility_Entry = 0x0;	/* 0 */
                    UNS16 slaveTest_obj1803_Event_Timer = 0x0;	/* 0 */
                    UNS8 slaveTest_obj1803_SYNC_start_value = 0x0;	/* 0 */
                    ODCallback_t slaveTest_Index1803_callbacks[] = 
                     {
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                     };
                    subindex slaveTest_Index1803[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1803 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1803_COB_ID_used_by_PDO },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1803_Transmission_Type },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1803_Inhibit_Time },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1803_Compatibility_Entry },
                       { RW, uint16, sizeof (UNS16), (void*)&slaveTest_obj1803_Event_Timer },
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_obj1803_SYNC_start_value }
                     };

/* index 0x1A00 :   Transmit PDO 1 Mapping. */
                    UNS8 slaveTest_highestSubIndex_obj1A00 = 8; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1A00[] = 
                    {
                      0x60000108,	/* 1610613000 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0	/* 0 */
                    };
                    subindex slaveTest_Index1A00[] = 
                     {
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1A00 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A00[0] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A00[1] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A00[2] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A00[3] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A00[4] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A00[5] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A00[6] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A00[7] }
                     };

/* index 0x1A01 :   Transmit PDO 2 Mapping. */
                    UNS8 slaveTest_highestSubIndex_obj1A01 = 8; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1A01[] = 
                    {
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0	/* 0 */
                    };
                    subindex slaveTest_Index1A01[] = 
                     {
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1A01 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A01[0] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A01[1] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A01[2] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A01[3] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A01[4] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A01[5] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A01[6] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A01[7] }
                     };

/* index 0x1A02 :   Transmit PDO 3 Mapping. */
                    UNS8 slaveTest_highestSubIndex_obj1A02 = 8; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1A02[] = 
                    {
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0	/* 0 */
                    };
                    subindex slaveTest_Index1A02[] = 
                     {
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1A02 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A02[0] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A02[1] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A02[2] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A02[3] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A02[4] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A02[5] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A02[6] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A02[7] }
                     };

/* index 0x1A03 :   Transmit PDO 4 Mapping. */
                    UNS8 slaveTest_highestSubIndex_obj1A03 = 8; /* number of subindex - 1*/
                    UNS32 slaveTest_obj1A03[] = 
                    {
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0,	/* 0 */
                      0x0	/* 0 */
                    };
                    subindex slaveTest_Index1A03[] = 
                     {
                       { RW, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj1A03 },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A03[0] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A03[1] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A03[2] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A03[3] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A03[4] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A03[5] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A03[6] },
                       { RW, uint32, sizeof (UNS32), (void*)&slaveTest_obj1A03[7] }
                     };

/* index 0x6000 :   Mapped variable Read Inputs 8 Bit */
                    UNS8 slaveTest_highestSubIndex_obj6000 = 1; /* number of subindex - 1*/
                    subindex slaveTest_Index6000[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj6000 },
                       { RO, uint8, sizeof (UNS8), (void*)&Read_Inputs_8_Bit[0] }
                     };

/* index 0x6200 :   Mapped variable Write Outputs 8 Bit */
                    UNS8 slaveTest_highestSubIndex_obj6200 = 1; /* number of subindex - 1*/
                    subindex slaveTest_Index6200[] = 
                     {
                       { RO, uint8, sizeof (UNS8), (void*)&slaveTest_highestSubIndex_obj6200 },
                       { RW, uint8, sizeof (UNS8), (void*)&Write_Outputs_8_Bit[0] }
                     };

/**************************************************************************/
/* Declaration of pointed variables                                       */
/**************************************************************************/

const indextable slaveTest_objdict[] = 
{
  { (subindex*)slaveTest_Index1000,sizeof(slaveTest_Index1000)/sizeof(slaveTest_Index1000[0]), 0x1000},
  { (subindex*)slaveTest_Index1001,sizeof(slaveTest_Index1001)/sizeof(slaveTest_Index1001[0]), 0x1001},
  { (subindex*)slaveTest_Index1005,sizeof(slaveTest_Index1005)/sizeof(slaveTest_Index1005[0]), 0x1005},
  { (subindex*)slaveTest_Index1006,sizeof(slaveTest_Index1006)/sizeof(slaveTest_Index1006[0]), 0x1006},
  { (subindex*)slaveTest_Index1014,sizeof(slaveTest_Index1014)/sizeof(slaveTest_Index1014[0]), 0x1014},
  { (subindex*)slaveTest_Index1017,sizeof(slaveTest_Index1017)/sizeof(slaveTest_Index1017[0]), 0x1017},
  { (subindex*)slaveTest_Index1018,sizeof(slaveTest_Index1018)/sizeof(slaveTest_Index1018[0]), 0x1018},
  { (subindex*)slaveTest_Index1200,sizeof(slaveTest_Index1200)/sizeof(slaveTest_Index1200[0]), 0x1200},
  { (subindex*)slaveTest_Index1400,sizeof(slaveTest_Index1400)/sizeof(slaveTest_Index1400[0]), 0x1400},
  { (subindex*)slaveTest_Index1401,sizeof(slaveTest_Index1401)/sizeof(slaveTest_Index1401[0]), 0x1401},
  { (subindex*)slaveTest_Index1402,sizeof(slaveTest_Index1402)/sizeof(slaveTest_Index1402[0]), 0x1402},
  { (subindex*)slaveTest_Index1403,sizeof(slaveTest_Index1403)/sizeof(slaveTest_Index1403[0]), 0x1403},
  { (subindex*)slaveTest_Index1600,sizeof(slaveTest_Index1600)/sizeof(slaveTest_Index1600[0]), 0x1600},
  { (subindex*)slaveTest_Index1601,sizeof(slaveTest_Index1601)/sizeof(slaveTest_Index1601[0]), 0x1601},
  { (subindex*)slaveTest_Index1602,sizeof(slaveTest_Index1602)/sizeof(slaveTest_Index1602[0]), 0x1602},
  { (subindex*)slaveTest_Index1603,sizeof(slaveTest_Index1603)/sizeof(slaveTest_Index1603[0]), 0x1603},
  { (subindex*)slaveTest_Index1800,sizeof(slaveTest_Index1800)/sizeof(slaveTest_Index1800[0]), 0x1800},
  { (subindex*)slaveTest_Index1801,sizeof(slaveTest_Index1801)/sizeof(slaveTest_Index1801[0]), 0x1801},
  { (subindex*)slaveTest_Index1802,sizeof(slaveTest_Index1802)/sizeof(slaveTest_Index1802[0]), 0x1802},
  { (subindex*)slaveTest_Index1803,sizeof(slaveTest_Index1803)/sizeof(slaveTest_Index1803[0]), 0x1803},
  { (subindex*)slaveTest_Index1A00,sizeof(slaveTest_Index1A00)/sizeof(slaveTest_Index1A00[0]), 0x1A00},
  { (subindex*)slaveTest_Index1A01,sizeof(slaveTest_Index1A01)/sizeof(slaveTest_Index1A01[0]), 0x1A01},
  { (subindex*)slaveTest_Index1A02,sizeof(slaveTest_Index1A02)/sizeof(slaveTest_Index1A02[0]), 0x1A02},
  { (subindex*)slaveTest_Index1A03,sizeof(slaveTest_Index1A03)/sizeof(slaveTest_Index1A03[0]), 0x1A03},
  { (subindex*)slaveTest_Index6000,sizeof(slaveTest_Index6000)/sizeof(slaveTest_Index6000[0]), 0x6000},
  { (subindex*)slaveTest_Index6200,sizeof(slaveTest_Index6200)/sizeof(slaveTest_Index6200[0]), 0x6200},
};

const indextable * slaveTest_scanIndexOD (UNS16 wIndex, UNS32 * errorCode, ODCallback_t **callbacks)
{
	int i;
	*callbacks = NULL;
	switch(wIndex){
		case 0x1000: i = 0;break;
		case 0x1001: i = 1;break;
		case 0x1005: i = 2;*callbacks = slaveTest_Index1005_callbacks; break;
		case 0x1006: i = 3;*callbacks = slaveTest_Index1006_callbacks; break;
		case 0x1014: i = 4;break;
		case 0x1017: i = 5;*callbacks = slaveTest_Index1017_callbacks; break;
		case 0x1018: i = 6;break;
		case 0x1200: i = 7;break;
		case 0x1400: i = 8;break;
		case 0x1401: i = 9;break;
		case 0x1402: i = 10;break;
		case 0x1403: i = 11;break;
		case 0x1600: i = 12;break;
		case 0x1601: i = 13;break;
		case 0x1602: i = 14;break;
		case 0x1603: i = 15;break;
		case 0x1800: i = 16;*callbacks = slaveTest_Index1800_callbacks; break;
		case 0x1801: i = 17;*callbacks = slaveTest_Index1801_callbacks; break;
		case 0x1802: i = 18;*callbacks = slaveTest_Index1802_callbacks; break;
		case 0x1803: i = 19;*callbacks = slaveTest_Index1803_callbacks; break;
		case 0x1A00: i = 20;break;
		case 0x1A01: i = 21;break;
		case 0x1A02: i = 22;break;
		case 0x1A03: i = 23;break;
		case 0x6000: i = 24;break;
		case 0x6200: i = 25;break;
		default:
			*errorCode = OD_NO_SUCH_OBJECT;
			return NULL;
	}
	*errorCode = OD_SUCCESSFUL;
	return &slaveTest_objdict[i];
}

/* 
 * To count at which received SYNC a PDO must be sent.
 * Even if no pdoTransmit are defined, at least one entry is computed
 * for compilations issues.
 */
s_PDO_status slaveTest_PDO_status[4] = {s_PDO_status_Initializer,s_PDO_status_Initializer,s_PDO_status_Initializer,s_PDO_status_Initializer};

const quick_index slaveTest_firstIndex = {
  7, /* SDO_SVR */
  0, /* SDO_CLT */
  8, /* PDO_RCV */
  12, /* PDO_RCV_MAP */
  16, /* PDO_TRS */
  20 /* PDO_TRS_MAP */
};

const quick_index slaveTest_lastIndex = {
  7, /* SDO_SVR */
  0, /* SDO_CLT */
  11, /* PDO_RCV */
  15, /* PDO_RCV_MAP */
  19, /* PDO_TRS */
  23 /* PDO_TRS_MAP */
};

const UNS16 slaveTest_ObjdictSize = sizeof(slaveTest_objdict)/sizeof(slaveTest_objdict[0]); 

CO_Data slaveTest_Data = CANOPEN_NODE_DATA_INITIALIZER(slaveTest);

        接下来,来说一下前面的的slaveTest_Data,这其实就是一个结构体类型变量供用户使用。slaveTest_data不需要我们自己去定义和初始化,你在对象字典工具里建立词典的时候,会自动在slaveTest.c源文件中定义并赋值。slaveTest_data的结构体的定义在data.h中。这个也是canfestival中最核心的一个结构体,基本包含节点所有的数据信息。

/**
 * @ingroup od
 * @brief This structure contains all necessary informations to define a CANOpen node 
 */
struct struct_CO_Data {
	/* Object dictionary */
	UNS8 *bDeviceNodeId;
	const indextable *objdict;
	s_PDO_status *PDO_status;
	TIMER_HANDLE *RxPDO_EventTimers;
	void (*RxPDO_EventTimers_Handler)(CO_Data*, UNS32);
	const quick_index *firstIndex;
	const quick_index *lastIndex;
	const UNS16 *ObjdictSize;
	const UNS8 *iam_a_slave;
	valueRangeTest_t valueRangeTest;
	
	/* SDO */
	s_transfer transfers[SDO_MAX_SIMULTANEOUS_TRANSFERS];
	/* s_sdo_parameter *sdo_parameters; */

	/* State machine */
	e_nodeState nodeState;
	s_state_communication CurrentCommunicationState;
	initialisation_t initialisation;
	preOperational_t preOperational;
	operational_t operational;
	stopped_t stopped;
     void (*NMT_Slave_Node_Reset_Callback)(CO_Data*);
     void (*NMT_Slave_Communications_Reset_Callback)(CO_Data*);
     
	/* NMT-heartbeat */
	UNS8 *ConsumerHeartbeatCount;
	UNS32 *ConsumerHeartbeatEntries;
	TIMER_HANDLE *ConsumerHeartBeatTimers;
	UNS16 *ProducerHeartBeatTime;
	TIMER_HANDLE ProducerHeartBeatTimer;
	heartbeatError_t heartbeatError;
	e_nodeState NMTable[NMT_MAX_NODE_ID]; 

	/* NMT-nodeguarding */
	TIMER_HANDLE GuardTimeTimer;
	TIMER_HANDLE LifeTimeTimer;
	nodeguardError_t nodeguardError;
	UNS16 *GuardTime;
	UNS8 *LifeTimeFactor;
	UNS8 nodeGuardStatus[NMT_MAX_NODE_ID];

	/* SYNC */
	TIMER_HANDLE syncTimer;
	UNS32 *COB_ID_Sync;
	UNS32 *Sync_Cycle_Period;
	/*UNS32 *Sync_window_length;;*/
	post_sync_t post_sync;
	post_TPDO_t post_TPDO;
	post_SlaveBootup_t post_SlaveBootup;
    post_SlaveStateChange_t post_SlaveStateChange;
	
	/* General */
	UNS8 toggle;
	CAN_PORT canHandle;	
	scanIndexOD_t scanIndexOD;
	storeODSubIndex_t storeODSubIndex; 
	
	/* DCF concise */
    const indextable* dcf_odentry;
	UNS8* dcf_cursor;
	UNS32 dcf_entries_count;
	UNS8 dcf_status;
    UNS32 dcf_size;
    UNS8* dcf_data;
	
	/* EMCY */
	e_errorState error_state;
	UNS8 error_history_size;
	UNS8* error_number;
	UNS32* error_first_element;
	UNS8* error_register;
    UNS32* error_cobid;
	s_errors error_data[EMCY_MAX_ERRORS];
	post_emcy_t post_emcy;
	
#ifdef CO_ENABLE_LSS
	/* LSS */
	lss_transfer_t lss_transfer;
	lss_StoreConfiguration_t lss_StoreConfiguration;
#endif	
};

         写到这里也就差不多了,我自己源码测试没问题的(当然。。这里只是我整理的测试程序可能有遗漏,没有测试)。

        最后的最后,请各位大佬评论区展示一下测试结果吧。。哈哈。。

  • 12
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
接入第三方登录是让用户方便快捷地使用已有账号登录你的网站或应用程序,提高用户体验的一种方式。本文将介绍如何使用 PHP 实现微信公众号第三方登录。 1. 获取微信授权 首先,需要获取微信用户的授权。具体步骤如下: 1)引导用户打开微信授权页面: ```php $appid = 'your_appid'; $redirect_uri = urlencode('http://yourdomain.com/callback.php'); $scope = 'snsapi_userinfo'; $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirect_uri&response_type=code&scope=$scope&state=STATE#wechat_redirect"; header("Location: $url"); ``` 其中,`$appid` 是你的微信公众号的 AppID,`$redirect_uri` 是授权后回调的 URL,`$scope` 是授权作用域,可以是 `snsapi_base` 或 `snsapi_userinfo`,`$state` 是自定义参数,用于防止 CSRF 攻击。 2)获取授权码: 用户同意授权后,会重定向到 `$redirect_uri` 指定的 URL,带上授权码 `code` 和 `state` 参数。 ```php $code = $_GET['code']; $state = $_GET['state']; ``` 3)获取 access_token 和 openid: 使用授权码 `code` 获取 `access_token` 和 `openid`。 ```php $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code=$code&grant_type=authorization_code"; $response = file_get_contents($access_token_url); $result = json_decode($response, true); $access_token = $result['access_token']; $openid = $result['openid']; ``` 其中,`$secret` 是你的微信公众号的 AppSecret。 2. 获取用户信息 获取到 `access_token` 和 `openid` 后,可以使用以下代码获取用户信息: ```php $userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN"; $response = file_get_contents($userinfo_url); $userinfo = json_decode($response, true); ``` 其中,`$userinfo` 包含用户的昵称、头像等信息。 3. 将用户信息保存到数据库 最后,将获取到的用户信息保存到数据库中,以便下次使用时快速登录。 ```php // 连接数据库 $con = mysqli_connect('localhost', 'username', 'password', 'database'); mysqli_set_charset($con, "utf8"); // 查询用户是否已存在 $sql = "SELECT * FROM users WHERE openid='$openid'"; $result = mysqli_query($con, $sql); if (mysqli_num_rows($result) == 0) { // 用户不存在,插入新用户信息 $nickname = mysqli_real_escape_string($con, $userinfo['nickname']); $headimgurl = mysqli_real_escape_string($con, $userinfo['headimgurl']); $sql = "INSERT INTO users (openid, nickname, headimgurl) VALUES ('$openid', '$nickname', '$headimgurl')"; mysqli_query($con, $sql); } // 保存用户登录状态 $_SESSION['openid'] = $openid; ``` 以上就是使用 PHP 实现微信公众号第三方登录的步骤。需要注意的是,为了确保安全性,应该对用户输入的数据进行过滤和验证,防止 SQL 注入和 XSS 攻击等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值