CANOpen EMCY紧急报文介绍

news2024/12/22 20:16:27

什么是CANOpen紧急报文

CANOpen中的Emcy紧急报文用于当设备出现故障或警告时,向其它节点报告故障或警告使用的。如设备某个设备出现过压或过流时,就可以发送紧急报文。

紧急报文的格式

在这里插入图片描述
错误代码:是0x1003索引预定义错误字段的内容,是16bit详细的错误代码
错误寄存器:是0x1001索引当前错误状态的内容,是8bit,每个bit代表一个含义,粗略的表示设备故障方向。

CANFestival 如何发送紧急报文,

当节点出现故障时,调用UNS8 EMCY_setError(CO_Data* d, UNS16 errCode, UNS8 errRegMask, UNS16 addInfo)函数发送紧急报文。

/*! Sets a new error with code errCode. Also sets corresponding bits in Error register (1001h)
 **                                                                                                 
 **  
 ** @param d
 ** @param errCode Code of the error                                                                                        
 ** @param errRegister Bits of Error register (1001h) to be set.
 ** @return 1 if error, 0 if successful
 */
UNS8 EMCY_setError(CO_Data* d, UNS16 errCode, UNS8 errRegMask, UNS16 addInfo)
{
	UNS8 index;
	UNS8 errRegister_tmp;
	
	for (index = 0; index < EMCY_MAX_ERRORS; ++index)
	{
		if (d->error_data[index].errCode == errCode)		/* error already registered */
		{
			if (d->error_data[index].active)
			{
				MSG_WAR(0x3052, "EMCY message already sent", 0);
				return 0;//错误已注册已发送直接返回
			} else d->error_data[index].active = 1;		/*已注册但还未发送 将active置1*/ /* set as active error */
			break;
		}
	}
	
	if (index == EMCY_MAX_ERRORS)	/*进了这个if表示错误代码还没注册*/	/* if errCode not already registered */
		for (index = 0; index < EMCY_MAX_ERRORS; ++index) if (d->error_data[index].active == 0) break;	/* find first inactive error */
	
	if (index == EMCY_MAX_ERRORS)		/* error_data full */
	{
		MSG_ERR(0x3053, "error_data full", 0);
		return 1;
	}
	
	d->error_data[index].errCode = errCode;
	d->error_data[index].errRegMask = errRegMask;
	d->error_data[index].active = 1;
	
	/* set the new state in the error state machine */
	d->error_state = Error_occurred;//将对象字典中的错误状态标记为错误发生

	/* set Error Register (1001h) */
	for (index = 0, errRegister_tmp = 0; index < EMCY_MAX_ERRORS; ++index)
		if (d->error_data[index].active == 1) errRegister_tmp |= d->error_data[index].errRegMask;
	*d->error_register = errRegister_tmp;//修改了索引0x1001的内容
	
	/* set Pre-defined Error Field (1003h) */
	for (index = d->error_history_size - 1; index > 0; --index)//for循环的将0x1003索引的错误代码向后滑动一个
		*(d->error_first_element + index) = *(d->error_first_element + index - 1);
	*(d->error_first_element) = errCode | ((UNS32)addInfo << 16);//将新的错误代码设置到最前边的索引
	if(*d->error_number < d->error_history_size) ++(*d->error_number);//错误个数自增
	
	/* send EMCY message */
	if (d->CurrentCommunicationState.csEmergency)//如果当前通信状态下emcy紧急报文服务是支持的则发送
		return sendEMCY(d, errCode, *d->error_register, NULL, 0);
	else return 1;
}

使用该函数时一定要注意,同一个错误代码,只发送一次。因为源码中判断错误代码已经注册到0x1003索引的,并且已经发送的则不再发送。到了这里可能有人有疑问了,假设这样一种情况:设备在运行过程中,某一时候设备过压,发送了紧急报文,然后故障解除,在之后的一段时间再次出现设备过压,这岂不是就无法再次发送紧急报文了吗?别急,这就说到了下边要介绍的内容,如何解除故障。

CANFestival 如何解除故障

当设备某个故障解除的时候,用户调用void EMCY_errorRecovered(CO_Data* d, UNS16 errCode)函数解除这个故障状态。

/*! Deletes error errCode. Also clears corresponding bits in Error register (1001h)
 **                                                                                                 
 **  
 ** @param d
 ** @param errCode Code of the error                                                                                        
 ** @param errRegister Bits of Error register (1001h) to be set.
 ** @return 1 if error, 0 if successful
 */
void EMCY_errorRecovered(CO_Data* d, UNS16 errCode)
{
	UNS8 index;
	UNS8 errRegister_tmp;
	UNS8 anyActiveError = 0;
	
	for (index = 0; index < EMCY_MAX_ERRORS; ++index)
		if (d->error_data[index].errCode == errCode) break;		/* find the position of the error */

	
	if ((index != EMCY_MAX_ERRORS) && (d->error_data[index].active == 1))
	{
		d->error_data[index].active = 0;//上边的for循环找到故障代码的位置 这里将其active标记为0表示该故障已解除
		
		/* set Error Register (1001h) and check error state machine */
		for (index = 0, errRegister_tmp = 0; index < EMCY_MAX_ERRORS; ++index)
			if (d->error_data[index].active == 1)
			{
				anyActiveError = 1;//标记还有其它故障
				errRegister_tmp |= d->error_data[index].errRegMask;
			}
		if(anyActiveError == 0)//判断有没有其他故障
		{
			d->error_state = Error_free;
			/* send a EMCY message with code "Error Reset or No Error" */
			if (d->CurrentCommunicationState.csEmergency)
				sendEMCY(d, 0x0000, 0x00, NULL, 0);//如果所有的故障都解除了就发送一个8字节全0的紧急报文
		}
		*d->error_register = errRegister_tmp;
	}
	else
		MSG_WAR(0x3054, "recovered error was not active", 0);
}

解除的核心就是将active 字段设置为0。解除以后如果再次发生同样的故障就可以调用EMCY_errorRecovered函数继续发送紧急报文了

CANFestival处理接收到的紧急报文

当CANFestival协议栈收到紧急报文就会调用void proceedEMCY(CO_Data* d, Message* m)函数去处理接收到的紧急报文。

/*! This function is responsible to process an EMCY canopen-message.
 **
 **
 ** @param d
 ** @param m The CAN-message which has to be analysed.
 **
 **/
void proceedEMCY(CO_Data* d, Message* m)
{
	UNS8 nodeID;
	UNS16 errCode;
	UNS8 errReg;
	
	MSG_WAR(0x3055, "EMCY received. Proceed. ", 0);
  
	/* Test if the size of the EMCY is ok */
	if ( m->len != 8) {
		MSG_ERR(0x1056, "Error size EMCY. CobId  : ", m->cob_id);
		return;
	}
	
	/* post the received EMCY */
	nodeID = m->cob_id & 0x7F;
	errCode = m->Data[0] | ((UNS16)m->Data[1] << 8);
	errReg = m->Data[2];
	(*d->post_emcy)(d, nodeID, errCode, errReg);//调用回调函数,具体的动作留给用户实现
}

当处理完紧急报文会执行回调函数,具体要做什么处理由用户决定。

CANFestival紧急报文回调函数实现

void _post_emcy(CO_Data* d, UNS8 nodeID, UNS16 errCode, UNS8 errReg)
{
	printf("%s\r\n",__FUNCTION__);//收到emcy 紧急报文会执行这个回调函数
}

紧急报文概念不抽象,源码实现也较少,理解起来还算轻松,紧急报文就介绍到这里。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1975136.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

修改VSCode插件默认安装路径

文章目录 前言VSCode插件默认安装路径添加环境变量先修改路径注意事项 前言 今天发现C盘快满了&#xff0c;只能清理点东西&#xff0c;给C盘腾出的空间出来&#xff0c;结果一看&#xff0c;VSCode的插件目录就占了不少呢。 VSCode插件默认安装路径 C:\Users\{个人用户名}\.…

比较支持向量机、AdaBoost、逻辑斯谛回归模型的学习策略与算法

(1)支持向量机&#xff1a;SVM 是一种监督学习算法&#xff0c;用于分类和回归任务。 学习策略&#xff1a;间隔最大化 算法&#xff1a;最大间隔法、软间隔算法。 参数学习&#xff1a;参数学习过程是要最小化目标函数&#xff0c;通常通过优化算法&#xff08;如SMO&#x…

为什么选择 Baklib 而不是 Salesforce 进行知识库管理

对于希望管理其产品和服务的在线文档或知识库以支持其客户和员工的组织来说&#xff0c;市场上有太多的平台和工具。知识库通过向客户和员工提供重要信息来帮助组织提高生产力。这大致分为客户关系管理或客户服务。 很少有平台能够为销售、客户服务等提供一套服务。Salesforce…

Adobe ColdFusion反序列化漏洞(cve-2017-3066)

目录 概述复现过程修复建议 概述 Adobe ColdFusion&#xff08;直译&#xff1a;冷聚变&#xff09;&#xff0c;是一个动态Web服务器&#xff0c;其CFML&#xff08;ColdFusion Markup Language&#xff09;是一种程序设计语言&#xff0c;类似JSP里的JSTL&#xff08;JSP St…

High Speed Serdes学习笔记

1 并行数据总线&#xff08;Parallel Data Bus&#xff09; 并行数据总线为传统的数据传输方式&#xff0c;存在两个问题&#xff1b; 1>需要大量的I/O引脚 2>必须满足严格的时序要求以保证数据正确传输。 图&#xff1a;两个设备之间的并行数据 2 数据串行化 减少并行…

【学习笔记】Day 2

一、进度概述 1、inversionnet_train_light 试运行——未成功 2、DL-FWI基础入门培训-1,2&#xff0c;以及作业1的完成 二、详情 1、inversionnet_train_light 试运行 在补充完相关依赖后&#xff0c;运行仍有报错 产生原因&#xff1a;这个代码在当时师兄的库中存在…

架构设计前期应该怎么做?

利益干系人分析 利益干系人分析框架 利益干系人 - 投资者 利益干系人 - 监管者 利益干系人 - 构建者&#xff0c;维护者 利益干系人 - 使用者&#xff0c;评估者 利益干系人 - 钱包案例 评估者&#xff1a;用户可以评估好不好用 利益干系人 - 外包系统案例 诉求优先级排序 …

【LeetCode每日一题】盛最多水的容器

思路 标签:双指针&#xff0c;贪心 分析&#xff1a; 首先选两条线为容器的两端&#xff0c;盛水的高度取决于高度小的那条线&#xff0c;此时在两条线中间选一条线&#xff0c;有两种情况&#xff0c;如果区间内某条线比两端高度小的那条线还要小&#xff0c;此时宽度和高度…

UE4-常用快捷键汇总

一.虚幻引擎编辑器快捷键 二.蓝图编辑器快捷键

JAVA项目

目录 一、前言 二、技术介绍 三、项目实现流程 四、论文流程参考 五、核心代码截图 专注于大学生实战开发、讲解和毕业答疑等辅导&#xff0c;获取源码后台 一、前言 在数字化音乐时代&#xff0c;个性化推荐已成为提升用户体验、促进音乐消费的重要手段。为此&#xff0…

mybatis-plus selectPage获取到数据但是total为0

查数据库返回数据&#xff0c;但是total显示为0 这里需要设置分页拦截器 config目录下新建mybatisConfig.java import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.spri…

Airtest精讲Template配置参数

Airtest精讲Template配置参数 今天我们讲一下airtest图像识别中的一个最基本、最常用的一个类Template 一、环境背景 首先我们先看一个非常简单的脚本示例&#xff0c;在AirtestIDE中&#xff0c;显示如图&#xff1a; 在编辑器中点击鼠标右键菜单的‘图片/代码模式切换’&am…

美股:AMD展现乐观前景,挑战AI加速器市场霸主

在科技行业的激烈竞争中&#xff0c;AMD公司近期发布了对当前季度收入的乐观预测&#xff0c;显示出其新推出 一、AMD第三季度营收预期超越分析师平均预期 AMD在周二的声明中预计&#xff0c;第三季度营收将达到约67亿美元&#xff0c;这一数字超出了分析师此前平均预期的66.…

mybatis-plus雪花算法

苞米豆mybatis-plus已实现雪花算法&#xff0c;若项目中使用雪花算法生成自增主键&#xff0c;可直接引用相关jar实现其工具类&#xff0c;若不想再单独引用jar也可将其Sequence类直接复制到自己项目中定义为工具类使用 官方文档&#xff1a;https://baomidou.com/ Git地址&am…

ESP32是什么?

ESP32是一款由乐鑫信息科技&#xff08;Espressif Systems&#xff09;推出的高度集成的低功耗系统级芯片&#xff08;SoC&#xff09;&#xff0c;它结合了双核处理器、无线通信、低功耗特性和丰富的外设&#xff0c;特别适用于各种物联网&#xff08;IoT&#xff09;应用。以…

架构设计中期应该怎么做?

设计备选方案 架构设计常见的错误思维 什么是备选架构&#xff1f; 能够解决系统复杂度的方案 备选方案设计过程 备选架构设计技巧 备选方案常见困难和应对技巧 学的太浅&#xff1a;不知道本质 比较学习法 评估和选择备选方案 错误的方法 正确的方法 - 360度环评 优先级排…

vulhub-wordpress

1.打开wordpress关卡&#xff0c;选择简体中文 2.添加信息——点击安装WordPress 登录 点击外观—编辑主题 插入一句话木马 —更新文件 访问404.php的路径/wp-content/themes/twentyfifteen/404.php 使用菜刀连接

嗖嗖移动业务大厅(Java版)

首先对此项目说明一下&#xff0c;我只完成了项目的基本需求&#xff0c;另外增加了一个用户反馈的功能&#xff0c;但是可能项目中间使用嗖嗖这个功能还有一些需要完善的地方&#xff0c;或者还有一些小bug&#xff0c;就当给大家参考一下了&#xff0c;希望谅解。代码我也上传…

数据结构初阶之排序(下)

前言 上一期内容中我们了解了基本排序中的插入与选择排序&#xff0c;今天我将为大家带来剩下的几种排序算法 快速排序 快速排序是Hoare于1962年提出的⼀种⼆叉树结构的交换排序⽅法&#xff0c;其基本思想为&#xff1a;任取待排序元素序列中的某元素作为基准值&#xff0c;…

ARM 架构与技术综述

目录 认识 ARM ARM 发展历史 指令集 ARM 公司产品分类 ARM 体系结构 数据类型约定 处理器的 32 位和 64 位含义 指令集 ARM 处理器的工作模式 CPU (内核) 组成 寄存器 时钟 认识 ARM ARM 可以指&#xff1a; 一家公司。一种技术。一系列处理器。 架构&#xff1a;A…