一、准备工作
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
};
写到这里也就差不多了,我自己源码测试没问题的(当然。。这里只是我整理的测试程序可能有遗漏,没有测试)。
最后的最后,请各位大佬评论区展示一下测试结果吧。。哈哈。。