基于igh Master 主站协议栈的一个测试用例源码分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于igh Master 主站协议栈的一个测试用例源码分析相关的知识,希望对你有一定的参考价值。

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

/****************************************************************************/

#include "ecrt.h"

/****************************************************************************/

// Application parameters
#define FREQUENCY 100
#define PRIORITY 1

/****************************************************************************/

// EtherCAT
static ec_master_t *master = NULL;
static ec_master_state_t master_state = {};

static ec_domain_t *domainInput = NULL;
static ec_domain_state_t domainInput_state = {};

static ec_domain_t *domainOutput = NULL;
static ec_domain_state_t domainOutput_state = {};

static ec_slave_config_t *sc_motor = NULL;
static ec_slave_config_state_t sc_motor_state = {};

// Timer
static unsigned int sig_alarms = 0;
static unsigned int user_alarms = 0;

/****************************************************************************/
/* Master 0, Slave 1, "EL2008"
 * Vendor ID:        0x00000002
 * Product code:     0x07d83052
 * Revision number:  0x00100000
 */

 ec_pdo_entry_info_t slave_1_pdo_entries[] = {
     {0x7000, 0x01, 1}, /*Output */
     {0x7010, 0x01, 1}, /*Output */
     {0x7020, 0x01, 1}, /*Output */
     {0x7030, 0x01, 1}, /*Output */
     {0x7040, 0x01, 1}, /*Output */
     {0x7050, 0x01, 1}, /*Output */
     {0x7060, 0x01, 1}, /*Output */
     {0x7070, 0x01, 1}, /*Output */
 };

 ec_pdo_into_t slave_1_pdos[] = {
     {0x1600, 1, slave_1_pdo_entries + 0}, /* Channel 1 */
     {0x1601, 1, slave_1_pdo_entries + 1}, /* Channel 2 */
     {0x1602, 1, slave_1_pdo_entries + 2}, /* Channel 3 */
     {0x1603, 1, slave_1_pdo_entries + 3}, /* Channel 4 */
     {0x1604, 1, slave_1_pdo_entries + 4}, /* Channel 5 */
     {0x1605, 1, slave_1_pdo_entries + 5}, /* Channel 6 */
     {0x1606, 1, slave_1_pdo_entries + 6}, /* Channel 7 */
     {0x1607, 1, slave_1_pdo_entries + 7}, /* Channel 8 */
 };

 ec_sync_info_t slave_1_syncs[] = {
     {0, EC_DIR_OUTPUT, 8, slave_1_pdos + 0, EC_WD_ENABLE},
     {0xff}
 }

/* Master 0, Slave 2, "EL1008"
 * Vendor ID:        0x00000002
 * Product code:     0x03f03052
 * Revision number:  0x00100000
 */

 ec_pdo_entry_info_t slave_2_pdo_entries[] = {
     {0x6000, 0x01, 1}, /*Input */
     {0x6010, 0x01, 1}, /*Input */
     {0x6020, 0x01, 1}, /*Input */
     {0x6030, 0x01, 1}, /*Input */
     {0x6040, 0x01, 1}, /*Input */
     {0x6050, 0x01, 1}, /*Input */
     {0x6060, 0x01, 1}, /*Input */
     {0x6070, 0x01, 1}, /*Input */
 };

 ec_pdo_into_t slave_2_pdos[] = {
     {0x1a00, 1, slave_2_pdo_entries + 0}, /* Channel 1 */
     {0x1a01, 1, slave_2_pdo_entries + 1}, /* Channel 2 */
     {0x1a02, 1, slave_2_pdo_entries + 2}, /* Channel 3 */
     {0x1a03, 1, slave_2_pdo_entries + 3}, /* Channel 4 */
     {0x1a04, 1, slave_2_pdo_entries + 4}, /* Channel 5 */
     {0x1a05, 1, slave_2_pdo_entries + 5}, /* Channel 6 */
     {0x1a06, 1, slave_2_pdo_entries + 6}, /* Channel 7 */
     {0x1a07, 1, slave_2_pdo_entries + 7}, /* Channel 8 */
 };

 ec_sync_info_t slave_2_syncs[] = {
     {0, EC_DIR_INPUT, 8, slave_2_pdos + 0, EC_WD_DISABLE},
     {0xff}
 }
/****************************************************************************/
// process data
static uint8_t *domainOutput_pd = NULL;
static uint8_t *domainInput_pd = NULL;

#define MotorSlavePos 0, 0
#define Delta_ASDAA2 0x000001dd, 0x10305070

// offsets for PDO entries
static unsigned int asdaa2_cntlwd;
static unsigned int asdaa2_tarvel;
static unsigned int asdaa2_tarpos;
static unsigned int asdaa2_provel;
static unsigned int asdaa2_proacc;
static unsigned int asdaa2_prodec;
static unsigned int asdaa2_maxvel;
static unsigned int asdaa2_maxspd;
static unsigned int asdaa2_mottyp;
static unsigned int asdaa2_modeop;
static unsigned int asdaa2_status;
static unsigned int asdaa2_actpos;
static unsigned int asdaa2_actvel;
static unsigned int asdaa2_acttor;
static unsigned int asdaa2_modedp;

const static ec_pdo_entry_reg_t domainOutput_regs[] = {
 { MotorSlavePos, Delta_ASDAA2, 0x607F, 0, &asdaa2_maxvel },
 { MotorSlavePos, Delta_ASDAA2, 0x6080, 0, &asdaa2_maxspd },
 { MotorSlavePos, Delta_ASDAA2, 0x60FF, 0, &asdaa2_tarvel },
 { MotorSlavePos, Delta_ASDAA2, 0x607A, 0, &asdaa2_tarpos },
 { MotorSlavePos, Delta_ASDAA2, 0x6081, 0, &asdaa2_provel },
 { MotorSlavePos, Delta_ASDAA2, 0x6040, 0, &asdaa2_cntlwd },
 { MotorSlavePos, Delta_ASDAA2, 0x6086, 0, &asdaa2_mottyp },
 { MotorSlavePos, Delta_ASDAA2, 0x6060, 0, &asdaa2_modeop },
 {}
};

const static ec_pdo_entry_reg_t domainInput_regs[] = {
 { MotorSlavePos, Delta_ASDAA2, 0x6064, 0, &asdaa2_actpos },
 { MotorSlavePos, Delta_ASDAA2, 0x606C, 0, &asdaa2_actvel },
 { MotorSlavePos, Delta_ASDAA2, 0x6041, 0, &asdaa2_status },
 { MotorSlavePos, Delta_ASDAA2, 0x6077, 0, &asdaa2_acttor },
 { MotorSlavePos, Delta_ASDAA2, 0x6061, 0, &asdaa2_modedp },
 {}
};

static unsigned int counter = 0;

/*****************************************************************************/
static ec_pdo_entry_info_t asdaa2_pdo_entries_output[] = {
 { 0x607F, 0x00, 32 },
 { 0x6080, 0x00, 32 },
 { 0x60FF, 0x00, 32 },
 { 0x607A, 0x00, 32 },
 { 0x6081, 0x00, 32 },
 { 0x6040, 0x00, 16 },
 { 0x6086, 0x00, 16 },
 { 0x6060, 0x00, 8 },
};

static ec_pdo_entry_info_t asdaa2_pdo_entries_input[] = {
 { 0x6064, 0x00, 32 },
 { 0x606C, 0x00, 32 },
 { 0x6041, 0x00, 16 },
 { 0x6077, 0x00, 16 },
 { 0x6061, 0x00, 8 },
};

static ec_pdo_info_t asdaa2_pdo_1600[] = {
 { 0x1600, 8, asdaa2_pdo_entries_output },
};

static ec_pdo_info_t asdaa2_pdo_1a00[] = {
 { 0x1A00, 5, asdaa2_pdo_entries_input },
};

static ec_sync_info_t asdaa2_syncs[] = {
 { 0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE },
 { 1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE },
 { 2, EC_DIR_OUTPUT, 1, asdaa2_pdo_1600, EC_WD_DISABLE },
 { 3, EC_DIR_INPUT, 1, asdaa2_pdo_1a00, EC_WD_DISABLE },
 { 0xff }
};

/*****************************************************************************/

void check_domain_state(void)
{
 ec_domain_state_t ds;

 ecrt_domain_state(domainOutput, &ds);

 if (ds.working_counter != domainOutput_state.working_counter)
  printf("domainOutput: WC %u.\n", ds.working_counter);
 if (ds.wc_state != domainOutput_state.wc_state)
  printf("domainOutput: State %u.\n", ds.wc_state);

 domainOutput_state = ds;

 ecrt_domain_state(domainInput, &ds);

 if (ds.working_counter != domainInput_state.working_counter)
  printf("domainInput: WC %u.\n", ds.working_counter);
 if (ds.wc_state != domainInput_state.wc_state)
  printf("domainInput: State %u.\n", ds.wc_state);

 domainInput_state = ds;
}

/*****************************************************************************/

void check_master_state(void)
{
 ec_master_state_t ms;

 ecrt_master_state(master, &ms);

 if (ms.slaves_responding != master_state.slaves_responding)
  printf("%u slave(s).\n", ms.slaves_responding);
 if (ms.al_states != master_state.al_states)
  printf("AL states: 0x%02X.\n", ms.al_states);
 if (ms.link_up != master_state.link_up)
  printf("Link is %s.\n", ms.link_up ? "up" : "down");

 master_state = ms;
}

/*****************************************************************************/

void check_slave_config_states(void)
{
 ec_slave_config_state_t s;
 ecrt_slave_config_state(sc_motor, &s);

 if (s.al_state != sc_motor_state.al_state)
  printf("Motor: State 0x%02X.\n", s.al_state);
 if (s.online != sc_motor_state.online)
  printf("Motor: %s.\n", s.online ? "online" : "offline");
 if (s.operational != sc_motor_state.operational)
  printf("Motor: %soperational.\n",
  s.operational ? "" : "Not ");

 sc_motor_state = s;

}

/****************************************************************************/

void cyclic_task()
{
 // receive process data
 ecrt_master_receive(master);
 ecrt_domain_process(domainOutput);
 ecrt_domain_process(domainInput);

 // check process data state (optional)
 check_domain_state();

 if (counter) {
  counter--;
 }
 else { // do this at 1 Hz
  counter = FREQUENCY;

  // check for master state (optional)
  check_master_state();

  // check for islave configuration state(s) (optional)
  check_slave_config_states();

  printf("pos = %d\n", EC_READ_S32(domainInput_pd + asdaa2_actpos));
  printf("vel = %d\n", EC_READ_S32(domainInput_pd + asdaa2_actvel));
 }

 static int state = -500;
 state++;
 switch (state){
 case -1:
  printf("-1\n");
  EC_WRITE_U16(domainOutput_pd + asdaa2_cntlwd, 0x80);
  break;
 case 0:
  printf("0\n");
  EC_WRITE_S8(domainOutput_pd + asdaa2_modeop, 1);
  EC_WRITE_U32(domainOutput_pd + asdaa2_provel, 9000000);
  break;
 case 3:
  printf("3\n");
  EC_WRITE_U16(domainOutput_pd + asdaa2_cntlwd, 0x06);
  break;
 case 4:
  printf("4\n");
  EC_WRITE_U16(domainOutput_pd + asdaa2_cntlwd, 0x07);
  break;
 case 5:
  printf("5\n");
  EC_WRITE_U16(domainOutput_pd + asdaa2_cntlwd, 0xF);
  break;
 }

 if (state > 100){
  if (state % 300 == 0)
   EC_WRITE_U16(domainOutput_pd + asdaa2_cntlwd, 0xB);
  if (state % 300 == 5 && state % 600 != 5){
   printf(" \n");
   EC_WRITE_S32(domainOutput_pd + asdaa2_tarpos, 0x11111111);
  }
  else if (state % 600 == 5){
   printf("-\n");
   EC_WRITE_S32(domainOutput_pd + asdaa2_tarpos, 0xFFFFFFFFEEEEEEEF);
  }
  if (state % 300 == 6)
   EC_WRITE_U16(domainOutput_pd + asdaa2_cntlwd, 0x7F);
 }

 // send process data
 ecrt_domain_queue(domainOutput);
 ecrt_domain_queue(domainInput);
 ecrt_master_send(master);
}

/****************************************************************************/
int main(int argc, char **argv)
{
 // Requests an EtherCAT master for realtime operation.
 master = ecrt_request_master(
  0); // Index of the master to request.
 if (!master)
  return -1;

 // Creates a new process data domain
 domainOutput = ecrt_master_create_domain(master);
 if (!domainOutput)
  return -1;
 domainInput = ecrt_master_create_domain(master);
 if (!domainInput)
  return -1;

 // Obtains a slave configuration
 if (!(sc_motor = ecrt_master_slave_config(
  master, MotorSlavePos, Delta_ASDAA2))) {
  fprintf(stderr, "Failed to get slave configuration.\n");
  return -1;
 }

 // Configuring PDOs
 printf("Configuring PDOs...\n");
 if (ecrt_slave_config_pdos(sc_motor, EC_END, asdaa2_syncs)) {
  fprintf(stderr, "Failed to configure PDOs.\n");
  return -1;
 }

 if (ecrt_domain_reg_pdo_entry_list(domainOutput, domainOutput_regs)) {
  fprintf(stderr, "PDO entry registration failed!\n");
  return -1;
 }

 if (ecrt_domain_reg_pdo_entry_list(domainInput, domainInput_regs)) {
  fprintf(stderr, "PDO entry registration failed!\n");
  return -1;
 }

 printf("Activating master...\n");
 if (ecrt_master_activate(master))
  return -1;

 if (!(domainOutput_pd = ecrt_domain_data(domainOutput))) {
  return -1;
 }

 if (!(domainInput_pd = ecrt_domain_data(domainInput))) {
  return -1;
 }

 printf("Started.\n");
 while (1) {
  usleep(1000000 / FREQUENCY);
  cyclic_task();
 }
 return 0;
}

  1. /****************************************************************************/

以上是关于基于igh Master 主站协议栈的一个测试用例源码分析的主要内容,如果未能解决你的问题,请参考以下文章

基于ZYNQAM5728AM5708AM437xAM335xSTM32+FPGA等平台提供了开源EtherCAT主站IgH案例

SylixOS上EtherCAT实现

Beaglebone Black中安装EtherCAT主站IGH方法

IgH设置EtherCAT数据流程

基于 FPGA verilog 的 Ethercat 主站工程代码

IgH Master 1.5.2 Documentation 中文版