CAN这东西,刚接触的时候觉得挺玄乎,什么差分信号什么仲裁机制,课本上一堆名词。真上手调过几块板子、烧过几颗收发器之后,你会发现它骨子里就那么点事儿——一群节点挂在一根线上,谁着急谁先说,说完自己听一遍,觉得没毛病就完事,觉得说错了就主动坦白重来,要是有人一直胡言乱语,其他人合伙把它踹出去。
就这么简单粗暴。
物理层那边,我最烦别人只背那句"差分信号抗干扰"。差分到底好在哪?好就好在它不管你电压偏高还是偏低,认的是两条线之间的差。你可以想象两个人被同一阵风吹歪了,但他俩之间的距离没变,信号就认这个距离。实际拿示波器戳上去,显性的时候H大概3.5V、L大概1.5V,差着2V左右;隐性的时候俩都2.5V,差几乎为零。记住这个就行。
终端电阻这事儿我得单独拎出来说,因为被坑过太多次了。两头各一个120Ω,少一个都不行。有回同事随手从抽屉里摸了个100Ω的焊上去,波形边沿那个振铃啊,跟心电图似的,误码率跑着跑着就上去了,查了半天最后发现是电阻值不对。换成120Ω立马干干净净。所以别在这个地方图省事。
仲裁这块,是CAN最聪明的地方,但理解错了容易出事儿。它不是谁先喊谁赢,是谁先扔0谁赢。因为0是显性,能压住1。所以ID数字越小越牛,刹车ESP的ID是0x100,车窗是0x500,俩人同时张嘴,比到某一位的时候刹车那边是0,车窗那边是1,车窗当场闭嘴,老老实实切到接收状态去听刹车的。整个过程数据不丢、时间不浪费,全凭硬件物理特性搞定。
干活时候留个心眼,关键报文ID别全挤一块儿。我见过发动机和雨刷ID就差一位的,总线一忙起来俩信号在仲裁域掐得死去活来,完全没必要。
帧格式这东西,不用死记硬背,但有两个位你最好心里有数。一个是RTR位,远程帧用的,说白了就是你不想要某个节点一直往外吐数据,你就发个远程帧问它"你现在多少",它回你一下就行,省带宽。另一个是CRC界定符和ACK界定符,这俩都是隐性位。调板子的时候拿示波器看波形,如果这俩位置被拉低了,别犹豫,肯定有节点在搞事情,这是排查物理故障最快的一条线索。
说到错误处理,这才是能不能真正调通CAN的分水岭。教科书上列了五种错误类型,我直接跟你说实际干活怎么看。
最常碰见的是ACK Error,你发一帧出去没人把ACK槽拉低,说明压根没人理你。三步走:先看终端电阻通不通,再看节点上电没有,最后对一下波特率。波特率只要偏一点点,接收节点就觉得自己收到的是乱码,绝对不会回ACK。
一旦错误计数器过了128,节点就进入被动错误状态,开始装怂,不咋抢总线了;过了255直接离线自闭,啥也不管了。很多人这时候以为硬件烧了,其实没大事,错误积累清了重新上电或者发个恢复命令就能出来。我自己的习惯是调试时候把错误计数器通过诊断报文打出来,比看那些花里胡哨的错误码直观一万倍。
波特率和时序这俩放一块说,因为坑都连着呢。CAN的位时间分了好几段,什么同步段、传播段、相位段,还有SJW。你不用自己从头算,记住一个硬道理就行:采样点放到位时间的75%到85%之间,这是车载行业大量验证过的黄金区间。SJW设1到2个Tq,晶振精度不太好的时候往2个Tq靠,容忍度一下就上来了。
说个真实翻车案例:俩节点都设的500k,但一个晶振精度±50ppm,另一个±100ppm,刚开始跑啥事没有,半小时后开始偶尔错一帧,一小时不到总线直接挂。最后咋解决的?SJW从1个Tq改到2个Tq,问题消失。所以别觉得这参数是摆设。
最后说说负载率,这事儿很多人不当回事。理论带宽100%,你别真信。实际超过60%就开始闹心了,因为隐性到显性的跳变沿受线缆分布电容影响,负载越高边沿越缓,误码率跟着往上蹿。我一般控制在30到50之间,剩下的留给诊断和刷写用。真想跑高负载?换CAN-FD去,别在经典CAN上死磕。
总的就一句话,CAN这东西不复杂,就是脾气倔,你得顺着它来。电阻给准,优先级分好,时序调稳,负载压住,它就能一年到头不出幺蛾子。