第三章:硬件平台搭建——选对芯片,少走弯路
好,咱们进入实操环节。前面两章讲了CANopen协议栈和运动控制的基本概念,现在该落地了。硬件平台怎么搭?说白了就是三样东西:微控制器(MCU)、CAN控制器、CAN收发器。这三者怎么选、怎么连,我踩过的坑可不少,今天一次性说清楚。
核心思路:CAN控制器负责协议处理,收发器负责电平转换,MCU负责应用逻辑。三者缺一不可,但选型顺序有讲究。
3.1 微控制器选型——别光看主频
很多人选MCU第一眼看主频,其实这是个误区。我做过一个项目,选了200MHz的芯片,结果CAN通信死活不稳定。后来发现是CAN控制器外设的缓冲区太小,导致数据帧溢出。
我个人习惯按这个顺序来选:
- 内置CAN控制器优先——省掉外部CAN控制器芯片,成本低、布线简单
- 至少2个独立的CAN通道——万一要扩展节点,不用重新设计
- RAM要够大——运动控制算法+协议栈,至少64KB起步
- 定时器资源丰富——同步周期、心跳报文都需要硬件定时器
举个例子,我常用的STM32F407系列,内置两个CAN控制器,主频168MHz,RAM 192KB。嗯,这个配置跑CANopen运动控制绰绰有余。你想想看,如果选个低端芯片,光协议栈就占掉一半RAM,后面加个PID算法都费劲。
我的经验:如果预算允许,优先选带CAN-FD的MCU。虽然现在用标准CAN 2.0,但未来升级CAN-FD时不用换硬件。我手头三个项目都是这么干的,省了两次改板费用。
3.2 CAN控制器——内置还是外置?
这个问题其实没啥好纠结的。现在主流MCU基本都内置CAN控制器,比如STM32、GD32、NXP的LPC系列。但如果你用的是低端MCU或者FPGA方案,那就得外挂。
外置CAN控制器我推荐两个:
| 型号 | 特点 | 适用场景 |
|---|---|---|
| MCP2515 | SPI接口,便宜,资料多 | 低端MCU、Arduino扩展 |
| SJA1000 | 并行接口,稳定,工业级 | 工控主板、PLC扩展 |
我曾经在一个项目里用了MCP2515,结果发现SPI速率上不去,导致CAN总线利用率低。后来换成内置控制器,问题直接解决。所以我的建议是:能用内置就别用外置,除非你确实需要独立控制。
3.3 CAN收发器——别小看这颗芯片
收发器负责把CAN控制器的逻辑电平转换成差分信号。很多人觉得随便选一个就行,其实不然。我见过一个案例,选了便宜的TJA1050,结果在强电磁干扰环境下频繁丢帧。
选收发器要注意三点:
- 速率匹配——标准CAN最高1Mbps,CAN-FD最高8Mbps,收发器要支持
- 耐压等级——工业环境建议选±36V耐压的,比如SN65HVD230
- 待机功耗——如果做电池供电设备,选带待机模式的
我个人常用的组合是:STM32F407(内置CAN控制器)+ TJA1050(收发器)。这个组合我用了五年,没出过问题。当然,如果你预算充足,可以上隔离型收发器,比如ISO1050,能彻底解决共模干扰问题。
避坑指南:我曾经在收发器的终端电阻上吃过亏。CAN总线两端必须各接一个120Ω电阻,少一个都不行。有一次调试时忘了接,结果通信时好时坏,查了两天才发现。嗯,这个坑你们别踩。
3.4 最小系统搭建——连线图
下面这张图是我画的最小系统框架,包含了MCU、CAN控制器(内置)、收发器、终端电阻和电源。你照着连就行。
3.5 实际连线注意事项
图纸画好了,实际焊接时还有几个细节要注意:
- 电源去耦——每个芯片的VCC引脚旁边放一个0.1μF电容,我习惯再加一个10μF电解电容
- 收发器使能引脚——TJA1050的RS引脚接地(高速模式),S引脚接高电平(正常模式)
- 终端电阻位置——必须放在总线物理两端,不是PCB两端。如果节点少,直接在收发器旁边焊上
- 共模扼流圈——工业环境建议在CAN_H和CAN_L上串一个共模扼流圈,能有效抑制干扰
我的小技巧:调试时先别焊终端电阻,用示波器看CAN_H和CAN_L的差分信号。如果波形干净,再焊上电阻。这样能快速定位是芯片问题还是总线问题。
3.6 代码示例——初始化CAN外设
硬件连好了,得让MCU跑起来。下面是一段STM32的CAN初始化代码,我加了详细注释:
// CAN初始化函数
void CAN_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
// 1. 使能时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
// 2. 配置CAN引脚(PB8=RX, PB9=TX)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 3. 复用功能映射
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_CAN1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_CAN1);
// 4. CAN参数配置
CAN_InitStructure.CAN_TTCM = DISABLE; // 时间触发模式
CAN_InitStructure.CAN_ABOM = ENABLE; // 自动离线管理
CAN_InitStructure.CAN_AWUM = ENABLE; // 自动唤醒
CAN_InitStructure.CAN_NART = DISABLE; // 自动重传
CAN_InitStructure.CAN_RFLM = DISABLE; // 接收FIFO锁定
CAN_InitStructure.CAN_TXFP = DISABLE; // 发送优先级由ID决定
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; // 正常模式
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; // 同步跳转宽度
CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq; // 时间段1
CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq; // 时间段2
CAN_InitStructure.CAN_Prescaler = 6; // 分频系数
CAN_Init(CAN1, &CAN_InitStructure);
// 5. 配置滤波器(接收所有ID)
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
// 6. 使能CAN中断
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
NVIC_EnableIRQ(CAN1_RX0_IRQn);
}
这段代码配置了1Mbps的波特率(42MHz APB1时钟下)。你想想看,如果分频系数算错了,通信就会失败。我建议用示波器实测CAN_H上的位时间,确保在1μs左右。
3.7 硬件调试——三板斧
硬件焊好了,代码烧进去了,但通信不通怎么办?别慌,我总结了三板斧:
- 测电源——先量MCU和收发器的VCC,确保电压正常。我遇到过5V供电的收发器接了3.3V,结果完全没反应
- 看波形——用示波器看CAN_TX引脚有没有方波输出。如果有,说明MCU在发数据;如果没有,检查初始化代码
- 查终端电阻——断开总线,用万用表量CAN_H和CAN_L之间的电阻。正常应该是60Ω(两个120Ω并联)
曾经踩过的坑:有一次我焊完板子,通信死活不通。查了两天,最后发现是CAN收发器的S引脚悬空了。TJA1050的S引脚是静音模式控制,悬空会导致芯片进入静音状态,只能收不能发。嗯,从此以后我焊完板子第一件事就是检查所有使能引脚的电平。
好了,硬件平台搭建就讲到这里。你按照上面的选型建议和连线图,搭一个最小系统应该没问题。记住,硬件是基础,基础打牢了,后面的协议栈和运动控制才能跑得稳。