发表于:2017/6/3 20:49:48
#0楼
历史
2009 年大二下学期,我和小夥伴们一起参与一个校企联合项目,开发一款煤矿用皮带机综合保护器, 我主要负责电路软硬件设计,因为矿井中皮带很长,保护器节点间相距约六百米, 各节点除了处理数据收发还要负责中继,为了更优的可靠性和实时性,中继部分采用 FPGA 硬件实现, 因此中继带来的延时远小于一个位长。 因为没有额外的主机,按照传统,只能指定其中一个节点为主机, 该节点负责持续发出查询命令同步所有节点之数据,但万一该主节点中途出故障下线,整个总线将会停止运行。 所以为了进一步提升系统鲁棒性及降低软件复杂性,于是我设计了一款带仲裁的 485 协议,做到节点间可以自由收发数据, 只有第一字节用做仲裁的字段使用低速传输,剩余数据使用传统 485 高速传输,在引入仲裁的同时保留了高速,当然也是由硬件实现。
传统 485 的局限
无论是串口还是 485 通讯,传输的数据正常都是要打包发送,常见的有类似 0xff 0xaa 两个字节做为数据包的开头,加上用户自定义的数据格式可以判断包的结尾。 0xff 0xaa 这种标记方式容易与其后数据重复,做为判断不是绝对保险(譬如一个数据包正文正好也有一个 0xff 0xaa, 当该数据包出错一次导致错位,接收者认为正文的 0xff 0xaa 是包头,那么其后的超时重传可能会导致错误一直持续下去); 绝对保险的方式是使用 ModBus RTU 也采用的空闲状态来做分隔,总线没有数据超过设定时间后为空闲状态, 空闲状态下到来的数据便是数据包的开始,但这种方式对于用户的实时性要求较高,譬如使用了带 FIFO 缓冲的串口接收芯片,如果用户未及时取出第一个数据包又收到第二个数据包, 那么两个数据包的数据连在一起无法通过时间来分隔(此时按照数据包格式通常也可以继续区分数据包,但前提是数据包不能出错)。
在普通的 485 应用场景中,CPU 直接控制 485 接口芯片接收数据,需要软件判断数据包何时开始何时结束,即使该数据包并非发给自己,CPU 也要被总线数据频繁中断,影响效率。 同时收到数据包后还要校验以确保正确性,是一件非常占用 CPU 资源的工作。 值得一提的情形是:如果 CPU 有较高优先级任务要处理,会很难指定数据接收和其它任务的优先级顺序:如果数据接收的优先级更高,那么当总线不停来数据的时候会不停打断其它任务处理; 如果接收优先级低一些,那么又会经常丢失数据。
同时,由于传统 485 只能单台主机不停查询各从机以同步数据,总线的数据一定少不了,且利用率很低,实时性和鲁棒性也差。 譬如有一个从机是一只开关,主机为了知道开关当前是否按下,要不停发送查询数据包,然后开关回覆一个包含当前状态的数据包给主机; 如果可以做到各节点均可主动发出数据包,那么当开关状态改变时,只需要发送一个数据包给主机便可,即快省又便捷。
CAN 总线的局限
为了降低 CPU 占用和自由收发数据包,所以一部分人选择了 CAN 总线,CAN 控制器由硬件处理数据包收发、校验,同时提供自由收发数据包的能力(仲裁), 但是 CAN 的数据包最多只能传输 8 个字节数据,而且高速 CAN 最高速率只有 1 Mbps, 比 485 的标准 10 Mbps 低太多(485 速率还可以更高),而且 CAN 的版权费用导致成本很高。
最新的 CAN FD (CAN with Flexible Data-Rate) 可以支持超过 1 Mbps 的速率,但由于硬件依旧不是推挽输出,所以通常也只有 2 Mbps、5 Mbps, 而且也找不到独立的控制器芯片, 由于要兼容 CAN2.0, 加上 CAN 本身硬件较为复杂,Microchip 2015 年说计划推出 CAN FD 控制器,结果到现在也没有出来。
CAN 还有一个特色是废除传统的站地址编码,代之通过区分不同消息,以实现多播 (multicast), 但我觉得它带来的缺点远超过优点:因为整个系统的命令空间会耦合在一起, 如果一开始命令空间分配的不合理,要想修改就会牵一发而动全身;而且配置过滤接收也十分繁琐;接收者也不清楚是谁发出的数据包;发送者虽然能收到 ACK 应答,也不能保证所有相关节点都收到。
在节点本来就不多的系统中(不超过 255),仅使用单播和广播就完全够用:譬如我要同时控制四个车窗升降,分别发送四个数据包给四个玻璃窗也不会很低效,而且当我想单独控制某一个玻璃窗时也不需要改变数据包定义; 又如,当刹车等紧急情况发生时,使用广播包可以最迅速通知到每一个节点,即便车窗不响应该命令,被紧急事务打断一下也是完全可以接受的。
2009 年大二下学期,我和小夥伴们一起参与一个校企联合项目,开发一款煤矿用皮带机综合保护器, 我主要负责电路软硬件设计,因为矿井中皮带很长,保护器节点间相距约六百米, 各节点除了处理数据收发还要负责中继,为了更优的可靠性和实时性,中继部分采用 FPGA 硬件实现, 因此中继带来的延时远小于一个位长。 因为没有额外的主机,按照传统,只能指定其中一个节点为主机, 该节点负责持续发出查询命令同步所有节点之数据,但万一该主节点中途出故障下线,整个总线将会停止运行。 所以为了进一步提升系统鲁棒性及降低软件复杂性,于是我设计了一款带仲裁的 485 协议,做到节点间可以自由收发数据, 只有第一字节用做仲裁的字段使用低速传输,剩余数据使用传统 485 高速传输,在引入仲裁的同时保留了高速,当然也是由硬件实现。
传统 485 的局限
无论是串口还是 485 通讯,传输的数据正常都是要打包发送,常见的有类似 0xff 0xaa 两个字节做为数据包的开头,加上用户自定义的数据格式可以判断包的结尾。 0xff 0xaa 这种标记方式容易与其后数据重复,做为判断不是绝对保险(譬如一个数据包正文正好也有一个 0xff 0xaa, 当该数据包出错一次导致错位,接收者认为正文的 0xff 0xaa 是包头,那么其后的超时重传可能会导致错误一直持续下去); 绝对保险的方式是使用 ModBus RTU 也采用的空闲状态来做分隔,总线没有数据超过设定时间后为空闲状态, 空闲状态下到来的数据便是数据包的开始,但这种方式对于用户的实时性要求较高,譬如使用了带 FIFO 缓冲的串口接收芯片,如果用户未及时取出第一个数据包又收到第二个数据包, 那么两个数据包的数据连在一起无法通过时间来分隔(此时按照数据包格式通常也可以继续区分数据包,但前提是数据包不能出错)。
在普通的 485 应用场景中,CPU 直接控制 485 接口芯片接收数据,需要软件判断数据包何时开始何时结束,即使该数据包并非发给自己,CPU 也要被总线数据频繁中断,影响效率。 同时收到数据包后还要校验以确保正确性,是一件非常占用 CPU 资源的工作。 值得一提的情形是:如果 CPU 有较高优先级任务要处理,会很难指定数据接收和其它任务的优先级顺序:如果数据接收的优先级更高,那么当总线不停来数据的时候会不停打断其它任务处理; 如果接收优先级低一些,那么又会经常丢失数据。
同时,由于传统 485 只能单台主机不停查询各从机以同步数据,总线的数据一定少不了,且利用率很低,实时性和鲁棒性也差。 譬如有一个从机是一只开关,主机为了知道开关当前是否按下,要不停发送查询数据包,然后开关回覆一个包含当前状态的数据包给主机; 如果可以做到各节点均可主动发出数据包,那么当开关状态改变时,只需要发送一个数据包给主机便可,即快省又便捷。
CAN 总线的局限
为了降低 CPU 占用和自由收发数据包,所以一部分人选择了 CAN 总线,CAN 控制器由硬件处理数据包收发、校验,同时提供自由收发数据包的能力(仲裁), 但是 CAN 的数据包最多只能传输 8 个字节数据,而且高速 CAN 最高速率只有 1 Mbps, 比 485 的标准 10 Mbps 低太多(485 速率还可以更高),而且 CAN 的版权费用导致成本很高。
最新的 CAN FD (CAN with Flexible Data-Rate) 可以支持超过 1 Mbps 的速率,但由于硬件依旧不是推挽输出,所以通常也只有 2 Mbps、5 Mbps, 而且也找不到独立的控制器芯片, 由于要兼容 CAN2.0, 加上 CAN 本身硬件较为复杂,Microchip 2015 年说计划推出 CAN FD 控制器,结果到现在也没有出来。
CAN 还有一个特色是废除传统的站地址编码,代之通过区分不同消息,以实现多播 (multicast), 但我觉得它带来的缺点远超过优点:因为整个系统的命令空间会耦合在一起, 如果一开始命令空间分配的不合理,要想修改就会牵一发而动全身;而且配置过滤接收也十分繁琐;接收者也不清楚是谁发出的数据包;发送者虽然能收到 ACK 应答,也不能保证所有相关节点都收到。
在节点本来就不多的系统中(不超过 255),仅使用单播和广播就完全够用:譬如我要同时控制四个车窗升降,分别发送四个数据包给四个玻璃窗也不会很低效,而且当我想单独控制某一个玻璃窗时也不需要改变数据包定义; 又如,当刹车等紧急情况发生时,使用广播包可以最迅速通知到每一个节点,即便车窗不响应该命令,被紧急事务打断一下也是完全可以接受的。
[此贴子已经被作者于2017/6/10 19:02:50编辑过]