紧急报文,当设备内部发生错误时触发该对象,即发送设备内部错误代码。
在canopen内部维持一个错误表,对发生的错误进行记录。当错误发生后从表中查看该错误是否已经发生并未被解决时,则报告主站;如果错误被解决则从表中清除,当所有错都被解决,则报告主站。
canopen记录了所有错误的历史记录,当前是否有错误发生,所有错误掩码,目前为止发生过的错误种数。
/* 紧急报文初始化 */
void emergencyInit(CO_Data *d)
{/* 按索引号0x1003和子索引号0x00注册字典入口的回调函数 */RegisterSetODentryCallBack(d, 0x1003, 0x00, &OnNumberOfErrorsUpdate);/* 错误个数 */*d->error_number = 0;
}/* 紧急报文停止 */
void emergencyStop(CO_Data* d)
{}/* 发送紧急报文 */
UNS8 sendEMCY(CO_Data *d, UNS16 errCode, UNS8 errRegister, const void *Specific, UNS8 SpecificLength)
{Message m;MSG_WAR(0x3051, "sendEMCY", 0);/* cob_id */m.cob_id = (UNS16)(*(UNS32*)d->error_cobid);/* 数据帧 */m.rtr = NOT_A_REQUEST;/* 错误码 */m.Data[0] = errCode & 0xFF;m.Data[1] = (errCode >> 8) & 0xFF;/* 错误掩码 */m.Data[2] = errRegister;/* 集体字段 */if(Specific == NULL){m.Data[3] = 0;m.Data[4] = 0;m.Data[5] = 0;m.Data[6] = 0;m.Data[7] = 0;SpecificLength = 5;}else{if(SpecificLength > 5) SpecificLength = 5;memcpy(&m.Data[3], Specific, SpecificLength);    }/* 数据包长度 */m.len = SpecificLength + 3;return canSend(d->canHandle,&m);
}/* 错误发生 */
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){/* 该错误已经存在,则无需重复发送 */if(d->error_data[index].active){MSG_WAR(0x3052, "EMCY message already sent", 0);return 0;}/* 如果该错误不存在,则需要上报 */elsed->error_data[index].active = 1;break;}}/* 如果该错误在列表中不存在 */if(index == EMCY_MAX_ERRORS){/* 则遍历列表,看看有没有错误列表项未被错误占用 */for(index = 0; index < EMCY_MAX_ERRORS; ++index) {if(d->error_data[index].active == 0) break;}}/* 错误列表已经满了,直接退出 */if(index == EMCY_MAX_ERRORS){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;/* 该节点已经存在错误 */d->error_state = Error_occurred;/* 遍历整个错误列表 */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;/* 将错误历史记录向后偏移一个 */for(index = d->error_history_size - 1; index > 0; --index){*(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);}/* 发送紧急报文 */if(d->CurrentCommunicationState.csEmergency)return sendEMCY(d, errCode, *d->error_register, NULL, 0);else return 1;
}/* 错误恢复 */
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;}}/* 如果找到该错误项并且未被解决 */if((index != EMCY_MAX_ERRORS) && (d->error_data[index].active == 1)){/* 首先将该错误置为已经解决 */d->error_data[index].active = 0;/* 遍历错误列表,重新计算错误掩码 */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;/* 发送紧急报文,通知主站所有错误已经解决 */if(d->CurrentCommunicationState.csEmergency)sendEMCY(d, 0x0000, 0x00, NULL, 0);}/* 记录错误掩码 */*d->error_register = errRegister_tmp;}elseMSG_WAR(0x3054, "recovered error was not active", 0);
}/* 紧急报文处理 */
void proceedEMCY(CO_Data* d, Message* m)
{UNS8 nodeID;UNS16 errCode;UNS8 errReg;MSG_WAR(0x3055, "EMCY received. Proceed. ", 0);/* 紧急报文数据长度始终8字节 */if(m->len != 8) {MSG_ERR(0x1056, "Error size EMCY. CobId  : ", m->cob_id);return;}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);
}

CANOpen紧急报文相关推荐

  1. Emergency 紧急报文的实施

    Emergency 紧急报文的实施 紧急报文的概念 1.紧急时间由设备内部的错误事件触发,将诊断信息发送给主站.当诊断事件消失之后,从站应该将诊断事件和错误复位吗再发送一次.下图紧急事件数据帧格式

  2. CANOpen网络管理报文

    网络管理报文用于监视和设置节点的运行状态,心跳机制和寿命保护机制都基于该报文. /* 改变节点状态 */ UNS8 masterSendNMTstateChange(CO_Data *d, UNS8 ...

  3. CANOpen同步报文

    同步(SYNC),该报文对象基于生产者/消费者模式,由SYNC生产者周期性的广播,作为网络基本时钟,实现整个网络的同步传输,每个节点都以该同步报文作为同步PDO触发参数,因此该同步报文的COB-ID具 ...

  4. CANopen通讯基础

    文章目录 CANopen通讯基础 CAN概述 CAN的基本原理 CANopen概述 CANopen对象词典 CANopen通讯标识符 CANopen协议概述 CANopen管理报文 CANopen紧急 ...

  5. CANOpen报文类型

    CANOpen应用层协议细化了CAN总线协议中关于标识符的定义.定义标准报文的11比特标识符中高4比特为功能码,后7比特为节点号,重命名为通讯对象标识符(COB-ID). 功能码将所有的报文分为7个优 ...

  6. canopen服务器协议,CANopen

    CAN應用層和CANopen CANopen 概述 CANopen是附加了一套设备子协议的高层(第7层)CAN通信协议.作为一种标准化.高度可配置的嵌入式网络解决方案,它广泛应用于实时工业应用.机器人 ...

  7. CANOpen状态机

    CANopen 的每一个节点都维护了一个状态机.该状态机的状态决定了该节点当前支持的通讯方式以及节点行为. 节点在不同的状态下支持不同的报文通讯 初始化:bootup报文(lifeguard的一种) ...

  8. CANopen协议及应用

    文章目录 CANopen协议 CAN总线 CAN报文 CANopen概述 对象字典(Object Dictionary) 概述 通讯对象子协议区 制造商特定子协议 CANopen报文 NMT网络管理 ...

  9. CANopen协议解读

    CANopen协议解读 一.协议标准 二.CANopen报文说明 三.CANopen协议内容 1. ID的理解 2. NMT (1) 节点状态 (2) 节点状态控制 (3) 节点心跳报文 一.协议标准 ...

最新文章

  1. ​《头号玩家》中的“绿洲”,用 VR 可以找到
  2. 智慧电梯物联网 未来电梯将更智能
  3. BZOJ2298 [HAOI2011]problem a
  4. 自定义ChannelHandler 的添加过程
  5. mysql 交集_MYSQL交集函数
  6. TCP三次握手,握的是啥?
  7. 造轮子是什么意思_聊聊在阿里工作一年的收获,什么是真正的技术能力?
  8. Flowmill :为分布式应用程序世界构建的网络可观察性解决方案
  9. 无法获取计算机名,Spring Cloud常见问题之:无法注册主机名
  10. 获取所有汉字与 Unicode 的对照表
  11. Pascal之父、编程祖师爷尼古拉斯•威茨痛批:教授成了项目经理,大学过于“重论文轻教学“...
  12. .net平台调用(P/Invoking)查询网站
  13. php 请求 响应,发送http响应后继续处理php
  14. mac检测是否安装mysql_mac安装mysql
  15. Java工具类,随机生成(姓名,年龄,性别,密码,邮箱,地址,)
  16. distill_basic_teacher
  17. 【nestjs】Nest can‘t resolve dependencies of xxx无法解析xxx的依赖关系
  18. css中字母数字自动换行
  19. 线程调度策略SCHED_RR(轮转法)和SCHED_FIFO(先进先出)之对比
  20. springboot+mybatis-plus在log控制台输出sql语句

热门文章

  1. Qt学习笔记-OpenGL做正方体并旋转
  2. Qt creator5.7 OpenCV249之图片灰度处理(含源码下载)
  3. HTML期末学生大作业-乒乓球网页作业html+css+javascript
  4. c语言中用于获取字符串长度的函数是,C语言中求字符串长度的函数的几种实现方法...
  5. 如何创建一个特定版本的python虚拟环境
  6. 鼠标在滑块上滚轮控制_高速直线运动导轨—滚轮直线导轨
  7. Process com.xxxxxxxx has died
  8. (数据库系统概论|王珊)第七章数据库设计-第四节:逻辑结构设计
  9. 面试题55 - I. 二叉树的深度
  10. Redis持久化RDB