3. CAN控制器与收发器:硬件的“大脑”和“嘴巴”

做CAN开发,你最先接触到的就是两个芯片:控制器和收发器。很多人一开始搞混,觉得它们是一回事。其实分工很明确——控制器负责“想”和“算”,收发器负责“说”和“听”。

我刚开始做项目时,就吃过这个亏。选了个控制器,没仔细看收发器的匹配,结果通信死活不稳定。后来才明白,这两者就像人的大脑和嘴巴,大脑想好了要说的话,嘴巴得能清晰喊出去,还得能听清别人说什么。

3.1 控制器:CAN协议的大脑

控制器的核心任务,就是完成CAN协议的数据链路层功能。说白了,它负责组帧、发送、接收、错误检测、仲裁这些脏活累活。MCU只需要把数据扔给它,剩下的它自己搞定。

市面上主流的独立CAN控制器,我接触最多的就是这两款:

特性 SJA1000 MCP2515
接口类型 并行(Intel/Motorola模式) SPI(最高10 MHz)
工作模式 BasicCAN / PeliCAN 标准帧 / 扩展帧
接收缓冲区 64字节FIFO 2个接收缓冲器 + 6个过滤器
典型MCU搭配 51单片机、ARM7 STM32、Arduino、树莓派
封装 DIP28 / SOIC28 SOIC18 / DIP18

3.1.1 SJA1000:老将出马

SJA1000是NXP(原Philips)的经典产品。我最早接触CAN时用的就是它。它走的是并行总线,跟MCU连接需要至少8根数据线加若干控制线。优点是速度快,数据吞吐量大;缺点是占用的GPIO太多,布线麻烦。

它支持两种模式:BasicCAN和PeliCAN。BasicCAN是早期标准,只支持11位标识符。PeliCAN是扩展模式,支持29位标识符,还增加了错误捕获和单次发送功能。我个人习惯直接用PeliCAN模式,兼容性更好。

我的经验:如果你用SJA1000,记得初始化时把时钟分频寄存器配好。我遇到过有人忘了设分频,结果总线速率完全不对,查了半天才发现是时钟没配。

3.1.2 MCP2515:SPI小钢炮

MCP2515是Microchip的产品,走SPI接口。它只需要4根线(SCK、MOSI、MISO、CS)就能跟MCU通信,特别适合引脚紧张的MCU。我后来做项目基本都用它,尤其是用STM32或Arduino的时候。

它内部有2个接收缓冲器,每个都可以独立配置过滤器。还有1个发送缓冲器,支持优先级设置。最让我喜欢的是它的回环模式——调试时不用接总线,自己发自己收,方便极了。

注意:MCP2515的SPI时钟频率不能超过10 MHz。我曾经为了追求速度,把SPI时钟设到12 MHz,结果数据经常错位。后来老老实实降到8 MHz,问题解决。

3.2 收发器:信号的“翻译官”

控制器出来的是逻辑电平(通常是3.3V或5V的TTL/CMOS电平),但CAN总线需要的是差分信号。收发器就是干这个翻译活的——把逻辑电平转成CAN_H和CAN_L上的差分电压。

选收发器,主要看三个指标:速率、耐压、功耗。

型号 速率 工作电压 特点 典型应用
TJA1050 最高1 Mbps 5V 低电磁辐射、总线引脚ESD保护 工业控制、汽车电子
SN65HVD230 最高1 Mbps 3.3V 低功耗、待机模式、差分输出 电池供电设备、便携设备
TJA1040 最高1 Mbps 5V 低功耗待机、远程唤醒 汽车网络、节点休眠场景
ISO1050 最高1 Mbps 5V / 3.3V 隔离型、2500Vrms隔离 高可靠性、抗干扰场景

3.2.1 TJA1050:经典5V方案

TJA1050是NXP的经典收发器,我最早的项目用的就是它。它工作在5V,速率最高1 Mbps。它的特点是电磁辐射低,总线引脚有ESD保护,抗干扰能力强。

它有个静音模式(通过RS引脚控制),可以让发送器关闭,只保留接收功能。这在多节点调试时很有用——你可以让某个节点只听不说,不影响总线。

避坑指南:我曾经在TJA1050的CAN_H和CAN_L上忘了加终端电阻,结果总线信号反射严重,通信时好时坏。记住:CAN总线两端必须各加一个120Ω电阻,不能省。

3.2.2 SN65HVD230:3.3V低功耗之选

SN65HVD230是TI的产品,工作电压3.3V。它跟MCP2515是绝配——MCP2515也是3.3V供电,两者可以直接连接,不需要电平转换。

它有个待机模式,功耗极低,适合电池供电的设备。我做过一个手持诊断仪,平时让收发器处于待机状态,需要通信时才唤醒,电池续航提升了不少。

它的差分输出电压比TJA1050略低,但完全符合CAN标准。注意:如果总线上混用5V和3.3V的收发器,要确保共模电压范围兼容。我一般建议统一供电电压,省心。

3.3 MCU与控制器接口:SPI vs 并行

控制器跟MCU怎么连?两种主流方式:SPI和并行。选哪个,取决于你的MCU资源和对速率的要求。

接口方式 引脚数 速率 复杂度 典型控制器
SPI 4根(SCK、MOSI、MISO、CS) 受限于SPI时钟,通常≤10 Mbps 低,软件模拟也容易 MCP2515
并行 8~16根数据线 + 控制线 高,可达到数十Mbps 高,需要地址/数据总线 SJA1000

3.3.1 SPI接口:简单灵活

SPI接口是我现在最常用的。它只需要4根线,而且很多MCU都有硬件SPI模块,配置起来很简单。MCP2515的SPI指令集很清晰:读、写、位修改、复位、请求发送,总共就几条指令。

下面是一个典型的MCP2515初始化代码片段:

// MCP2515初始化示例(伪代码)
void MCP2515_Init(void) {
    // 1. 复位芯片
    SPI_Write(MCP2515_CMD_RESET, 0x00);
    delay_ms(10);
    
    // 2. 配置CAN波特率(假设500 kbps,16 MHz晶振)
    // CNF1: SJW=1, BRP=0 (分频1)
    MCP2515_WriteRegister(CNF1, 0x00);
    // CNF2: 采样点=75%, TSEG1=13 TQ
    MCP2515_WriteRegister(CNF2, 0xB1);
    // CNF3: TSEG2=2 TQ
    MCP2515_WriteRegister(CNF3, 0x05);
    
    // 3. 配置过滤器(接收所有帧)
    MCP2515_WriteRegister(RXF0SIDH, 0x00);
    MCP2515_WriteRegister(RXF0SIDL, 0x00);
    MCP2515_WriteRegister(RXM0SIDH, 0x00);
    MCP2515_WriteRegister(RXM0SIDL, 0x00);
    
    // 4. 进入正常模式
    MCP2515_WriteRegister(CANCTRL, 0x00);
}
小技巧:调试SPI通信时,我习惯先用逻辑分析仪抓一下波形。确认SCK、MOSI、MISO的时序对不对,CS片选有没有拉低。很多SPI问题都是时序不匹配造成的。

3.3.2 并行接口:高速但占资源

并行接口适合对速率要求极高的场景,比如多个CAN通道同时收发大量数据。但代价是占用大量GPIO,而且布线复杂。SJA1000的并行接口支持Intel模式和Motorola模式,两者时序略有不同,选哪种取决于你的MCU。

我个人不太推荐在新项目里用并行接口的独立控制器。现在很多MCU(比如STM32)都内置了CAN控制器,直接用内部外设更省事。除非你用的是没有CAN外设的廉价MCU,或者需要扩展额外的CAN通道。

3.4 硬件连接实战:MCP2515 + SN65HVD230

这是我做项目最常用的组合。下面是一个典型的连接图:

MCP2515 + SN65HVD230 典型连接图 MCU (STM32/Arduino) SPI主机 MCP2515 CAN控制器 SPI从机 SN65HVD230 CAN收发器 3.3V供电 SCK MOSI MISO CS TXD RXD CAN总线 CAN_H / CAN_L 120Ω 120Ω 说明: 1. MCP2515和SN65HVD230都是3.3V供电,可直接连接TXD/RXD。 2. CAN总线两端必须各接一个120Ω终端电阻,防止信号反射。

连接要点:

  • 供电:MCP2515和SN65HVD230都是3.3V,可以直接连接。如果MCU是5V,需要加电平转换或使用5V容忍引脚。
  • TXD/RXD:MCP2515的TXD接SN65HVD230的TXD,RXD接RXD。注意交叉——控制器发,收发器收。
  • 终端电阻:CAN总线两端各一个120Ω电阻。如果节点数少(比如只有2个),可以只在两端各加一个。节点多时,要计算等效电阻。
  • 去耦电容:每个芯片的电源引脚附近放一个0.1μF的陶瓷电容。我吃过亏,没加去耦电容,总线上的噪声导致通信误码率飙升。
曾经踩过的坑:有一次我把MCP2515的INT引脚悬空了,结果中断信号一直拉低,MCU不停地进中断,程序卡死。后来才意识到,INT引脚必须接上拉电阻到VCC,或者配置为推挽输出。记住:不用的引脚也要妥善处理,不能放任不管。

3.5 选型建议:怎么选最省心?

说了这么多,到底怎么选?我根据项目经验,给几个实用建议:

  • 新手入门:MCP2515 + SN65HVD230。SPI接口简单,3.3V供电,模块化设计,淘宝上大把现成模块,几块钱一个。配合Arduino或STM32,半天就能跑起来。
  • 工业项目:TJA1050 + SJA1000(或内置CAN的MCU)。5V供电抗干扰强,并行接口速率高。如果MCU自带CAN,直接用内部控制器,省一个芯片。
  • 低功耗场景:SN65HVD230 + MCP2515。待机模式功耗极低,适合电池供电的设备。
  • 高可靠性:ISO1050隔离型收发器。用在电机驱动、变频器等强干扰环境,隔离能保命——保MCU的命。

嗯,硬件选型就这些。记住一个原则:能用内置就别用外置,能用SPI就别用并行,能统一电压就别混用。省下的引脚和精力,留着调试软件不香吗?