3. PIC32 CAN控制器架构解析

PIC32 系列 MCU 内部集成的 CAN 控制器(在数据手册中通常称为 ECAN,Enhanced CAN)并不是一个简单的“发送/接收寄存器对”,而是一套由协议引擎、消息缓冲区 RAM、验收过滤器、DMA 接口和中断聚合逻辑共同构成的子系统。理解它的架构,直接决定了后面配置位定时、组织报文、设计过滤规则时能否一次成功。本节以 PIC32MX 系列常见的 ECAN 模块为对象,逐层拆解其框图结构、寄存器映射、消息缓冲区组织、过滤器与屏蔽器配置,以及 DMA 与中断源的组织方式。

一、CAN 模块整体框图

从信号流角度看,ECAN 模块可以划分为四个层次:物理接口层、协议引擎层、消息存储层和主机接口层。物理接口层由 CANTX 与 CANRX 两个引脚构成,它们连接到外部 CAN 收发器(如 MCP2551、ATA6561 等),收发器再把差分信号送到 CAN_H/CAN_L 总线上。协议引擎层负责位定时、位填充、CRC 校验、错误计数、仲裁与应答,它把串行位流转换成结构化的报文帧。消息存储层是模块内部的一块专用 RAM,被划分为多个消息缓冲区(Message Buffer),每个缓冲区可独立配置为发送或接收。主机接口层则通过 SFR 寄存器、DMA 通道和中断线,把消息缓冲区与 CPU 内核连接起来。

需要特别注意的是,PIC32 的 ECAN 消息缓冲区 RAM 是模块私有存储,不占用普通数据 RAM 空间,CPU 只能通过特定的寄存器窗口(通常以 CANADDR 之类的间接寻址方式)访问。这一点与某些把报文直接映射到普通 RAM 的控制器不同,也是初学时最容易踩坑的地方。

PIC32 ECAN 模块架构框图 物理接口层 CANTX / CANRX 引脚 外部收发器 → CAN_H/L 协议引擎层 位定时 / 位填充 / CRC 仲裁 / 错误计数 / ACK 消息存储层(专用 RAM) 消息缓冲区 0 ~ N 发送缓冲 / 接收缓冲 主机接口层 SFR 寄存器窗口 / DMA 通道 中断聚合 → CPU 向量中断 验收过滤 过滤器 RxF0~RxF5 屏蔽器 RxM0~RxM1 关键数据通路说明 ① 总线位流经收发器进入 CANRX,协议引擎完成解码后写入接收消息缓冲区。 ② 接收缓冲区在写入前先经过过滤器/屏蔽器匹配,只有命中的报文才被存储。 ③ CPU 通过 SFR 窗口读写缓冲区;DMA 可在缓冲区与数据 RAM 之间搬运,无需 CPU 干预。 ④ 发送时 CPU/DMA 写入发送缓冲区,置位发送请求位后由协议引擎送上总线。 ⑤ 各类事件(接收、发送完成、错误、溢出)汇聚为中断源,映射到 CPU 中断向量。

二、寄存器映射与访问方式

ECAN 的控制与状态寄存器分布在 SFR 空间中,主要分为三类。第一类是模块级控制寄存器,例如 C1CON(使能、请求工作模式、中止所有发送)、C1CFG(配置接收 FIFO 深度、唤醒滤波等)、C1INT(中断使能与标志)、C1EC(错误计数器)、C1FCTRL(FIFO 控制)。第二类是位定时寄存器 C1CFG 中的 BRP、SJW、PRSEG、PHSEG1、PHSEG2 字段,它们共同决定波特率与采样点。第三类是消息缓冲区访问寄存器,包括 C1TR01CON 之类的发送控制寄存器、C1RXF0SID 之类的过滤器寄存器,以及用于间接访问缓冲区 RAM 的地址与数据窗口。

由于消息缓冲区 RAM 不在普通数据空间,访问它需要“先写地址、再读写数据”的两步操作。典型流程是:把目标缓冲区的字偏移写入 C1ADDR 的低位字段,然后从 C1RXDATA 或向 C1TXDATA 读写。每次访问后地址通常自动递增,因此连续读取一个报文的数据字节时,只需一次设置地址即可。这个细节在写 DMA 描述符时尤其重要,因为 DMA 搬运的正是这段窗口。

三、消息缓冲区组织

PIC32 ECAN 的消息缓冲区 RAM 被组织成若干条“消息”,每条消息占用固定的字数。以 PIC32MX 的 ECAN 为例,每条消息缓冲区通常占用 4 个字(16 字节),其中包含 SID、EID、DLC、数据字节以及状态/控制字段。缓冲区在逻辑上分为发送缓冲区与接收缓冲区,接收侧又常被组织成 FIFO,以支持按到达顺序处理。

发送缓冲区一般有 3 个(TXB0、TXB1、TXB2),每个都有独立的优先级控制位,可以配置发送优先级,也可以把多个缓冲区串联成 FIFO 以支持连续发送。接收侧则通常提供 2 个接收 FIFO(RXFIFO0、RXFIFO1),每个 FIFO 的深度可通过 C1CFG 的 RXFIFO0DEP、RXFIFO1DEP 字段配置,深度越大,突发流量下的抗溢出能力越强,但会占用更多缓冲区 RAM。此外还有若干独立的接收缓冲(RXB0、RXB1),用于特定过滤规则命中的报文。

一个实用的组织策略是:把高优先级、低速率的关键控制报文分配到独立接收缓冲,把周期性传感器数据分配到较深的 FIFO,把诊断报文分配到另一条 FIFO。这样在软件层就能用不同的处理节奏读取不同队列,避免关键报文被大量普通报文淹没。

四、过滤器与屏蔽器配置

过滤器(Filter)与屏蔽器(Mask)是接收路径上的“硬件筛选器”。过滤器寄存器保存期望匹配的标识符位,屏蔽器寄存器决定哪些位参与比较。规则是:屏蔽位为 1 表示该位必须与过滤器一致,为 0 表示该位不关心。例如,若希望接收所有标准帧 ID 在 0x100~0x10F 范围内的报文,可把过滤器设为 0x100,屏蔽器设为 0x7F0,这样低 4 位被忽略,高 7 位必须匹配。

PIC32 ECAN 通常提供 6 个过滤器(RxF0~RxF5)和 2 个屏蔽器(RxM0、RxM1)。过滤器与屏蔽器的绑定关系由 C1FCTRL 或相关配置位决定,常见做法是 RxF0/RxF1 共用 RxM0,RxF2~RxF5 共用 RxM1。每个过滤器还可以配置为只接收标准帧、只接收扩展帧或两者都接收。配置时必须先让模块进入配置模式(C1CON.REQOP = 100),修改完成后再切回正常模式,否则写入可能不生效。

过滤器与屏蔽器的匹配是“与”逻辑:只有屏蔽位为 1 的那些位,才要求过滤器与报文 ID 完全一致。设计过滤规则时,先确定“哪些位必须固定”,再把这些位在屏蔽器中置 1,其余位置 0,可以显著减少需要配置的过滤器数量。

五、DMA 支持与中断源

ECAN 模块与 DMA 控制器的配合,是降低高负载下 CPU 占用的关键。接收方向上,当一条报文被写入接收缓冲区后,可以触发 DMA 请求,由 DMA 把缓冲区窗口中的数据搬运到用户定义的数组或环形缓冲区。发送方向上,DMA 可以预先从内存取数据写入发送缓冲区,再由软件或硬件触发发送。使用 DMA 时要注意:DMA 搬运的是缓冲区窗口,因此描述符中的源/目的地址必须与 C1ADDR 窗口配合,且每次搬运的字数要与消息长度匹配。

中断源方面,ECAN 把多种事件聚合到少数几个中断向量上。常见的中断标志包括:接收缓冲区 0/1 有新报文、发送缓冲区 0/1/2 发送完成、接收 FIFO 溢出、发送错误计数超限、接收错误计数超限、总线唤醒、模块进入错误被动或总线关闭状态等。这些标志集中在 C1INT 寄存器中,通过 C1INT 的使能位决定哪些事件真正产生中断。由于多个事件共享一个向量,中断服务程序必须先读标志、再分派处理,处理完对应标志后要显式清零,否则会反复进入中断。

一个常见的工程做法是:接收中断只做“搬运或置标志”这类短操作,把协议解析放到主循环或任务中;发送完成中断用于释放发送缓冲区或触发下一帧;错误类中断则用于记录错误计数并决定是否进入恢复流程。这样既保证了实时性,又避免了在中断里做耗时处理。

修改过滤器、屏蔽器、位定时或缓冲区深度配置前,必须先把 ECAN 模块切到配置模式并等待 C1CON.OPMOD 确认进入;配置完成后切回正常模式并等待确认。在模块运行中直接改写这些寄存器,写入可能被忽略,表现为“配置看起来写了但行为不对”。

六、配置检查清单

在进入下一节的位定时计算之前,可以用下面这份清单快速核对架构层面的配置是否完整。它覆盖了本节涉及的模块框图、寄存器、缓冲区、过滤器和中断五个方面,适合在初始化代码写完后逐项确认。

检查项关键寄存器/字段预期状态
模块进入配置模式C1CON.REQOP / OPMODREQOP=100,OPMOD 回读为 100
位定时参数已写入C1CFG.BRP/SJW/PRSEG/PHSEG1/PHSEG2与目标波特率、采样点一致
接收 FIFO 深度C1CFG.RXFIFO0DEP / RXFIFO1DEP按流量预估设置,非零
过滤器与屏蔽器C1RXF0SID ~ C1RXF5SID、C1RXM0SID、C1RXM1SID屏蔽位与过滤规则匹配
发送缓冲区优先级C1TR01CON 等关键报文优先级高于普通报文
中断使能与标志C1INT所需事件使能,标志初始清零
DMA 请求映射DMA 通道配置寄存器源/目的与缓冲区窗口一致
模块切回正常模式C1CON.REQOP / OPMODREQOP=000,OPMOD 回读为 000