跳转至

硬件资源

1.1 简介

本章主要介绍如何通过指令访问硬件资源,硬件资源类型详细说明如下:

数字量输出资源:包括专用数字量输出(如伺服使能数字量输出、伺服报警清除数字量输出)和通用数字量输出。

数字量输入资源:包括专用数字量输入资源(正限位数字量输入、负限位数字量输入、驱动报警数字量输入、原点信号数字量输入)和通用数字量输入。

编码器计数资源:用来对外部编码器的脉冲输出进行计数。

模拟量输入资源:电压输入通道,用来获取外部模拟量输入信号。

模拟量输出资源:电压输出通道,输出-10V~+10V的控制电压。

1.2 数字量输入输出

1.2.1 指令列表

访问数字输入输出指令列表

指令 说明
GTN_ReadDigitalInput 读取数字量输入状态。
GTN_GetDiReverseCount 读取数字量输入信号的变化次数。
GTN_SetDiReverseCount 设置数字量输入信号的变化次数的初值。
GTN_WriteDigitalOutputPro 设置数字量输出状态。
GTN_SetDoBitReverse 使数字量输出信号输出定时脉冲信号。
GTN_ReadDigitalOutput 读取数字量输出状态。
GTN_SetSense 设置输入输出资源的电平逻辑。
GTN_GetSense 读取输入输出资源的电平逻辑。

1.2.2 重点说明

调用GTN_ReadDigitalInput指令可以读取限位、驱动报警、原点、通用输入、手轮接口等数字量输入接口的输入电平状态。

调用GTN_WriteDigitalOutputPro指令可以设置伺服使能、报警清除、通用输出等数字量输出接口的输出电平状态。

调用GTN_GetDiReverseCount指令可以读取数字量输入的变化次数,当数字量输入由0变为1,或者由1变为0,该次数就会增加一次。GTN_SetDiReverseCount指令用来设置数字量变化次数计数器的初值。

调用GTN_SetDoBitReverse指令可以使数字量输出信号输出一个定时的脉冲,例如,假设当前通用数字量输出信号1是高电平,当调用指令GTN_SetDoBitReverse(MC_GPO, 1, 0, 100);则该数字量信号将会发出一个100×period(中断周期)时间宽度的负脉冲。

下面详细说明专用数字量输入和输出的含义和用途。

1. 正负限位

控制器为每个轴提供两个输入信号作为行程控制开关。如图所示。

限位开关示意图

把轴配置成正负限位有效后,如果轴运动超越了限位开关所在位置,限位开关触发,运动控制器禁止在触发限位方向继续运动,同时该轴的限位触发状态置1(通过调用GTN_GetStsEx可以查看此状态标志位)。离开限位回到安全运动范围以后,需要调用指令GTN_ClrSts清除限位触发状态,才能使控制轴回到正常运动状态。

注意

限位触发后,轴紧急停止,调用GTN_GetStsEx读取状态,会发现正限位触发标志位或负限位触发标志位置1。用户应按如下步骤操作:
1. 调用指令让轴向反方向运动到安全范围内停下:即如果正限位触发就让轴往负方向运动,负限位触发就让轴往正方向运动。
2. 调用GTN_ClrSts清除限位触发状态。
限位触发后的紧急停止可能会因为运动过冲而引入位置误差,建议用户重新回零。回零方法详见回零功能

如果用户不使用限位开关,可以通过控制器配置,将轴的正负限位配置为无效。

限位开关默认为高电平触发。通过调用GTN_SetSense指令可以修改限位开关的触发电平。

2. 驱动器报警信号

控制器提供专用的驱动报警信号输入接口。该接口应该与驱动器的报警输出信号接口相接。当检测到驱动器报警信号以后,运动控制器将关闭该轴的伺服使能,急停运动规划,同时该轴报警触发标志置1(通过调用GTN_GetStsEx可以查看此状态标志位)。

驱动报警信号默认是低电平触发。

注意

驱动报警后,轴紧急停止,调用GTN_GetStsEx读取状态,会发现驱动器报警标志位置1。用户应当执行以下操作:
1. 确定引起驱动器报警的原因,并加以改正。
2. 复位驱动器。
3. 调用GTN_ClrSts清除报警,重新回机床原点。

3. 原点信号

原点信号又叫Home信号,即电机回到原点时的触发信号,回零功能具体操作请参考"回零功能"章节。

4. 电机到位信号

电机到位信号又叫Arrive信号,电机到达目标位置时的触发信号,硬件接口在网络型模块轴接口中可以找到(请参考硬件说明书)。某些驱动器上有电机到位数字输出接口,控制器提供电机到位输入接口,方便用户使用此功能。

5. 手轮输入信号

手轮数字量输入信号硬件接口在网络型模块对应的手轮(MPG)接口(请参考硬件说明书),用于设置手轮编码器的倍率。

6. 伺服使能

伺服使能信号默认与axis关联,用户不能直接调用GTN_WriteDigitalOutputPro对伺服使能设置输出电平。默认情况下,调用GTN_AxisOn,伺服使能输出低电平,DO置0。如果驱动器是低电平使能,则必须在控制器配置将伺服使能输出设置为输出电平取反,具体操作可参考"系统配置"章节中的"1.3.8 配置专用输出"。

伺服使能信号的硬件接口在网络型模块轴接口中可以找到(请参考硬件说明书)。如果用户使用的驱动器不含伺服使能输入信号,或者用户不需要使用此信号,可以取消伺服使能DO与axis的关联,具体操作可参考"系统配置"章节中的"1.3.8 配置专用输出",这样用户可以直接调用GTN_WriteDigitalOutputProGTN_SetDoBit对伺服使能设置输出电平。

7. 报警清除

某些驱动器上有报警清除数字输入接口,控制器提供报警清除数字量输出接口,方便用户使用此功能。但是此信号不能清除所有的驱动报警情况。例如,在编码器接线不良引起驱动报警时,就无法使用清除报警信号来清除。因此,当报警无法清除时,用户需要具体问题具体分析。用户可以调用GTN_WriteDigitalOutputProGTN_SetDoBit来设置清除报警信号的电平。

访问数字量输入输出例程
// hardware.cpp : 定义控制台应用程序的入口点。

// 该例程仅用于功能演示,请保证安全的情况下使用

// 测试功能:控制器数字量输入输出功能
// 测试平台:网络型运动控制器
// 测试环境:Windows
// 测试流程:
//           (1)初始化控制器
// 注意事项:
//           (1)本例程使用的“例程专用.xml”、“例程专用.cfg”,仅用于本例程
//           (2)实际使用时,需要使用MotionStudio生成网络配置xml
#include "stdafx.h"

// 加载固高运动控制库头文件
#include "gxn.h"
// 动态加载固高运动控制gxn.lib库
#pragma comment(lib,"gxn.lib")

/**
 * @brief 指令出错打印函数
 * @param command 打印信息字符串
 * @param error 错误码
 * @return 错误码
*/
short CommandHandler(char *command ,short error)
{
    printf("%s = %d\n", command, error);
    getchar();
    return error;
}

int _tmain(int argc, _TCHAR* argv[])
{
    short core = 1;
    short rtn;
    int i;
    long status;
    short overTime;
    short diType,diIndex,count;
    short diValue[10];
    TDigitalOutputPro outputPro;
    short doValue[10];
    //打开控制器
    rtn = GTN_OpenCard(CHANNEL_PCIE,NULL,NULL);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_OpenCard",rtn);
    }
     // 初始化网络
    // 注意:(1)“例程专用.xml”仅用于本例程
    //       (2)实际使用时,需要使用MotionStudio生成对应的网络配置文件
    // overTime:网络初始化超时时间,单位:秒
    overTime = 120;
    rtn = GTN_NetInit(NET_INIT_MODE_XML_STRICT,"例程专用.xml",overTime,&status);
    if ( 0 != rtn )
    {
        printf("status = %d\n",status);
        return CommandHandler("GTN_NetInit",rtn);
    }
    printf("Init Net Success !\n");

    //读取数字量输入状态,从第1路开始连续读取10路。
    diType = MC_GPI;
    diIndex = 1;
    count = 10;
    rtn = GTN_ReadDigitalInput(core,diType,diIndex,diValue,10);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_ReadDigitalInput",rtn);
    }
    for (i = 1; i <= count;i++)
    {
        // 显示DI输入数值
        printf("diIndex = %d,value = %d\n",i,diValue[i-1]);
    }

    //设置数字量输出状态,从第1路开始连续设置10路输出立即输出为0。
    memset(&outputPro,0,sizeof(outputPro));
    outputPro.doType = MC_GPO;
    outputPro.doIndex = 1;
    outputPro.doCount = 10;
    outputPro.mode = 1; 
    outputPro.pValue = &doValue[0];
    rtn = GTN_WriteDigitalOutputPro(core,&outputPro,NULL);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_WriteDigitalOutputPro",rtn);
    }

    rtn = GTN_ReadDigitalInput(core,diType,diIndex,diValue,10);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_ReadDigitalInput",rtn);
    }
    for (i = 1; i <= count;i++)
    {
        // 显示DI输入数值
        printf("diIndex = %d,value = %d\n",i,diValue[i-1]);
    }
    printf("Press Any Key To Exit !\n");
    getchar();
    return 0;
}

1.3 编码器

1.3.1 指令列表

访问编码器指令列表

指令 说明
GTN_GetEncPos 读取编码器位置。
GTN_GetEncVel 读取编码器速度。
GTN_SetEncPosEx 设置编码器位置。
GTN_ReadAuEncPos 读取辅助编码器位置。
GTN_ReadMpgInfo 读取手轮信息。
GTN_WriteAuEncPos 设置辅助编码器位置。
GTN_WriteMpgPos 设置手轮编码器位置。
GTN_DisableMpgRoundOff 关闭手轮编码器圆整到4的整数倍功能。
GTN_EnableMpgRoundOff 开启手轮编码器圆整到4的整数倍功能。

1.3.2 重点说明

控制器的编码器资源包括轴编码器、辅助编码器和手轮编码器。轴编码器指网络型模块轴接口对应的编码器,辅助编码器指网络型模块上的ENCx(例如ENC1)接口,手轮编码器指网络型模块上的MPG接口。

1. 轴编码器

控制器内部为每个轴配置了脉冲计数装置。控制器默认的脉冲计数源是外部编码器。如果用户在接线时将外部编码器的信号与网络型模块轴接口的编码器信号接在一起,就可以调用上述指令读取外部编码器的值。如果用户没有接外部编码器反馈信号,例如,使用步进电机时没有编码器反馈部件,如图所示,则用户调用GTN_GetEncPos读取的编码器位置为0。

开环控制系统示意图

控制器还可以配置脉冲计数源是脉冲计数器(具体操作可参考"系统配置"章节中的"1.3.4 配置encoder")。调用GTN_GetEncPos读取的将是运动控制器向驱动器发出的脉冲个数。因此,即使不接反馈部件,也可以读取变化的位置值。

调用GTN_SetEncPosEx修改编码器位置的值。例如,设置轴1的编码器位置为0,则接下来的编码器计数从0开始。若设置为1000,则编码器计数从1000开始。

2. 辅助编码器

调用指令GTN_ReadAuEncPosGTN_WriteAuEncPos读取和设置辅助编码器位置。

3. 手轮编码器

调用指令GTN_ReadMpgInfo读取手轮编码器位置、编码器速度和DI。调用指令 GTN_WriteMpgPos设置手轮编码器位置。

调用指令GTN_EnableMpgRoundOff启动手轮编码器圆整功能,即手轮最小单位是4pulse。控制器默认状态是使能该功能,可以通过指令GTN_DisableMpgRoundOff关闭圆整功能。

访问编码器例程
// encExample.cpp : 定义控制台应用程序的入口点。
//
// 该例程仅用于功能演示,请保证安全的情况下使用

// 测试功能:控制器读取编码器输入功能
// 测试平台:网络型运动控制器
// 测试环境:Windows
// 测试流程:
//           (1)初始化控制器
// 注意事项:
//           (1)本例程使用的“例程专用.xml”、“例程专用.cfg”,仅用于本例程
//           (2)实际使用时,需要使用MotionStudio生成网络配置xml
#include "stdafx.h"

// 加载固高运动控制库头文件
#include "gxn.h"
// 动态加载固高运动控制gxn.lib库
#pragma comment(lib,"gxn.lib")

/**
 * @brief 指令出错打印函数
 * @param command 打印信息字符串
 * @param error 错误码
 * @return 错误码
*/
short CommandHandler(char *command ,short error)
{
    printf("%s = %d\n", command, error);
    getchar();
    return error;
}

int _tmain(int argc, _TCHAR* argv[])
{
    short core = 1;
    short rtn;
    int i;
    long status;
    short overTime;
    short index,count;
    double readValue[8];
    TMpgInfo mpgInfo;
    //打开控制器
    rtn = GTN_OpenCard(CHANNEL_PCIE,NULL,NULL);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_OpenCard",rtn);
    }
     // 初始化网络
    // 注意:(1)“例程专用.xml”仅用于本例程
    //       (2)实际使用时,需要使用MotionStudio生成对应的网络配置文件
    // overTime:网络初始化超时时间,单位:秒
    overTime = 120;
    rtn = GTN_NetInit(NET_INIT_MODE_XML_STRICT,"例程专用.xml",overTime,&status);
    if ( 0 != rtn )
    {
        printf("status = %d\n",status);
        return CommandHandler("GTN_NetInit",rtn);
    }
    printf("Init Net Success !\n");

    //读取轴编码器输入状态,从第1路开始连续读取8路。
    index = 1;
    count = 8;
    rtn = GTN_GetEncPos(core,index,readValue,count,NULL);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetEncPos",rtn);
    }
    for (i = 1; i <= count;i++)
    {
        // 显示轴编码器输入数值
        printf("encIndex = %d,value = %.0f\n",i,readValue[i-1]);
    }
    //读取辅助编码器输入状态,从第1路开始连续读取8路。
    index = 1;
    count = 8;
    rtn = GTN_ReadAuEncPos(core,index,readValue,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_ReadAuEncPos",rtn);
    }
    for (i = 1; i <= count;i++)
    {
        // 显示辅助编码器输入数值
        printf("auEncIndex = %d,value = %.0f\n",i,readValue[i-1]);
    }

    //读取第1路手轮信息(包括手轮编码器和数字量输入)。
    index = 1;
    rtn = GTN_ReadMpgInfo(core,index,&mpgInfo);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_ReadMpgInfo",rtn);
    }
    // 显示辅助编码器输入数值
    printf("mpgIndex = 1,encValue = %.0f  encVel = %.0f  di=%x\n"  ,
          i,mpgInfo.pos,mpgInfo.vel,mpgInfo.di);
    printf("Press Any Key To Exit !\n");
    getchar();
    return 0;
}

1.4 脉冲计数器

1.4.1 指令列表

访问内部脉冲计数输入指令列表

指令 说明
GTN_SetPlsPos 设置内部脉冲计数器位置。
GTN_GetPlsPos 读取内部脉冲计数器位置。
GTN_GetPlsVel 读取内部脉冲计数器速度。

1.4.2 重点说明

脉冲计数器是通过内部硬件计算输出的脉冲个数,需要网络模块支持该功能(目前GNM模块和GTM模块支持,gLink-II驱动器不支持)。调用指令 GTN_GetPlsPos读取指定轴通道的输出脉冲个数。和通过指令GTN_EncOff将脉冲计数源设置为脉冲计数器读取的位置一致,但是不需要占用编码器读取通道,即可以通过相应的指令同时读取编码器位置和脉冲计数器位置,便于调试。

注意

控制器默认脉冲计数器的资源未打开,需要调用指令GTN_SetResCount打开资源。

访问内部脉冲计数器例程
// pulseExample.cpp : 定义控制台应用程序的入口点。
//
// 该例程仅用于功能演示,请保证安全的情况下使用

// 测试功能:控制器读取脉冲计数器输入功能
// 测试平台:网络型运动控制器
// 测试环境:Windows
// 测试流程:
//           (1)初始化控制器
// 注意事项:
//           (1)本例程使用的“例程专用.xml”、“例程专用.cfg”,仅用于本例程
//           (2)实际使用时,需要使用MotionStudio生成网络配置xml
#include "stdafx.h"

// 加载固高运动控制库头文件
#include "gxn.h"
// 动态加载固高运动控制gxn.lib库
#pragma comment(lib,"gxn.lib")

/**
 * @brief 指令出错打印函数
 * @param command 打印信息字符串
 * @param error 错误码
 * @return 错误码
*/
short CommandHandler(char *command ,short error)
{
    printf("%s = %d\n", command, error);
    getchar();
    return error;
}

int _tmain(int argc, _TCHAR* argv[])
{
    short core = 1;
    short rtn;
    int i;
    long status;
    short overTime;
    short index,count;
    double readValue[8];
    //打开控制器
    rtn = GTN_OpenCard(CHANNEL_PCIE,NULL,NULL);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_OpenCard",rtn);
    }
     // 初始化网络
    // 注意:(1)“例程专用.xml”仅用于本例程
    //       (2)实际使用时,需要使用MotionStudio生成对应的网络配置文件
    // overTime:网络初始化超时时间,单位:秒
    overTime = 120;
    rtn = GTN_NetInit(NET_INIT_MODE_XML_STRICT,"例程专用.xml",overTime,&status);
    if ( 0 != rtn )
    {
        printf("status = %d\n",status);
        return CommandHandler("GTN_NetInit",rtn);
    }
    printf("Init Net Success !\n");

    //读取脉冲计数器计数,从第1路开始连续读取8路。
    index = 1;
    count = 8;
    // 默认脉冲计数器(MC_PULSE)是不开启的(节省中断执行时间),先开启8路脉冲计数器资源。
    rtn = GTN_SetResCount(core,MC_PULSE,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_SetResCount",rtn);
    }
    rtn = GTN_GetPlsPos(core,index,readValue,count,NULL);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetPlsPos",rtn);
    }
    for (i = 1; i <= count;i++)
    {
        // 显示脉冲计数器数值
        printf("index = %d,value = %.0f\n",i,readValue[i-1]);
    }
    printf("Press Any Key To Exit !\n");
    getchar();
    return 0;
}

1.5 模拟量输出

1.5.1 指令列表

访问DAC指令列表

指令 说明
GTN_SetDac 设置DAC输出电压。
GTN_GetDac 读取DAC输出电压。
GTN_SetAuDac 设置非轴模拟量(AUDAC)输出电压。
GTN_GetAuDac 读取非轴模拟量(AUDAC)输出电压。

1.5.2 重点说明

控制器模拟量输出资源分为模拟量输出DAC(硬件通道和轴接口在一起)和非轴模拟量输出AUDAC(独立的硬件接口),两种软件资源是独立寻址的。

控制器的模拟量输出通道在闭环控制模式下,作为伺服电压输出控制通道,与驱动器连接,是不允许用户操作的。如果网络从站是固高自主研发的gLink-II驱动器,在闭环控制模式下,轴上模拟量输出依然支持指令GTN_SetDac设置输出电压。

在开环控制模式下,可以作为通用的电压输出通道。上电复位后,控制器默认为脉冲(开环)控制模式,用户可以调用DAC指令列表中的指令来设置和读取DAC输出电压。模块上轴接口对应的模拟电压值与指令读取数值对应关系为[-10V,10V]对应[-32768,32767]。

1.6 模拟量输入

1.6.1 指令列表

访问模拟量输入指令列表

指令 说明
GTN_GetAdc 读取模拟量输入的电压值。
GTN_GetAdcValue 读取模拟量输入的数字转换值。
GTN_SetAdcFilterPrm 设置模拟量输入的滤波参数。
GTN_GetAdcFilterPrm 读取模拟量输入的滤波参数。
GTN_GetAuAdc 读取非轴模拟量输入的电压值。
GTN_GetAuAdcValue 读取非轴模拟量输入的数字转换值。
GTN_SetAuAdcFilterPrm 设置非轴模拟量输入的滤波参数。
GTN_GetAuAdcFilterPrm 读取非轴模拟量输入的滤波参数。

1.6.2 重点说明

控制器模拟量输入资源分为模拟量输入ADC(硬件通道和轴接口在一起)和非轴模拟量输入AUADC(独立的硬件接口),两种软件资源是独立寻址的。

调用指令GTN_GetAdc读取指定轴通道的外部输入模拟电压值,指令GTN_GetAuAdc读取指定非轴通道的外部输入模拟电压值。模拟电压值与指令读取数值对应关系为[-10V,10V]对应[-32768,32767]。

访问模拟量输入输出例程
// dacExample.cpp : 定义控制台应用程序的入口点。

// 该例程仅用于功能演示,请保证安全的情况下使用

// 测试功能:控制器模拟量输入输出功能
// 测试平台:网络型运动控制器
// 测试环境:Windows
// 测试流程:
//           (1)初始化控制器
// 注意事项:
//           (1)本例程使用的“例程专用.xml”、“例程专用.cfg”,仅用于本例程
//           (2)实际使用时,需要使用MotionStudio生成网络配置xml
#include "stdafx.h"

// 加载固高运动控制库头文件
#include "gxn.h"
// 动态加载固高运动控制gxn.lib库
#pragma comment(lib,"gxn.lib")

/**
 * @brief 指令出错打印函数
 * @param command 打印信息字符串
 * @param error 错误码
 * @return 错误码
*/
short CommandHandler(char *command ,short error)
{
    printf("%s = %d\n", command, error);
    getchar();
    return error;
}

int _tmain(int argc, _TCHAR* argv[])
{
    short core = 1;
    short rtn;
    int i;
    long status;
    short overTime;
    short index,count;
    short readValue[2];
    short writeValue[2];
    double readVoltage[2];
    //打开控制器
    rtn = GTN_OpenCard(CHANNEL_PCIE,NULL,NULL);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_OpenCard",rtn);
    }
     // 初始化网络
    // 注意:(1)“例程专用.xml”仅用于本例程
    //       (2)实际使用时,需要使用MotionStudio生成对应的网络配置文件
    // overTime:网络初始化超时时间,单位:秒
    overTime = 120;
    rtn = GTN_NetInit(NET_INIT_MODE_XML_STRICT,"例程专用.xml",overTime,&status);
    if ( 0 != rtn )
    {
        printf("status = %d\n",status);
        return CommandHandler("GTN_NetInit",rtn);
    }
    printf("Init Net Success !\n");

    //设置模拟量输出,从第1路开始连续设置2路DAC输出。
    index = 1;
    count = 2;
    for (i = 1; i <= count;i++)
    {
        // 初始化输出值
        writeValue[i-1] = 16384;//对应5V
    }
    rtn = GTN_SetDac(core,index,writeValue,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_SetDac",rtn);
    }
    //读取模拟量输出
    rtn = GTN_GetDac(core,index,readValue,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetDac",rtn);
    }
    for (i = 1; i <= count;i++)
    {
        // 显示dac输出的数值,该数值是控制器的数值,实际输出需要测量硬件
        printf("dacIndex = %d,value = %d\n",i,readValue[i-1]);
    }
    // 设置非轴dac输出
    rtn = GTN_SetAuDac(core,index,writeValue,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_SetAuDac",rtn);
    }
    // 读取非轴dac输出
    rtn = GTN_GetAuDac(core,index,readValue,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetAuDac",rtn);
    }
    for (i = 1; i <= count;i++)
    {
        // 显示dac输出的数值,该数值是控制器的数值,实际输出需要测量硬件
        printf("auDacIndex = %d,value = %d\n",i,readValue[i-1]);
    }
    // 读取模拟量输入电压值
    rtn = GTN_GetAdc(core,index,readVoltage,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetAdc",rtn);
    }
    for (i = 1; i <= count;i++)
    {
        // 显示adc输入的数值
        printf("adcIndex = %d,value = %.4f\n",i,readVoltage[i-1]);
    }
    // 读取非轴模拟量输入电压值
    rtn = GTN_GetAuAdc(core,index,readVoltage,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetAdc",rtn);
    }
    for (i = 1; i <= count;i++)
    {
        // 显示adc输入的数值
        printf("auAdcIndex = %d,value = %.4f\n",i,readVoltage[i-1]);
    }
    printf("Press Any Key To Exit !\n");
    getchar();
    return 0;
}

1.7 扩展模块

1.7.1 指令列表

扩展模块功能指令列表

指令 说明
GTN_SetExtModuleAccessMode 设置扩展模块的访问模式。
GTN_GetExtModuleAccessMode 读取扩展模块的访问模式。
GTN_GetExtModuleCount 读取扩展模块的个数。
GTN_SetExtDoBit 按位设置DO输出值。
GTN_SetExtDo 设置数字量输出DO数值。
GTN_GetExtDo 读取数字量输出DO数值。
GTN_GetExtDi 读取数字量输入DI数值。
GTN_SetExtAo 设置模拟量输出AO电压值。
GTN_GetExtAo 读取模拟量输出AO电压值。
GTN_GetExtAi 读取模拟量输入AI电压值。
GTN_SetExtModuleReverse 设置扩展模块输入输出取反。
GTN_GetExtModuleReverse 读取扩展模块输入输出取反。
GTN_BufExtDoBit 插补缓存区中按位设置扩展模块的DO输出值。
GTN_BufExtAo 插补缓存区中设置扩展模块的模拟量输出。

1.7.2 重点说明

GSN控制器本地的gLink-I接口和由gLink-II连接的网络型模块上的EXT I/O接口都可以级联扩展模块,如图所示。扩展模块包括数字量模块和模拟量模块,关于扩展模块选型等事项请联系固高销售人员。

GSN扩展模块连接示意图

GVN控制器仅通用gLink-II网络接口支持gLink-I扩展模块,即控制器上的gLink-I接口和通用gLink-II连接的网络型模块上的EXT I/O接口都可以级联扩展模块,如图所示。扩展模块相关指令只适用于通用gLink-II。扩展模块包括数字量模块和模拟量模块,关于扩展模块选型等事项请联系固高销售人员。

GVN扩展模块连接示意图

注意

GVN高速核不支持扩展模块。

1. 扩展模块IO资源映射

扩展模块包括数字量扩展模块和模拟量扩展模块。默认控制器会按照所接模块的个数和顺序自动配置软件资源和硬件资源的映射关系。首先映射控制器上gLink-I接口连接的所有扩展模块,再映射第一个网络型模块的EXT I/O接口连接的所有扩展模块,再顺序映射下一个网络型模块EXT I/O接口连接的所有扩展模块。

如上图所示的网络拓扑结构,在控制器的gLink-I接口连接了2个DI16DO16数字扩展模块,通用gLink-II上连接了GNM六轴网络型模块,GNM六轴网络型模块上连接了1个DI16DO16数字扩展模块和 1个AI06AO06模拟量扩展模块。默认软件资源和硬件资源的对应关系如表所示。

软件和硬件资源映射关系

软件资源 硬件资源 扩展模块序号
DI1~16 DI0~15 1
DI17~32 DI0~15 2
DI33~48 DI0~15 3
DO1~16 DO0~15 1
DO17~32 DO0~15 2
DO33~48 DO0~15 3
AI1~6 AI0~5 4
AO1~6 AO0~5 4

2. gLink-I扩展模块访问模式

gLink-I支持库访问和控制器访问2种完全独立的工作模式,默认为库访问模式,可以通过指令GTN_SetExtModuleAccessMode切换工作模式。库访问指令执行效率相比控制器访问快。如果用户需要使用插补缓存区访问扩展模块必须通过指令GTN_SetExtModuleAccessMode切换成"控制器访问模式"。

注意
  1. 默认配置是按照所接硬件资源的通道总数进行配置。如果硬件资源大于软件资源,默认映射是将所有的软件资源按顺序映射至相应的硬件资源,多余的未映射硬件资源不可控。
  2. 数字量模块和模拟量模块可以同时级联到同一个网络型模块,一套gLink-II协议最多可以级联64个扩展模块。
  3. 扩展模块的资源映射关系可以通过MotionStudio调试软件生成,请参考"基本操作指南"章节中的"xml映射文件生成"。
扩展模块输入输出
// extModuleExample.cpp : 定义控制台应用程序的入口点。
//
// 该例程仅用于功能演示,请保证安全的情况下使用

// 测试功能:控制器设置扩展模块输入输出
// 测试平台:网络型运动控制器
// 测试环境:Windows
// 测试流程:
//           (1)初始化控制器
// 注意事项:
//           (1)本例程使用的“例程专用.xml”、“例程专用.cfg”,仅用于本例程
//           (2)实际使用时,需要使用MotionStudio生成网络配置xml
#include "stdafx.h"

// 加载固高运动控制库头文件
#include "gxn.h"
// 动态加载固高运动控制gxn.lib库
#pragma comment(lib,"gxn.lib")

/**
 * @brief 指令出错打印函数
 * @param command 打印信息字符串
 * @param error 错误码
 * @return 错误码
*/
short CommandHandler(char *command ,short error)
{
    printf("%s = %d\n", command, error);
    getchar();
    return error;
}

int _tmain(int argc, _TCHAR* argv[])
{
    short core = 1;                // 指令核参数
    short rtn;                     // 指令返回值
    long status;                   // 开卡返回的详细错误
    short overTime;                // 网络初始化的延时时间
    short index,count;             // 扩展模块的输入输出起始序号和个数
    long writeValue,readValue;     // 数字量扩展模块的输出值和输入值
    long mask;                     // 数字量输出的掩码
    double aoValue,aiValue;        // 模拟量扩展模块的输出和输入电压值
    //打开控制器
    rtn = GTN_OpenCard(CHANNEL_PCIE,NULL,NULL);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_OpenCard",rtn);
    }
     // 初始化网络
    // 注意:(1)“例程专用.xml”仅用于本例程
    //       (2)实际使用时,需要使用MotionStudio生成对应的网络配置文件
    // overTime:网络初始化超时时间,单位:秒
    overTime = 120;
    rtn = GTN_NetInit(NET_INIT_MODE_XML_STRICT,"例程专用.xml",overTime,&status);
    if ( 0 != rtn )
    {
        printf("status = %d\n",status);
        return CommandHandler("GTN_NetInit",rtn);
    }
    printf("Init Net Success !\n");
//数字量模块的输入输出操作
    // 设置数字量扩展模块输出,从第1路开始,连续32路的输出。
    index = 1;
    mask = 0xffffffff;
    writeValue = 0xaaaa5555;
    rtn= GTN_SetExtDo(core,index,writeValue,mask);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_SetExtDo",rtn);
    }
    // 读取数字量扩展模块输出,从第1路开始,连续32路的输出。
    rtn = GTN_GetExtDo(core,index,&readValue);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetExtDo",rtn);
    }
    printf("doIndex = %d,value=0x%lx\n" ,index,readValue);
    // 读取数字量扩展模块输入,从第1路开始,连续32路的输出。
    rtn = GTN_GetExtDi(core,index,&readValue);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetExtDi",rtn);
    }
    printf("diIndex = 1,value=0x%x\n" ,index,readValue);

// 模拟量模块的输入和输出去
    // 设置第1路模拟量扩展模块输出。
    index = 1;
    aoValue = 5;
    count = 1;
    rtn= GTN_SetExtAo(core,index,&aoValue,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_SetExtAo",rtn);
    }
    // 读取第1路模拟量扩展模块输出,读取的数据是设置的值,硬件实际输出需要另外测量。
    rtn = GTN_GetExtAo(core,index,&aoValue,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetExtAo",rtn);
    }
    printf("aoIndex = %d,value=%.4f\n" ,index,aoValue);
   // 读取第1路模拟量扩展模块输入,单位为伏特。
    rtn = GTN_GetExtAi(core,index,&aiValue,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetExtAi",rtn);
    }
    printf("aiIndex = %d,value=%.4f\n" ,index,aiValue);

    printf("Press Any Key To Exit !\n");
    getchar();
    return 0;
}

1.7.3 扩展模块缓存区输出

扩展模块缓存区输出需要通过指令GTN_SetExtModuleAccessMode切换成"控制器访问扩展模块"模式。缓存区输出功能需先建立插补坐标系,往插补缓存区中压入数据,再启动缓存区的指令执行,详见"运动模式"章节中的"1.6 插补运动模式"。

调用缓存区指令设置插补缓存区中扩展模块的数字量或者模拟量输出,扩展模块的输出不会立即输出,调用GTN_CrdStart启动插补缓存区的指令执行后才会输出。

扩展模块缓存区输出
// extModuleBufExample.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

// 该例程仅用于功能演示,请保证安全的情况下使用

// 测试功能:插补缓存区设置扩展模块输出示例
// 测试平台:网络型运动控制器
// 测试环境:Windows
// 测试流程:
//           (1)初始化控制器
//           (2)建立插补坐标系
//           (3)初始化前瞻
//           (4)压直线插补数据和扩展模块输出指令
//           (5)启动插补坐标系运动
//           (6)检测插补是否运动完成
//           (7)运动完成,关闭控制器
// 注意事项:
//           (1)本例程使用的“例程专用.xml”、“例程专用.cfg”,仅用于本例程
//           (2)实际使用时,需要使用MotionStudio生成网络配置xml

// 加载固高运动控制库头文件
#include "gxn.h"
// 动态加载固高运动控制gxn.lib库
#pragma comment(lib,"gxn.lib")

/**
 * @brief 指令出错打印函数
 * @param command 打印信息字符串
 * @param error 错误码
 * @return 错误码
*/
short CommandHandler(char* command, short error)
{
    printf("%s = %d\n", command, error);
    getchar();

    return error;
}

/**
 * @brief 初始化运动控制器(开卡 + 初始化网络拓扑 + 初始化轴)
 * @param core 需要初始化的核号,从1开始
 * @param axis 需要初始化的轴起始索引,从1开始
 * @param axisCount 需要初始化的轴数量,从起始索引axis开始计数,必须大于0
 * @return 0表示初始化成功,非0表示初始化失败
*/
short InitMc(short core,short axis,short axisCount)
{
    short rtn;
    short overTime;
    long status;

    // 打开运动控制器
    rtn = GTN_OpenCard(CHANNEL_PCIE,NULL,NULL);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_OpenCard",rtn);
    }
    printf("Open Card Success !\n");

    // 初始化网络
    // 注意:(1)“例程专用.xml”仅用于本例程
    //       (2)实际使用时,需要使用MotionStudio生成对应的网络配置文件
    // overTime:网络初始化超时时间,单位:秒
    overTime = 120;
    rtn = GTN_NetInit(NET_INIT_MODE_XML_STRICT,"例程专用.xml",overTime,&status);
    if ( 0 != rtn )
    {
        printf("status = %d\n",status);
        return CommandHandler("GTN_NetInit",rtn);
    }
    printf("Init Net Success !\n");

    // 加载配置文件到控制器
    // 注意:(1)“例程专用.cfg”仅用于本例程
    //       (2)实际使用时,需要使用MotionStudio生成对应的配置文件
    rtn = GTN_LoadConfig(core,"例程专用.cfg");
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_LoadConfig(\"例程专用.cfg\")",rtn);
    }

    // 清除轴状态
    rtn = GTN_ClrSts(core,axis,axisCount);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_ClrSts",rtn);
    }
    printf("Init Mc Config Success !\n");

    return rtn;
}

/**
 * @brief 建立插补坐标系,并且初始化前瞻
 * @param core 插补坐标系所在的核号
 * @param crd 插补坐标系号
 * @param fifo 插补坐标系缓存区号
 * @return 0表示成功,非0表示失败
*/
short InitCrd(short core,short crd,short fifo)
{
    short rtn;
    short i;
    TCrdPrm crdPrm;                    // 插补坐标系参数

    EMachineMode machineMode;          // 插补坐标系机床模式
    TLookAheadParameter laPrm;         // 前瞻参数
    short motionMode;                  // 前瞻运行模式

    // 建立插补坐标系
    memset(&crdPrm,0,sizeof(crdPrm));  // 将结构体参数全部初始化为0
    crdPrm.dimension = 2;              // 二维坐标系
    crdPrm.profile[0] = CRD_AXIS_X;    // x轴,此处为规划器1为坐标系的x轴
    crdPrm.profile[1] = CRD_AXIS_Y;    // y轴,此处为规划器2为坐标系的y轴
    crdPrm.synVelMax = 500;            // 最大合成速度,单位:脉冲/ms
    crdPrm.synAccMax = 10;             // 最大合成加速度,单位:脉冲/ms^2
    crdPrm.evenTime = 0;               // 最小匀速时间,单位:ms
    crdPrm.setOriginFlag = 0;          // 坐标系原点设置标志,0:使用当前规划位置作为坐标系原点
                                       //                     1:使用crdPrm.originPos[8]中设置的位置作为坐标系原点
    rtn = GTN_SetCrdPrm(core,crd,&crdPrm);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_SetCrdPrm",rtn);
    }

    // 建立前瞻坐标系
    machineMode = NORMAL_THREE_AXIS;   // 标准三轴机床模式
    rtn = GTN_SetupLookAheadCrd(core,crd,machineMode);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_SetupLookAheadCrd",rtn);
    }

    // 初始化前瞻参数
    memset(&laPrm,0,sizeof(laPrm));    // 将结构体参数全部初始化为0
    laPrm.lookAheadNum = 200;          // 前瞻段数,前瞻工作区每攒够当前数量的运动段就会进行一次预处理,输出处理后的数据
    laPrm.time = 0.001;                // 时间常数,单位:ms
    laPrm.radiusRatio = 1.5;           // 曲率限制调节系数
    for (i=0;i<8;++i)                  // 数据索引,i=0表示x轴,i=1表示y轴,i=7表示w轴
    {
        laPrm.vMax[i] = 500;           // 当前轴最大速度限制,单位:mm/s
        laPrm.aMax[i] = 2000;          // 当前轴最大加速度限制,单位:mm/s^2
        laPrm.DVMax[i] = 300;          // 当前轴在时间常数内最大速度变化量
        laPrm.scale[i] = 1000;         // 当前轴当量,单位:脉冲/mm
        laPrm.axisRelation[i] = i+1;   // 一般按此配置,无需修改
    }
    motionMode = 0;                    // 保留参数,必须为0
                                       // TPreStartPos为保留参数,必须为NULL
    rtn = GTN_InitLookAheadEx(core,crd,&laPrm,fifo,motionMode,NULL);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_InitLookAheadEx",rtn);
    }

    // 清空插补缓冲区
    rtn = GTN_CrdClear(core,crd,fifo);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_CrdClear",rtn);
    }

    return rtn;
}

/**
 * @brief 获取插补运动状态
 * @param core 插补坐标系所在的核号
 * @param crd 插补坐标系号
 * @param fifo 插补坐标系缓存区号
 * @param pCrdRun 插补坐标系运动状态变量指针
 * @return 0表示获取插补运动状态成功,非0表示获取插补运动状态出错
*/
short GetMotionInfo(short core,short crd,short fifo,short *pCrdRun)
{
    short rtn;
    long crdExecuteSegNum;             // 插补已经执行的段数
    long crdRemainder;                 // 插补剩余未执行段数
    double crdPos[8];                  // 插补规划位置
    short index,diValue,count;
    double aoValue;
    index = 1;
    count = 1;
    // 运动过程中读取当前状态
    rtn = GTN_CrdStatus(core,crd,pCrdRun,&crdExecuteSegNum,fifo);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_CrdStatus",rtn);
    }
    rtn = GTN_GetCrdPos(core,crd,&crdPos[0]);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_GetCrdPos",rtn);
    }
    // 读取数字量扩展模块输出,从第1路开始,连续32路的输出。
    rtn = GTN_GetExtDoBit(core,index,&diValue);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetExtDoBit",rtn);
    }
    // 读取第1路模拟量扩展模块输出,读取的数据是设置的值,硬件实际输出需要另外测量。
    rtn = GTN_GetExtAo(core,index,&aoValue,count);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetExtAo",rtn);
    }
    printf("crdRun = %d, crdExecuteSegNum = %d, xPos = %lf, yPos = %lf,index = %d,doValue = %x,aoValue=%.4f\r",*pCrdRun,crdExecuteSegNum,crdPos[0],crdPos[1],index,diValue,aoValue);

    if ( 0 == *pCrdRun )
    {
        rtn = GTN_GetRemainderSegNum(core,crd,&crdRemainder,fifo);
        if ( 0 != rtn )
        {
            return CommandHandler("GTN_GetRemainderSegNum",rtn);
        }

        if ( 0 != crdRemainder )
        {
            printf("\nCrd Run Empty Error!\n");
        }
        else
        {
            printf("\nCrd Motion Done !\n");
        }
    }

    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    short rtn;                         // 指令返回值
    short core;                        // 需要执行例程的运动控制器核号
    short axis;                        // 需要初始化的轴起始索引号
    short axisCount;                   // 需要初始化的轴数量,从轴起始索引号开始算起
    short index;                       // 扩展模块输出的起始索引号
    short doValue;                     // 数字量扩展模块的输出值
    double aoValue;                    // 模拟量扩展模块的输出值,单位V
    // 初始化运动控制器
    // 开卡 + 初始化网络拓扑 + 初始化核1的1-8轴
    core = 1;
    axis = 1;
    axisCount = 8;
    rtn = InitMc(core,axis,axisCount);
    if ( 0 != rtn )
    {
        return rtn;
    }
    // 切换扩展模块支持控制器DSP访问,缓存区控制模块必须调用该指令切换。
    rtn = GTN_SetExtModuleAccessMode(core,1);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_SetExtModuleAccessMode",rtn);
    }
    short crd;                         // 插补坐标系号
    short fifo;                        // 插补数据使用的缓冲区号

    crd = 1;                           // 指定测试的插补坐标系号为1
    fifo = 0;                          // 指定测试的插补坐标系缓冲区号为0
                                       // 注意:(1)每套插补坐标系只有fifo=0时支持前瞻,fifo=1时不支持前瞻
                                       //       (2)fifo=0一般用于轨迹加工
                                       //       (3)fifo=1用于辅助fifo=0,例如加工过程中需要暂停一会儿去走其他轨迹,可以用fifo=1实现
    rtn = InitCrd(core,crd,fifo);
    if ( 0 != rtn )
    {
        return rtn;
    }

    double endPos[2];                  // 插补数据段目标位置
    double synVel;                     // 插补数据段合成目标速度
    double synAcc;                     // 插补数据段合成加速度
    long segNum;                       // 插补数据段用户段号
    short override2;                   // 插补运动倍率选择标志

    short crdRun;                      // 插补运动状态

    endPos[0] = 0;                     // 初始化x轴插补数据段目标位置为0
    endPos[1] = 0;                     // 初始化y轴插补数据段目标位置为0
    synVel = 500;                      // 插补数据段合成目标速度,单位:mm/s
    synAcc = 50;                       // 插补数据段合成目标加速度,单位:mm/s^2
    segNum = 0;                        // 初始化插补数据段段号为0
    override2 = 0;                     // 插补运动倍率选择标志,0:选择第一个倍率,1:选择第二个倍率

    endPos[0] = 200.0;
    endPos[1] = 0.0;
    segNum += 1;
    // 压直线插补数据
    rtn = GTN_LnXYEx(core,crd,endPos[0],endPos[1],synVel,synAcc,segNum,override2,fifo);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_LnXYEx",rtn);
    }
    index = 1;
    doValue = 1;
    // 数字量扩展模块第1路DO输出1。
    rtn = GTN_BufExtDoBitEx(core,crd,index,doValue,fifo);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_BufExtDoBitEx",rtn);
    }
    index = 1;
    aoValue = 5.0;
    // 模拟量扩展模块第1路AO输出5V。
    rtn = GTN_BufExtAoEx(core,crd,index,aoValue,fifo);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_BufExtAoEx",rtn);
    }
    endPos[0] = 100.0;
    endPos[1] = 200.0;
    segNum += 1;
    // 压直线插补数据
    rtn = GTN_LnXYEx(core,crd,endPos[0],endPos[1],synVel,synAcc,segNum,override2,fifo);
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_LnXYEx",rtn);
    }
    // 将数据压入运动控制器
    do 
    {
        rtn = GTN_CrdDataEx(core,crd,NULL,fifo);
        if ( 0 == rtn )
        {
            break;
        }
        if ( 1 != rtn )
        {
            return CommandHandler("GTN_CrdDataEx",rtn);
        }
    } while ( 1 == rtn );

    // 启动插补运动
    rtn = GTN_CrdStart(core,1<<(crd-1),fifo<<(crd-1));
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_CrdStart",rtn);
    }
    printf("Start Crd Success !\n");

    do 
    {
        // 运动过程中读取当前状态
        rtn = GetMotionInfo(core,crd,fifo,&crdRun);
        if ( 0 != rtn )
        {
            return rtn;
        }
    } while ( 1 == crdRun );

    // 关闭控制器
    rtn = GTN_Close();
    if ( 0 != rtn )
    {
        return CommandHandler("GTN_Close",rtn);
    }

    printf("Press Any Key To Exit !\n");
    getchar();

    return 0;
}

1.8 掉电存储功能

1.8.1 指令列表

掉电功能指令列表

指令 说明
GTN_SetRetainValue 保存数据到MRAM存储芯片。
GTN_GetRetainValue 读取MRAM存储芯片数据。

1.8.2 重点说明

掉电存储功能可以保存用户的重要数据,防止在异常断电的情况下丢失一些重要的数据。目前提供的非易失存储芯片最大存储资源为16384个words,用户可以根据自己需求随意使用,详细的使用方式详见以下例程。

掉电存储
// MRAM.cpp : 定义控制台应用程序的入口点。

// 该例程仅用于功能演示,请保证安全的情况下使用

// 测试功能:控制器掉电存储功能
// 测试平台:网络型运动控制器
// 测试环境:Windows
// 测试流程:
//           (1)初始化控制器
// 注意事项:
//           (1)本例程使用的“例程专用.xml”、“例程专用.cfg”,仅用于本例程
//           (2)实际使用时,需要使用MotionStudio生成网络配置xml
#include "stdafx.h"

// 加载固高运动控制库头文件
#include "gxn.h"
// 动态加载固高运动控制gxn.lib库
#pragma comment(lib,"gxn.lib")

/**
 * @brief 指令出错打印函数
 * @param command 打印信息字符串
 * @param error 错误码
 * @return 错误码
*/
short CommandHandler(char *command ,short error)
{
    printf("%s = %d\n", command, error);
    getchar();
    return error;
}

int _tmain(int argc, _TCHAR* argv[])
{
    short core = 1;
    short rtn;
    int i;
    long status;
    short overTime;
    unsigned long address;   // 起始地址
    short count;             // 数据个数
    short data[10];          // 写入和读取MRAM的数据
    //打开控制器
    rtn = GTN_OpenCard(CHANNEL_PCIE,NULL,NULL);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_OpenCard",rtn);
    }
     // 初始化网络
    // 注意:(1)“例程专用.xml”仅用于本例程
    //       (2)实际使用时,需要使用MotionStudio生成对应的网络配置文件
    // overTime:网络初始化超时时间,单位:秒
    overTime = 120;
    rtn = GTN_NetInit(NET_INIT_MODE_XML_STRICT,"例程专用.xml",overTime,&status);
    if ( 0 != rtn )
    {
        printf("status = %d\n",status);
        return CommandHandler("GTN_NetInit",rtn);
    }
    printf("Init Net Success !\n");

    address = 0;
    count = 10;
    // 初始化数据
    for (i = 0; i < count;i++)
    {
        data[i] = i;
    }
    // 设置MRAM数值,从地址0开始连续写10个数据
    rtn = GTN_SetRetainValue(core,address,count,data);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_SetRetainValue",rtn);
    }
    // 读取MRAM数值
    rtn = GTN_GetRetainValue(core,address,count,data);
    if (CMD_SUCCESS != rtn)
    {
        return CommandHandler("GTN_GetRetainValue",rtn);
    }
    for (i = 0; i < count;i++)
    {
        // 显示MRAM读取的数值
        printf("address = %d,value = %d\n",i,data[i]);
    }
    printf("Press Any Key To Exit !\n");
    getchar();
    return 0;
}