igh ethercat应用层代码分析

igh ethercat可以自己编写应用层代码与从站进行数据交互,本身主站给了例子,在example文件夹下,根据自己平台选择看某个例子,一般刚开始可以看user文件夹下的main.c文件,下面是我进行了一些修改,也带了一些解释。其实也就是控制io做流水灯操作。

//gcc test.c -o test.out -I/opt/etherlab/include -L/opt/etherlab/lib/ -lethercat
#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// Optional features
#define CONFIGURE_PDOS  1/****************************************************************************/// EtherCAT
static ec_master_t *master = NULL;
static ec_master_state_t master_state = {};static ec_domain_t *domain1 = NULL;
static ec_domain_state_t domain1_state = {};static ec_slave_config_t *sc_dig_out = NULL;
static ec_slave_config_state_t sc_dig_out_state = {};// Timer
static unsigned int sig_alarms = 0;
static unsigned int user_alarms = 0;/****************************************************************************/// process data
static uint8_t *domain1_pd = NULL;#define BusCouplerPos  0, 0  //alias,position
#define DigOutSlavePos 0, 1#define Beckhoff_EK9100 0x0000001a, 0x09139100       //vendor ID,product code
#define Beckhoff_EL2016 0x0000001a, 0x09132016static unsigned int Dig_out=1;// offsets for PDO entries
static unsigned int off_dig_out;const static ec_pdo_entry_reg_t domain1_regs[] = {{DigOutSlavePos, Beckhoff_EL2016, 0x3001, 1, &off_dig_out},{}
};static unsigned int counter = 0;
static unsigned int blink = 0;/*****************************************************************************/#if CONFIGURE_PDOS// Digital out ------------------------static ec_pdo_entry_info_t el2016_channels[] = {{0x3001, 1, 1}, // Value 1{0x3001, 2, 1}, // Value 2{0x3001, 3, 1}, // Value 3{0x3001, 4, 1}, // Value 4{0x3001, 5, 1}, // Value 5{0x3001, 6, 1}, // Value 6{0x3001, 7, 1}, // Value 7{0x3001, 8, 1}  // Value 8
};static ec_pdo_info_t el2016_pdos[] = {{0x1600, 8, el2016_channels},
};static ec_sync_info_t el2016_syncs[] = {{0, EC_DIR_OUTPUT, 1, el2016_pdos},{0xff}
};
#endif/*****************************************************************************/void check_domain1_state(void)
{ec_domain_state_t ds;ecrt_domain_state(domain1, &ds);if (ds.working_counter != domain1_state.working_counter)printf("Domain1: WC %u.\n", ds.working_counter);if (ds.wc_state != domain1_state.wc_state)printf("Domain1: State %u.\n", ds.wc_state);domain1_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_dig_out, &s);if (s.al_state != sc_dig_out_state.al_state)printf("DigOut: State 0x%02X.\n", s.al_state);if (s.online != sc_dig_out_state.online)printf("DigOut: %s.\n", s.online ? "online" : "offline");if (s.operational != sc_dig_out_state.operational)printf("output: %soperational.\n",s.operational ? "" : "Not ");sc_dig_out_state = s;
}/*****************************************************************************/void cyclic_task()
{// receive process dataecrt_master_receive(master);ecrt_domain_process(domain1);// check process data state (optional)check_domain1_state();if (counter) {counter--;} else { // do this at 1 Hzcounter = FREQUENCY;// check for master state (optional)check_master_state();// check for islave configuration state(s) (optional)check_slave_config_states();}// write process datablink++;
if(blink==100){if(Dig_out<0x100){Dig_out=Dig_out*2;}else{Dig_out=1;}blink=0;
}EC_WRITE_U8(domain1_pd + off_dig_out, Dig_out);// send process dataecrt_domain_queue(domain1);ecrt_master_send(master);
}/****************************************************************************/void signal_handler(int signum) {//进程收到定时信号所做的操作switch (signum) {case SIGALRM:sig_alarms++;break;}
}/****************************************************************************/int main(int argc, char **argv)
{ec_slave_config_t *sc;// 存放从站配置的结构体struct sigaction sa;// 描述信号到达时要采取的操作的结构体struct itimerval tv;//计算时间,用于定时的结构体master = ecrt_request_master(0);// 请求EtherCAT主机进行实时操作。if (!master)   return -1;domain1 = ecrt_master_create_domain(master);// 创建新的进程数据域if (!domain1)return -1;printf("Configuring PDOs...\n");if (!(sc_dig_out = ecrt_master_slave_config(//获取从站配置master, DigOutSlavePos, Beckhoff_EL2016))) {//第一个参数是所请求的主站实例,第二个包括主站的别名和位置,第三个包括供应商码和产品码fprintf(stderr, "Failed to get slave configuration.\n");return -1;}if (ecrt_slave_config_pdos(sc_dig_out, EC_END, el2016_syncs)) {//指定完整的PDO配置。第一个参数是获取的从站配置,第二个参数表示同步管理器配置数,EC_END=~u0,第三个参数表示同步管理器配置数组fprintf(stderr, "Failed to configure PDOs.\n");return -1;}// Create configuration for bus couplersc = ecrt_master_slave_config(master, BusCouplerPos, Beckhoff_EK9100);if (!sc)return -1;if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {//为进程数据域注册一组PDO项。参数一:创建的进程数据域,参数二:pdo注册数组fprintf(stderr, "PDO entry registration failed!\n");return -1;}printf("Activating master...\n");if (ecrt_master_activate(master))// 激活主站return -1;if (!(domain1_pd = ecrt_domain_data(domain1))) {//返回域的进程数据return -1;}#if PRIORITYpid_t pid = getpid();//获得进程PIDif (setpriority(PRIO_PROCESS, pid, -19))//设置进程优先级fprintf(stderr, "Warning: Failed to set priority: %s\n",strerror(errno));
#endifsa.sa_handler = signal_handler;//指定信号关联函数sigemptyset(&sa.sa_mask);// 初始化给出的信号集为空sa.sa_flags = 0;if (sigaction(SIGALRM, &sa, 0)) {//系统调用,用于更改进程在收到特定信号时采取的操作fprintf(stderr, "Failed to install signal handler!\n");return -1;}printf("Starting timer...\n");tv.it_interval.tv_sec = 0;//next timetv.it_interval.tv_usec = 1000000 / FREQUENCY;tv.it_value.tv_sec = 0;//current timetv.it_value.tv_usec = 1000;if (setitimer(ITIMER_REAL, &tv, NULL)) {//定时功能,以系统真实的时间来计算,每隔一段时间送出SIGALRM信号。fprintf(stderr, "Failed to start timer: %s\n", strerror(errno));return 1;}printf("Started.\n");while (1) {pause();//挂起,等待cpu唤醒while (sig_alarms != user_alarms) {//意思是每过一段时间才会执行一次,而不是一直死循环cyclic_task();user_alarms++;}}return 0;
}/****************************************************************************//**
先定义一些结构体,其中有存放从站配置的结构体,类型为ec_slave_config_t{},用在接收函数ecrt_master_slave_config()的返回值;用在描述信号到达时要采取的操作的结构体struct sigaction{};计算时间,用于定时的结构体struct itimerval{}。下面是关于主站和从站的一些配置
1. 请求EtherCAT主机进行操作,我感觉可以认为是创建一个主站实例对象。
2. 创建进程数据域。
3. 获取从站配置
4. 指定完整的pdo配置
5. 为进程数据域注册一组PDO项。
6. 激活主站
7. 返回域的进程数据
8. 可选选项:设置进程优先级
9. 可选选项:指定进程收到某种信号采取的操作
10. 可选选项:设置定时发送信号
11. 进入循环,开始循环任务其中对于几个可选选项,设置优先级,是为了让实时性更好;另外两个定时发送的信号作为进程采取操作的条件,而操作内容又作为循环任务的周期时间间隔,不对,这两个并不再是可选项,应该必须要设置的,周期交换数据的时间间隔要大于等于从站处理 数据和传输等时间总和。下面是在循环任务中做的事情:
1. 从硬件获取接收的帧并处理数据报。
2. 确定域数据报的状态。
3. 检查域的状态(可选项)
4. 周期性检查主站状态和从站配置状态(可选项)
5. 计算将要发送流水灯数据和数据改变周期大小
6. 将数据放入数据域
7. 将主数据报队列中的所有域数据报排队
8. 发送队列中的所有数据报。其中对于配置PDO所涉及到的几个结构体
typedef struct {uint16_t index; /**< PDO entry index. */uint8_t subindex; /**< PDO entry subindex. */uint8_t bit_length; /**< Size of the PDO entry in bit. */
} ec_pdo_entry_info_t;typedef struct {uint16_t index; /**< PDO index. */unsigned int n_entries; /**< Number of PDO entries in entries to map.Zero means, that the default mapping shall beused (this can only be done if the slave ispresent at bus configuration time). */ec_pdo_entry_info_t *entries; /**< Array of PDO entries to map. Can                                                         either be NULL, or must contain atleast n_entries values. */
} ec_pdo_info_t;typedef struct {uint8_t index; /**< Sync manager index. Must be lessthan #EC_MAX_SYNC_MANAGERS for a valid sync manager,but can also be 0xff to mark the end of the list. */ec_direction_t dir; /**< Sync manager direction. */unsigned int n_pdos; /**< Number of PDOs in pdos. */ec_pdo_info_t *pdos; /**< Array with PDOs to assign. This must containat least n_pdos PDOs. */ec_watchdog_mode_t watchdog_mode; /**< Watchdog mode. */
} ec_sync_info_t;typedef struct {uint16_t alias; /**< Slave alias address. */uint16_t position; /**< Slave position. */uint32_t vendor_id; /**< Slave vendor ID. */uint32_t product_code; /**< Slave product code. */uint16_t index; /**< PDO entry index. */uint8_t subindex; /**< PDO entry subindex. */unsigned int *offset; /**< Pointer to a variable to store the PDO                    entry's(byte-)offset in the process data. */unsigned int *bit_position; /**< Pointer to a variable to store a bitposition (0-7) within the offset. Can beNULL, in which case an error is raised if                                                the PDO entry does not byte-align. */
} ec_pdo_entry_reg_t;#define EC_WRITE_U8(DATA, VAL) \do { \*((uint8_t *)(DATA)) = ((uint8_t) (VAL)); \} while (0)*/

igh ethercat应用层代码分析相关推荐

  1. Igh EtherCAT Master 补丁推荐

    如果大家采用 Igh EtherCAT 开源代码做 EtherCAT 主站开发,这里有一个很好的针对 1.5.2 版的补丁:uecasm / Etherlab Master - Patches / [ ...

  2. igh ethercat主站文档(中文翻译上)

    此翻译主要是用翻译软件翻译,部分自己修改,若有不当之处,可以下方评论或私聊我提醒修改,若转载,请注明出处 本文是1-4章节. 1 The IgH EtherCAT Master 本章介绍有关Ether ...

  3. AUTOSAR从入门到精通100讲(三十五)-Lin通信协议栈分析三部曲LinTrcv配置及代码分析

    LinTrcv 0.Lin通信协议栈简介: LIN通信服务是一组用于与LIN通信系统进行车辆网络通信的模块.提供统一的LIN网络接口.对应用层程序隐藏协议信息和消息属性的特性. Lin通信服务包括: ...

  4. OpenAVNU 带宽预留协议SRP代码分析

    OpenAVNU 带宽预留协议SRP代码分析 AVNU AVNU由专业的汽车,消费电子和工业制造公司组成的联盟,它们共同致力于建立开放AVB和TSN标准的互操作性的认证. OpenAVNU AVNU在 ...

  5. 05-SA8155 QNX I2C框架及代码分析

    1. 描述 本文主要描述QNX I2C Drvier的相关内容,并以SA8155处理器为例讲解. I2C 是经常用到的一种总线协议,它只占用两个IO口资源,分别是SCL时钟信号线与SDA数据线, 两根 ...

  6. OAI项目GDB调试及代码分析

    OAI项目GDB调试及代码分析 如果想使用GDB调试工具对项目进行调试,首先需要在编译时加入调试信息. 在完成之前的对eNB和UE的编译之后,使用作者写的编译脚本,同时加上-g选项加入调试信息 ./c ...

  7. IGH EtherCAT Master安装记录

    前言 IGH EtherCAT Master的1.5.2版本中没有.bootstrap文件,如果只运行.configure文件后续会报错,所以在安装时选取了最近的stable-1.5.IGH源码下载地 ...

  8. 20145236《网络攻防》Exp4 恶意代码分析

    20145236<网络攻防>Exp4 恶意代码分析 一.基础问题回答 如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监控下系统一天天的到底在干些什么.请设计下你想监控的操作有哪些 ...

  9. C#中类的继承 override virtual new的作用以及代码分析

    继承中override virtual new的作用 virtual 父类中需要注明允许重写的方法: override 子类中必须显示声明该方法是重写的父类中的方法: new 子类中忽略父类的已存在的 ...

最新文章

  1. java 指令重拍_我发现我的Java重拍了!
  2. day30 并发编程
  3. 计算机丢失lib.dll,libprotobuf.dll
  4. ndk android studio万年坑
  5. 【Linux】Vi中的各种命令
  6. java中插入排序_Java中的插入排序
  7. 【同行说技术】Python开发、调试、爬虫类工具大全
  8. OpenStack之VM东西南北向流量分析
  9. 微信小程序tab切换效果
  10. layui prompt弹窗验证码操作
  11. 1年工作经验的C++程序员,感悟分享
  12. PEEKABOO——alpha冲刺置顶集合随笔
  13. 终极事务处理(XTP,Hekaton)——万能大招?
  14. 天数最少的年份_农历辛丑年仅有354天是怎么回事 平年比闰年少几天
  15. 计算机组成原理课程设计报告书
  16. CityMaker学习教程08 一个示例,创建漫游路径
  17. 美术改画系列-张聪-专题视频课程
  18. 《量子信息与量子计算简明教程》第三章·量子纠缠状态及其应用 (上)
  19. Ubuntu下U盘没有不能新建粘贴文件 报错 [sdf] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
  20. 单片机毕业设计 stm32智能电子秤系统设计与实现 - 物联网 嵌入式

热门文章

  1. 湖南工学院 戴成秋 计算机,【计算机专业论文】教师胜任力模型计算机专业论文(共1840字)...
  2. 串口服务器的作用和工作原理是什么
  3. Learning Synergies between Pushing and Grasping with Self-supervised Deep Reinforcement Learning
  4. 对抗人脸识别的一个新方法:隐藏身份、随机换脸
  5. 推荐几个黑白照片上色软件给大家
  6. Signal Tap Logic Analyzer的stp文件制作及添加到编译工程
  7. 苹果手机丢了如何通过定位找回?iPhone手机丢失定位找回方法
  8. iPhone开启的「查找」功能怎么操作
  9. 用Python解析HTML,BeautifulSoup使用简介
  10. 365天挑战LeetCode1000题——Day 154 Knight