这段代码是一个用于控制运动控制卡的应用程序,它通过编写板载程序并监控其执行来实现对运动轴的控制。代码中包含了初始化、设置运动参数、启动运动、等待运动完成以及错误处理等多个部分。
这个C程序是为了演示如何使用National Instruments的FlexMotion软件来同步主机程序和板载程序。程序分为两个主要部分:板载程序和主机程序。
-
板载程序:运行在运动控制卡上的程序,负责控制轴在两个预设位置之间移动。它使用变量来存储目标位置和移动方向的乘数,并通过标签和条件跳转来实现循环移动。在每次改变移动方向前,它会设置一个状态位,以便主机程序知道轴即将改变移动方向。
-
主机程序:运行在主机上的程序,监控板载程序的执行。它通过检查移动完成状态寄存器中的一个特定位来确定轴是否即将改变移动方向,并记录轴的新目标位置。如果发生错误,主机程序会读取错误信息并进行处理。
执行逻辑如下:
- 初始化变量,设置板卡ID、轴号、目标位置、乘数等。
- 将乘数和目标位置加载到板载变量中。
- 开始板载程序存储,设置操作模式为绝对位置,加载速度,插入标签,加载目标位置,启动移动,并等待移动完成。
- 在移动完成且即将改变方向时,通过设置状态位来通知主机程序。
- 主机程序循环检查轴的状态和移动完成状态寄存器,记录新的目标位置,并在轴移动完成、出现跟随错误或轴关闭时退出循环。
///
/
// 要求:FlexMotion软件版本5或更高版本。
//
// 使用导入库:
// <NI-Motion安装位置>\FlexMotion\lib\Microsoft\FlexMS32.lib
// 对于MS编译器,以及
// <NI-Motion安装位置>\FlexMotion\lib\Borland\FlexBC32.lib
// 对于BC编译器
//
// 在您的项目包含目录中添加包含路径:
// <NI-Motion安装位置>\FlexMotion\Include
// <NI-Motion安装位置>\FlexMotion\Examples\C\Includes
//
// 将常见源代码添加到您的项目中:
// <NI-Motion安装位置>\FlexMotion\Examples\C\Includes\NIMCExample.c
//
// 其中<NI-Motion安装位置>默认是
// <驱动器>\Program Files\National Instruments\NI-Motion
// 对于32位Windows
// <驱动器>\Program Files (x86)\National Instruments\NI-Motion
// 对于64位Windows
//
// 描述:
// 这个C示例演示了同步主机程序与板载程序的过程。这个示例分为两部分:
// 一部分是板载程序,另一部分是监控该板载程序的主机应用程序。
//
///
// 包含//
#include "flexmotn.h" // 包含FlexMotion库
#include "NIMCExample.h" // 包含NIMC示例代码
#include <stdio.h> // 标准输入输出库
#include <stdlib.h> // 标准库
//
// 主函数
void main(void)
{
u8 boardID; // 板卡标识号
u8 axis; // 轴号
u16 csr = 0; // 通信状态寄存器
i32 targetPosition; // 目标位置
i32 multiplier; // 乘数
u16 axisStatus; // 轴状态
u16 moveCompleteStatus; // 移动完成状态
// 模态错误处理的变量
u16 commandID; // 函数的commandID
u16 resourceID; // 资源ID
i32 errorCode; // 错误代码
///
// 设置板卡ID
boardID = 1;
// 设置轴号
axis = 1;
// 设置移动长度
targetPosition = 5000; // 目标位置
// 设置乘数
multiplier = -1;
//--------------------------------------------------------
// 板载程序。此板载程序将轴在targetPosition和-targetPosition之间来回移动。在改变方向之前,它会通知主机计算机。
//--------------------------------------------------------
// 初始化板载变量2为改变目标位置的乘数
err = flex_load_var(boardID, multiplier, 2);
CheckError;
// 初始化板载变量1为目标位置
err = flex_load_var(boardID, targetPosition, 1);
CheckError;
// 开始板载程序存储 - 程序编号1
err = flex_begin_store(boardID, 1);
// 设置操作模式为绝对位置
err = flex_set_op_mode(boardID, axis, NIMC_ABSOLUTE_POSITION);
CheckError;
// 设置速度
err = flex_load_velocity(boardID, axis, 10000, 0xFF);
CheckError;
// 插入标签编号1
err = flex_insert_program_label(boardID, 1);
CheckError;
// 从板载变量1加载目标位置
err = flex_load_target_pos(boardID, axis, 0, 1);
CheckError;
// 开始移动
err = flex_start(boardID, axis, 0);
CheckError;
// 等待移动完成
err = flex_wait_on_condition(boardID, 0, NIMC_WAIT, NIMC_CONDITION_MOVE_COMPLETE, (u8)(1<<axis)/*指示等待的轴*/,
0, NIMC_MATCH_ALL, 3000 /*超时*/, 0);
CheckError;
// 将变量1(即目标位置)与变量2(即乘数)相乘
// 将结果保存在变量1中 - 这计算了上一个目标位置的负值
err = flex_mult_vars(boardID, 1, 2, 1);
CheckError;
// 在移动完成状态寄存器中设置第13位,以便主机知道轴即将改变方向
err = flex_set_status_momo(boardID, 0x20, 0);
CheckError;
// 无条件跳转到加载新目标位置
err = flex_jump_label_on_condition (boardID, 0, NIMC_CONDITION_TRUE, 0, 0, NIMC_MATCH_ALL, 1/*标签编号*/);
CheckError;
// 结束程序存储
err = flex_end_store(boardID, 1);
CheckError;
//--------------------------------------------------------
// 主机程序。此程序监控移动完成状态寄存器中的第13位,并记录轴将要移动到的位置
//--------------------------------------------------------
do
{
// 检查移动完成状态/后续错误/轴关闭状态
err = flex_read_axis_status_rtn(boardID, axis, &axisStatus);
CheckError;
// 读取通信状态寄存器并检查模态错误
err = flex_read_csr_rtn(boardID, &csr);
CheckError;
// 检查模态错误
if (csr & NIMC_MODAL_ERROR_MSG)
{
err = csr & NIMC_MODAL_ERROR_MSG;
CheckError;
}
// 读取移动完成状态寄存器,一旦第13位被设置
// 重置该位并读取目标位置
err = flex_read_mcs_rtn(boardID, &moveCompleteStatus);
CheckError;
if(moveCompleteStatus & (1<<13)){
i32 currentTargetPosition;
// 在移动完成状态寄存器中重置第13位
err = flex_set_status_momo(boardID, 0, 0x20);
CheckError;
err = flex_read_var_rtn(boardID, 1, ¤tTargetPosition);
CheckError;
}
Sleep (50); //每50毫秒检查一次
}while (!(axisStatus & NIMC_FOLLOWING_ERROR_BIT) && !(axisStatus & NIMC_AXIS_OFF_BIT)); //在移动完成/后续错误/轴关闭时退出
return; // 退出应用程序
/
// 错误处理
nimcHandleError; //NIMCCATCHTHIS:
// 检查是否有任何模态错误
if (csr & NIMC_MODAL_ERROR_MSG){
do{
//从板卡上的错误堆栈中获取模态错误的命令ID、资源和错误代码
flex_read_error_msg_rtn(boardID,&commandID,&resourceID,&errorCode);
nimcDisplayError(errorCode,commandID,resourceID);
//读取通信状态寄存器
flex_read_csr_rtn(boardID,&csr);
}while(csr & NIMC_MODAL_ERROR_MSG);
}
else // 显示常规错误
nimcDisplayError(err,0,0);
return; // 退出应用程序
}
程序执行流程图: