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 的控制器不同,也是初学时最容易踩坑的地方。
二、寄存器映射与访问方式
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),修改完成后再切回正常模式,否则写入可能不生效。
五、DMA 支持与中断源
ECAN 模块与 DMA 控制器的配合,是降低高负载下 CPU 占用的关键。接收方向上,当一条报文被写入接收缓冲区后,可以触发 DMA 请求,由 DMA 把缓冲区窗口中的数据搬运到用户定义的数组或环形缓冲区。发送方向上,DMA 可以预先从内存取数据写入发送缓冲区,再由软件或硬件触发发送。使用 DMA 时要注意:DMA 搬运的是缓冲区窗口,因此描述符中的源/目的地址必须与 C1ADDR 窗口配合,且每次搬运的字数要与消息长度匹配。
中断源方面,ECAN 把多种事件聚合到少数几个中断向量上。常见的中断标志包括:接收缓冲区 0/1 有新报文、发送缓冲区 0/1/2 发送完成、接收 FIFO 溢出、发送错误计数超限、接收错误计数超限、总线唤醒、模块进入错误被动或总线关闭状态等。这些标志集中在 C1INT 寄存器中,通过 C1INT 的使能位决定哪些事件真正产生中断。由于多个事件共享一个向量,中断服务程序必须先读标志、再分派处理,处理完对应标志后要显式清零,否则会反复进入中断。
一个常见的工程做法是:接收中断只做“搬运或置标志”这类短操作,把协议解析放到主循环或任务中;发送完成中断用于释放发送缓冲区或触发下一帧;错误类中断则用于记录错误计数并决定是否进入恢复流程。这样既保证了实时性,又避免了在中断里做耗时处理。
C1CON.OPMOD 确认进入;配置完成后切回正常模式并等待确认。在模块运行中直接改写这些寄存器,写入可能被忽略,表现为“配置看起来写了但行为不对”。六、配置检查清单
在进入下一节的位定时计算之前,可以用下面这份清单快速核对架构层面的配置是否完整。它覆盖了本节涉及的模块框图、寄存器、缓冲区、过滤器和中断五个方面,适合在初始化代码写完后逐项确认。
| 检查项 | 关键寄存器/字段 | 预期状态 |
|---|---|---|
| 模块进入配置模式 | C1CON.REQOP / OPMOD | REQOP=100,OPMOD 回读为 100 |
| 位定时参数已写入 | C1CFG.BRP/SJW/PRSEG/PHSEG1/PHSEG2 | 与目标波特率、采样点一致 |
| 接收 FIFO 深度 | C1CFG.RXFIFO0DEP / RXFIFO1DEP | 按流量预估设置,非零 |
| 过滤器与屏蔽器 | C1RXF0SID ~ C1RXF5SID、C1RXM0SID、C1RXM1SID | 屏蔽位与过滤规则匹配 |
| 发送缓冲区优先级 | C1TR01CON 等 | 关键报文优先级高于普通报文 |
| 中断使能与标志 | C1INT | 所需事件使能,标志初始清零 |
| DMA 请求映射 | DMA 通道配置寄存器 | 源/目的与缓冲区窗口一致 |
| 模块切回正常模式 | C1CON.REQOP / OPMOD | REQOP=000,OPMOD 回读为 000 |