基于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;
}
- /****************************************************************************/
以上是关于基于igh Master 主站协议栈的一个测试用例源码分析的主要内容,如果未能解决你的问题,请参考以下文章
基于ZYNQAM5728AM5708AM437xAM335xSTM32+FPGA等平台提供了开源EtherCAT主站IgH案例
Beaglebone Black中安装EtherCAT主站IGH方法