CANopen是个啥?

一、CANopen协议的诞生和意义

  我个人的理解就是基于CAN BUS的上层应用协议,就好像有菜有锅有调料,不同的人做出来的菜是不一样的,CANopen就是希望建立一个应用标准,和CANopen一样的基于CAN BUS的上层应用还有Device NET、SAE J1939等,对于CANopen的发展历史以及提出这些动动手查查,官方的消息很多哦。但是国内CANopen使用的比较少,原因不详,我觉得这么好的东西不应该埋没呀,或许是因为CANopen栈占用的空间太大?
  当然这里还是要感谢CiA主席 蔡豪格,这位可爱的德国老人,坚持开放、免费、非盈利的准则,这种精神值得我们学习。
CiA主席

二、为什么选择CANopen

  对于我个人而言,选择CANopen主要是因为看上了CANopen协议的标准,以及其协议定制的规范性,既有主从模式,又有生产者和消费者模式,紧急上报,时间同步等内容,非常适合我目前的项目场景,并且由于有了一个标准规范,供应商定制协议可以由其发挥,不再浪费相互讨论时间。
  实际应用场景来展开说,当前项目主要由中心控制计算机以及多个分系统计算机组成,当前正在使用的方式使用的是一问一答的形式,每一次交互都由中心控制计算机发出,但是实际是中心计算机定周期的获取各个分系统计算机上报的遥测信息,不定期控制分系统计算机、只针对通信分系统进行定期的主动传输,如果使用CANopen协议栈,我们可以同步中心计算机产生同步信号,各分系统计算机根据配置主动上报遥测信息,对于控制有主动数据传输可使用传统的主从模式,CANopen对数据的主动上报可通过配置进行有效上报时间的配置,保证了数据上报的有效性,主从模式下有标准的应答,可以保证了解每一次的操作是否完成。
  并且在CANopen中定义了每个从机都会进行上线通知、定时上报自身运行状态,并且从机可以针对本身的紧急错误、事件进行主动上报,保证了主机可以及时的了解下属从机的在线/离线态,以此对各个从机进行对应操作。
  以上就是我选择CANopen的原因,不外乎CANopen的设计周全、也建立了一个标准,可以使得产品开发更加的便捷。

CANopen协议是基于CAN总线的一种高层通信协议,提供标准化的通信规范,以实现不同设备间的互操作性。该协议涵盖OSI七层模型,重点在于应用层和对象字典的设计。通过NMT、SDO、PDO、LSS等核心机制,支持设备配置、实时通信和故障处理 [^1]。 CANopen协议在标准的CAN总线上运行,其通信模式采用工业通信协议常用的“主从”模式,即网络中有一个主站(客户端)和多个从站(服务器),从站之间不直接通信,所有通信都在主站与从站之间进行 [^2]。 以官方的CiA 301 - 4.2.0基础协议为解读标准,CiA 301使用仲裁域ID为11Bit的标准帧格式,发送与接收以从机视角,多字节数据采用小端模式(低字节先发送) [^3]。 ### CANopen报文说明 CANopen报文主要有以下几种类型: - **NMT(网络管理)报文**:用于控制网络中节点的状态,如启动、停止、复位等。 - **SDO(服务数据对象)报文**:用于主站与从站之间的参数配置和数据传输,可进行远程读写操作。 - **PDO(过程数据对象)报文**:用于实时数据的快速传输,通常不经过确认,以保证通信的实时性。 - **LSS(链路层设置)报文**:用于在网络初始化阶段对节点进行配置,如节点ID分配等。 ### 示例代码(伪代码) 以下是一个简单的CANopen通信的伪代码示例,用于说明基本的发送和接收逻辑: ```python # 初始化CAN总线 def can_init(): # 初始化CAN硬件 pass # 发送SDO请求 def send_sdo_request(node_id, index, sub_index, data): # 构造SDO请求报文 sdo_message = construct_sdo_message(node_id, index, sub_index, data) # 发送报文到CAN总线 can_send(sdo_message) # 接收CAN消息 def receive_can_message(): # 从CAN总线接收消息 message = can_receive() if message: # 解析消息类型 message_type = parse_message_type(message) if message_type == "SDO": # 处理SDO消息 handle_sdo_message(message) elif message_type == "PDO": # 处理PDO消息 handle_pdo_message(message) # 其他消息类型处理... # 主循环 def main(): can_init() while True: # 发送SDO请求示例 send_sdo_request(0x01, 0x1000, 0x00, [0x01, 0x02, 0x03, 0x04]) # 接收CAN消息 receive_can_message() if __name__ == "__main__": main() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值