2. CMS32 CAN模块概览:特性、引脚与时钟

好,咱们正式开始看CMS32的CAN模块。说实话,我第一次拿到CMS32的参考手册时,第一反应是去找CAN章节——毕竟做嵌入式,通信接口就是命脉。这一节我会把CAN控制器的特性、引脚怎么接、时钟怎么配,掰开揉碎了讲清楚。

2.1 CAN控制器核心特性

CMS32系列内置的CAN控制器,其实是一个完整的CAN 2.0B协议引擎。它支持标准帧(11位ID)和扩展帧(29位ID),这点在现在的车载和工业现场基本是标配。但我个人最看重的,是它有几个很实在的特性:

  • 3个发送缓冲器:可以挂起3个待发报文,优先级由硬件自动仲裁
  • 2个接收缓冲器:每个都能存1个完整报文,配合FIFO机制不容易丢帧
  • 可编程的验收滤波器:最多支持4个32位掩码/ID组合,说白了就是能按需过滤,不用CPU一个个去翻
  • 总线错误诊断:能直接读出错误计数器和错误状态,调试时特别好用

关键参数速查表

参数CMS32 CAN控制器备注
协议标准CAN 2.0B兼容标准帧/扩展帧
发送缓冲器3个优先级由硬件仲裁
接收缓冲器2个 + FIFO深度可配置
验收滤波器4组 × 32位支持掩码和ID模式
位速率最高1 Mbps取决于时钟和分频
错误状态寄存器有可读发送/接收错误计数

我记得有一次项目,对方要求CAN总线跑在800kbps,结果我配完发现总是丢帧。查了半天,原来是验收滤波器没配好,把本应接收的报文全给滤掉了。嗯,从那以后我每次配滤波器都会反复确认掩码值。

2.2 引脚配置:CAN_TX 和 CAN_RX

CMS32的CAN接口只有两个引脚:CAN_TX(发送)和 CAN_RX(接收)。别小看这两个脚,接错了整个总线都起不来。

先看引脚功能:

引脚名方向功能描述
CAN_TX输出CAN控制器发送数据到收发器
CAN_RX输入CAN收发器接收数据到控制器

实际项目中,这两个引脚通常不会直接连到CAN总线上,而是通过一个CAN收发器(比如TJA1050或SN65HVD230)转成差分信号。我见过有人直接把CAN_TX和CAN_RX接到总线上,结果烧了IO口——收发器的作用就是把单端信号转成CANH/CANL差分,同时提供电平转换和总线保护。

⚠️ 引脚复用注意

CMS32的CAN_TX和CAN_RX通常与GPIO复用。上电后默认是GPIO模式,必须通过寄存器配置为CAN功能。我曾经在调试时发现CAN没反应,查了半天才发现是引脚功能没切过来——这种低级错误最容易浪费半天时间。

配置引脚时,一般需要两步:

  1. 在GPIO模块中,把对应引脚设为复用功能(AF模式)
  2. 在CAN模块中,使能CAN_TX和CAN_RX的驱动

具体代码我习惯这样写(以CMS32标准库为例):

// 使能CAN引脚时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);

// 配置CAN_TX (假设为PA12) 为复用推挽输出
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// 配置CAN_RX (假设为PA11) 为浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// 将PA11和PA12连接到CAN模块
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN);

你想想看,如果忘了最后那两行AF配置,CAN_TX和CAN_RX就还是普通GPIO,收发器根本收不到数据。这种坑我踩过不止一次。

2.3 时钟使能与复位

CAN模块要工作,首先得给它喂时钟。CMS32的CAN挂载在APB1总线上,时钟源通常来自系统时钟经过分频后的APB1时钟。

时钟使能很简单,就一个寄存器位:

// 使能CAN时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);

但这里有个关键点:CAN模块的位时序(Baud Rate)完全依赖于这个时钟频率。如果APB1时钟不准,CAN的波特率就会偏,总线通信就会出错。我建议你在配CAN之前,先确认APB1时钟的实际频率,最好用示波器量一下CAN_TX引脚的波形。

💡 我的调试习惯

每次初始化CAN之前,我都会先读一下RCC寄存器,确认APB1时钟值。然后在CAN初始化结构体里,把波特率参数算好再写进去。别偷懒,直接抄例程里的数值——不同板子的时钟可能不一样。

复位方面,CMS32提供了两种复位方式:

  • 软件复位:通过CAN模块的控制寄存器(CAN_MCR)中的RESET位触发,复位后所有寄存器回到默认值
  • 硬件复位:系统复位或看门狗复位时,CAN模块自动复位

我个人更常用软件复位,因为可以在不重启整个系统的情况下重新初始化CAN。比如总线出现Bus Off状态时,我会先软件复位CAN,再重新配置,而不是直接复位单片机。

// 软件复位CAN
CAN_DeInit(CAN1);

// 重新初始化
CAN_Init(CAN1, &CAN_InitStructure);

嗯,这里要注意:软件复位后,所有配置都会丢失,包括验收滤波器、中断使能等。所以复位后必须重新做一遍完整的初始化流程。

2.4 整体结构图

下面这张图把CMS32 CAN模块的内部结构和外部连接画清楚了。你可以看到CAN控制器、收发器、总线之间的关系,以及时钟和复位信号怎么进来。

CMS32 CAN模块结构图 CMS32 CAN模块结构图 CMS32 单片机 CAN 控制器 发送缓冲器 × 3 接收缓冲器 × 2 + FIFO 验收滤波器 × 4 错误状态寄存器 时钟使能 APB1时钟 复位控制 软件/硬件复位 CAN_TX PA12 (AF) CAN_RX PA11 (AF) CAN 收发器 TJA1050 / SN65HVD230 单端 ↔ 差分转换 TX RX CAN 总线 CANH / CANL 差分信号 CANH CANL 💡 关键路径 时钟使能 → 引脚AF配置 → 控制器初始化 → 收发器连接 → 总线通信

从图上你能看到,CAN控制器在单片机内部,通过CAN_TX和CAN_RX连接到外部收发器,再转成差分信号上总线。时钟和复位是控制器正常工作的前提——少了任何一个,CAN都动不了。

💡 快速检查清单

  • CAN_TX和CAN_RX是否已配置为复用功能?
  • APB1时钟是否已使能?频率是否正确?
  • 收发器供电是否正常?VCC和GND接好了吗?
  • 总线终端电阻(120Ω)是否在两端都接了?

好了,这一节的内容就是这些。CMS32的CAN模块其实不复杂,但引脚配置和时钟使能是基础中的基础。我见过太多人一上来就调波特率、配滤波器,结果发现CAN_TX根本没输出——回头一看,时钟没开。嗯,别笑,这种事真不少见。