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模式,兼容性更好。
3.1.2 MCP2515:SPI小钢炮
MCP2515是Microchip的产品,走SPI接口。它只需要4根线(SCK、MOSI、MISO、CS)就能跟MCU通信,特别适合引脚紧张的MCU。我后来做项目基本都用它,尤其是用STM32或Arduino的时候。
它内部有2个接收缓冲器,每个都可以独立配置过滤器。还有1个发送缓冲器,支持优先级设置。最让我喜欢的是它的回环模式——调试时不用接总线,自己发自己收,方便极了。
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引脚控制),可以让发送器关闭,只保留接收功能。这在多节点调试时很有用——你可以让某个节点只听不说,不影响总线。
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);
}
3.3.2 并行接口:高速但占资源
并行接口适合对速率要求极高的场景,比如多个CAN通道同时收发大量数据。但代价是占用大量GPIO,而且布线复杂。SJA1000的并行接口支持Intel模式和Motorola模式,两者时序略有不同,选哪种取决于你的MCU。
我个人不太推荐在新项目里用并行接口的独立控制器。现在很多MCU(比如STM32)都内置了CAN控制器,直接用内部外设更省事。除非你用的是没有CAN外设的廉价MCU,或者需要扩展额外的CAN通道。
3.4 硬件连接实战:MCP2515 + SN65HVD230
这是我做项目最常用的组合。下面是一个典型的连接图:
连接要点:
- 供电:MCP2515和SN65HVD230都是3.3V,可以直接连接。如果MCU是5V,需要加电平转换或使用5V容忍引脚。
- TXD/RXD:MCP2515的TXD接SN65HVD230的TXD,RXD接RXD。注意交叉——控制器发,收发器收。
- 终端电阻:CAN总线两端各一个120Ω电阻。如果节点数少(比如只有2个),可以只在两端各加一个。节点多时,要计算等效电阻。
- 去耦电容:每个芯片的电源引脚附近放一个0.1μF的陶瓷电容。我吃过亏,没加去耦电容,总线上的噪声导致通信误码率飙升。
3.5 选型建议:怎么选最省心?
说了这么多,到底怎么选?我根据项目经验,给几个实用建议:
- 新手入门:MCP2515 + SN65HVD230。SPI接口简单,3.3V供电,模块化设计,淘宝上大把现成模块,几块钱一个。配合Arduino或STM32,半天就能跑起来。
- 工业项目:TJA1050 + SJA1000(或内置CAN的MCU)。5V供电抗干扰强,并行接口速率高。如果MCU自带CAN,直接用内部控制器,省一个芯片。
- 低功耗场景:SN65HVD230 + MCP2515。待机模式功耗极低,适合电池供电的设备。
- 高可靠性:ISO1050隔离型收发器。用在电机驱动、变频器等强干扰环境,隔离能保命——保MCU的命。
嗯,硬件选型就这些。记住一个原则:能用内置就别用外置,能用SPI就别用并行,能统一电压就别混用。省下的引脚和精力,留着调试软件不香吗?