LPC29xx CAN控制器自测与全局验收滤波器实战解析
1. 项目概述与核心价值
在嵌入式系统,尤其是汽车电子和工业控制领域,CAN总线是连接各个电子控制单元的“神经系统”。它的稳定性和效率直接决定了整个系统的可靠性与实时性。然而,仅仅让CAN控制器能够收发数据是远远不够的。想象一下,一个繁忙的CAN网络上充斥着上百条不同功能的报文,如果每个报文都触发CPU中断,让CPU去逐一判断“这条消息是不是给我的?”,那CPU将不堪重负,宝贵的计算资源会被大量浪费在无效的报文筛选上。
这正是CAN验收滤波器存在的意义。它就像一位训练有素的“交通协管员”,站在CAN控制器的入口,只允许那些持有“通行证”(即符合预设标识符)的报文进入接收缓冲区,从而极大地减轻了CPU的负担。LPC29xx系列微控制器集成的CAN控制器,其全局验收滤波器设计得尤为精妙和强大。它不仅支持标准帧和扩展帧的精确匹配与范围匹配,还引入了独特的FullCAN模式,可以将特定报文直接存入专用内存,实现近乎零开销的快速数据获取。
与此同时,在开发调试或系统自检阶段,如何在不依赖外部节点的情况下,验证CAN控制器自身的收发链路是否完好?LPC29xx的自测模式为此提供了优雅的解决方案。通过设置自接收请求,控制器可以自发自收,形成一个内部闭环,快速诊断硬件链路。
本文将深入拆解LPC29xx CAN控制器的这两大核心机制:自测功能与全局验收滤波器。我会结合多年的嵌入式开发经验,不仅告诉你它们“是什么”,更会重点剖析“为什么这么设计”以及“在实际项目中如何用好”。无论你是正在评估LPC29xx的架构师,还是正在调试CAN驱动的工程师,相信这些从芯片手册字里行间提炼出的实战细节和避坑指南,都能为你带来直接的帮助。
2. CAN控制器自测功能深度解析
自测功能是CAN控制器硬件诊断的利器。它的核心思想是让控制器自己给自己发消息,并验证能否正确收到,从而在系统集成早期或故障排查时,快速隔离问题——是软件配置错误,还是物理层(如收发器、线缆)故障?LPC29xx提供了两种自测模式:全局自测和本地自测。虽然原理都基于“自接收请求”,但应用场景和硬件依赖截然不同。
2.1 全局自测:多节点系统的配置验证
全局自测(Global Self-Test)用于验证在一个真实的、至少包含两个节点的CAN网络中的控制器配置是否正确。它的工作前提是:总线上必须存在至少一个其他能够正常应答的CAN节点。
2.1.1 工作原理与硬件依赖
当你发起一次全局自测时,控制器会像正常发送一样,将报文放到总线上。关键区别在于,它同时会置位自接收请求位,并配置验收滤波器,允许接收自己刚发出的这个报文ID。总线上另一个节点在收到此报文后,会按照CAN协议回复一个“应答位”。只有收到这个外部应答,本次发送才被视为成功。紧接着,控制器自身的接收逻辑会通过验收滤波器匹配到这个报文,并将其存入接收缓冲区,从而同时产生发送完成中断和接收中断。
这个过程验证了什么?它验证了一条完整的、端到端的通信链路:
- 本地TX通路:控制器的发送逻辑、TX引脚驱动是否正常。
- 物理层:CAN收发器、总线终端电阻、线缆连接是否完好。
- 远程节点:对方节点的收发功能是否正常。
- 本地RX通路及滤波器配置:控制器的接收逻辑、RX引脚以及验收滤波器的配置是否正确。
如果全局自测成功(即收到了TX和RX中断),那么基本可以断定,从本节点到总线,再到另一个节点的整个物理和基础数据链路层都是通的,且本地滤波配置无误。
2.1.2 操作流程与寄存器配置
进行全局自测,控制器需处于正常操作模式。操作流程高度封装,主要通过命令寄存器CCCMD触发:
前期准备:
- 配置好CAN波特率、工作模式等。
- 必须正确配置全局验收滤波器,确保将要自测的报文ID能被接收。例如,如果你打算发送ID为
0x123的标准数据帧,那么必须在验收滤波器的某个区域(如标准帧显式标识符段)添加该ID。 - 使能发送中断和接收中断。
填充发送缓冲区:向选定的发送缓冲区(如
CCTXB1MI,CCTXB1ID,CCTXB1DA/DB)写入要发送的报文信息,包括ID、数据长度码和数据。触发自测发送:向
CCCMD寄存器写入特定值。这是最关键的一步。你需要同时置位:SRR:自接收请求位,设为1。STBx:选择发送缓冲区位(STB1, STB2, STB3),根据你使用的缓冲区置位。TR:传输请求位,设为1。
例如,使用发送缓冲区1进行自测,则写入
CCCMD = (1 << 4) | (1 << 5) | (1 << 0),即同时置位SRR、STB1和TR。等待与判断:控制器将报文发出。如果总线上的其他节点给予了应答,则发送成功,产生发送中断。同时,该报文通过验收滤波器被自己接收,产生接收中断。在接收中断服务程序中,你可以读取接收缓冲区的数据,与发送的数据进行比对,确保内容一致。
注意:全局自测失败的可能原因很多。如果只有发送中断没有接收中断,可能是验收滤波器配置错误,或者接收部分硬件故障。如果连发送中断都没有,则可能是波特率配置错误、总线物理层故障(如终端电阻缺失导致无法产生应答),或另一个节点根本不存在/未工作。
2.2 本地自测:单节点硬件闭环检验
本地自测(Local Self-Test)的应用场景更为独立,它用于测试单个CAN节点自身的完整性,无需任何外部节点参与。这在产品出厂测试、模块单独调试或排查是否因外部总线故障导致本机问题时非常有用。
2.2.1 工作原理与模式切换
本地自测的核心是将控制器置于自测模式。在此模式下,控制器内部逻辑会“模拟”一个来自总线的应答,因此它不依赖也不检查物理总线上是否有其他节点的应答位。只要报文被成功发出(从TX引脚输出),控制器就认为发送成功,随即产生发送中断。同时,由于SRR位被置位,该报文也会被导入接收路径,通过验收滤波器后产生接收中断。
关键配置在于模式寄存器CCMODE。你必须先将控制器置于复位模式(RM=1),才能设置自测模式位STM=1。退出复位模式后,控制器便运行在自测模式下。
2.2.2 操作流程与注意事项
本地自测的软件操作流程与全局自测类似,但硬件环境和模式设置不同:
- 进入复位模式:向
CCMODE寄存器写入,设置RM=1。 - 使能自测模式:在
RM=1的前提下,设置CCMODE寄存器的STM=1。 - 退出复位模式:清除
CCMODE寄存器的RM位(设为0),控制器开始运行。 - 配置验收滤波器与中断:同样,必须配置滤波器以接收自测报文ID,并使能TX/RX中断。
- 填充发送缓冲区并触发:与全局自测步骤完全相同,向
CCCMD写入SRR|STBx|TR。 - 验证结果:此时,只要本节点的TX引脚和收发器输出正常,就会产生发送中断和接收中断。即使CAN总线完全断开,测试也能成功。
重要心得:本地自测是验证“从芯片引脚到收发器输出”这段链路是否完好的黄金标准。但它无法验证总线物理层(如阻抗匹配)或与其他节点的交互。一个常见的调试策略是:当系统通信异常时,先让问题节点进行本地自测。如果自测失败,则问题大概率出在该节点本身的CAN控制器或收发器电路上;如果自测成功,则问题可能出在总线物理层、其他节点或网络负载等方面。
2.3 自测功能的应用场景与避坑指南
应用场景:
- 驱动开发与单元测试:在编写CAN底层驱动时,使用本地自测可以快速验证驱动代码对寄存器的读写、中断配置是否正确,无需搭建复杂的多节点环境。
- 生产测试:在产品出厂前,通过本地自测可以快速筛查出CAN接口硬件焊接不良或芯片损坏的故障品。
- 系统故障诊断:当网络通信异常时,通过让各节点依次进行全局自测(需至少一个参考节点在线)或本地自测,可以快速定位故障节点。
- 滤波器配置验证:自测是验证复杂验收滤波器配置是否生效的直观方法。发送特定ID的报文,观察是否能触发接收中断。
避坑指南与常见问题:
- 中断风暴:如果验收滤波器配置为接收所有报文(如旁路模式),在自测时可能会因为收到自己发出的报文而产生一次接收中断。这是正常的。但如果中断重复触发,需检查是否在中断服务程序中正确释放了接收缓冲区(对普通模式)或读取了FullCAN消息对象(对FullCAN模式)。
- 自测模式忘记退出:这是一个低级但容易发生的错误。在完成本地自测后,如果忘记将
STM位清零并重新初始化控制器,控制器将无法与真实总线通信,因为它不再监听外部应答。务必在自测完成后,先将控制器置为复位模式(RM=1),再清除STM位,最后退出复位模式。 - 滤波器配置遗漏:这是自测失败的最常见原因。无论全局还是本地自测,都必须确保你发送的报文ID在验收滤波器的允许列表中,否则报文发出后会被自己的过滤器丢弃,无法产生接收中断。
- 单次传输模式:
CCCMD寄存器中的AT(中止传输)位与TR和SRR结合使用,可以实现“单次传输”。这在某些测试场景下有用,可以防止报文在出错时无休止重发。但需注意,在自测中若使用单次传输且发生错误(如总线冲突,在全局测试中可能发生),则不会重试,可能导致测试结果不稳定。
3. 全局验收滤波器原理与架构
如果说自测功能是CAN控制器的“体检医生”,那么全局验收滤波器就是其“智能门卫”。LPC29xx的全局验收滤波器设计非常模块化且功能强大,它独立于CAN控制器,为芯片上的所有CAN通道(CAN0, CAN1)提供统一的过滤服务。理解其架构是进行高效配置的基础。
3.1 滤波器核心:ID查找表内存
全局验收滤波器的核心是一块2KB大小的ID查找表内存。这块内存可以被软件(CPU)读写,用于存放所有需要接收的CAN报文标识符规则。它的组织方式非常巧妙:
- 容量:2KB = 512个32位字。
- 存储内容:可以存储最多1024个11位的标准帧标识符,或512个29位的扩展帧标识符,或两者的混合。
- 关键特性:这块内存是仅按字寻址的。这意味着你不能单独读写一个16位的半字或8位的字节,每次访问必须以32位为单位。这在编程时需要特别注意数据结构对齐。
查找表内存被划分为最多五个连续的段,每个段存放一种特定类型的过滤规则。这五个段及其顺序是固定的,构成了过滤器的搜索路径:
- 标准帧格式FullCAN标识符段
- 标准帧格式显式标识符段
- 标准帧格式组标识符段
- 扩展帧格式显式标识符段
- 扩展帧格式组标识符段
3.2 段边界控制:起始地址寄存器
五个段在内存中如何划分?边界由一组起始地址寄存器定义。这些寄存器存储的是相对于查找表基地址CANAFM的偏移量(以字为单位)。
CASFESA:标准帧显式标识符段起始地址。CASFGSA:标准帧组标识符段起始地址。CAEFESA:扩展帧显式标识符段起始地址。CAEFGSA:扩展帧组标识符段起始地址。CAEOTA:表结束地址。它标识了整个标识符列表的结束,同时也是FullCAN消息对象段的开始。
段的存在性判断:如果两个连续的起始地址寄存器的值相等,则表示这两个段之间的那个段是“不存在”的(长度为0)。例如,如果CASFESA == CASFGSA,则表示标准帧显式标识符段为空。
搜索顺序的固化:验收滤波器对报文的筛查严格按照上述1到5的顺序进行。一旦在某个段中找到匹配项,搜索立即停止,后续段不再检查。这个顺序是硬件固定的,无法更改。因此,FullCAN段的优先级最高。如果你将同一个ID既放在FullCAN段,又放在标准帧显式段,那么报文只会被FullCAN逻辑处理。
3.3 各段数据结构详解
每个段在内存中的数据结构都有明确规范,编程时必须严格遵守。
3.3.1 标准帧格式FullCAN标识符段
这是为FullCAN模式服务的特殊段。FullCAN模式是一种高级功能,允许将特定ID的报文数据直接存储到一块专有的消息对象内存中,无需CPU通过读接收缓冲区来获取,极大地减少了中断延迟和CPU开销。
- 存储格式:每个32位字存放两个11位标准帧ID。
- 位[31:29]:SCC (Source CAN Channel),源CAN通道号(0或1),指定这个ID属于哪个CAN控制器。
- 位[28]:MDB (Message Disable Bit),消息禁用位。0=启用,1=禁用。可以动态开关对某个ID的接收。
- 位[27]:保留。
- 位[26:16]:ID[28:18],11位CAN标识符的高11位(对于标准帧,ID位[28:18]即完整的11位ID)。
- 位[15:13]:第二个ID的SCC。
- 位[12]:第二个ID的MDB。
- 位[11]:保留。
- 位[10:0]:第二个ID的ID[28:18]。
- 排序要求:该段内的所有ID必须按照数值升序排列。这是硬件查找算法(通常是二分查找或类似高效算法)的要求,不排序会导致过滤失败或产生不可预知的行为。
3.3.2 标准帧/扩展帧显式标识符段
这两个段用于精确匹配单个ID。它们的结构类似,区别在于ID的位数。
- 标准帧显式段:每个32位字存放两个11位ID,格式与FullCAN标识符段完全相同(但不用于FullCAN逻辑)。
- 扩展帧显式段:每个32位字存放一个29位扩展ID。
- 位[31:29]:SCC。
- 位[28:0]:完整的29位扩展标识符。
3.3.3 标准帧/扩展帧组标识符段
这两个段用于范围匹配,接收一个ID区间内的所有报文。这在需要接收一组连续或相关ID的报文时非常高效,无需逐个列出每个ID。
- 数据结构:每个“组”由两个连续的32位字定义。
- 第一个字:定义范围的下限(Lower Bound)。
- 第二个字:定义范围的上限(Upper Bound)。
- 匹配规则:只要接收到的ID满足
下限 ≤ ID ≤ 上限,即被视为匹配。上下限值本身也包含在范围内。 - 排序要求:各个“组”必须按照其下限值的数值升序排列。
3.4 过滤器工作模式与配置
全局验收滤波器有三种工作模式,通过CAMODE寄存器的ACCOFF和ACCBP位控制:
关闭模式:
ACCOFF = 1。在此模式下,过滤器完全关闭,所有接收到的报文都不会被存入接收缓冲区。CPU可以无条件访问所有过滤器的寄存器和查找表内存。此模式通常仅用于初始化配置阶段,用于安全地写入过滤规则。旁路模式:
ACCBP = 1。在此模式下,过滤器逻辑被绕过,所有接收到的报文都会被存入接收缓冲区。此时,CPU仍然可以读写查找表内存。这个模式非常有用:- 动态重配置:可以在系统运行时修改过滤规则。先进入旁路模式,修改查找表,再退出旁路模式启用新规则。
- 调试与监听:需要监听总线上所有流量时使用。
- 在旁路模式下,软件需要自己处理ID过滤,可以通过读取报文ID来判断是否需要处理。
过滤模式:
ACCOFF = 0且ACCBP = 0。这是正常工作模式。过滤器根据查找表内存中的规则对报文进行筛选,只有匹配的报文才会被存入接收缓冲区或FullCAN消息对象区。
模式切换的注意事项:从关闭模式或旁路模式切换到过滤模式前,必须确保查找表内存中的内容已正确配置且排序无误。硬件不会检查表的有效性,错误的配置可能导致过滤器工作异常。
4. FullCAN模式:高性能数据接收的利器
FullCAN模式是LPC29xx CAN控制器的一个亮点功能,它专为需要极低延迟、极高确定性处理特定CAN报文的场景设计。在传统的缓冲区模式下,CPU需要在中断服务程序中读取多个寄存器来获取报文数据。而在FullCAN模式下,报文数据被直接DMA到一块结构化的内存区域,CPU可以像访问普通数组一样直接读取,效率极高。
4.1 FullCAN模式的工作原理与激活条件
当验收滤波器在标准帧格式FullCAN标识符段找到一个匹配的ID时,如果FullCAN模式已激活,它不会将报文放入普通的接收缓冲区,而是执行以下操作:
- 根据匹配ID在FullCAN标识符段中的索引
i,计算出对应的FullCAN消息对象在内存中的地址:消息对象地址 = CAEOTA + (12 × i)。这里CAEOTA是表结束地址寄存器,12 × i是因为每个FullCAN消息对象占用12个字节。 - 将接收到的报文数据(包括帧格式、远程帧标志、数据长度码、标识符和最多8字节数据)直接写入到这个计算出的固定地址。
- 更新该消息对象内部的信号量状态,通知CPU有新数据可用。
激活FullCAN模式必须同时满足三个条件:
- 模式使能:将
CAMODE寄存器中的EFCAN位设置为1。 - 空间预留:
CAEOTA寄存器指向的地址之后,必须有足够的连续内存空间来存放所有在FullCAN标识符段中定义的ID所对应的消息对象。每个对象占12字节。 - 段有效:标准帧显式标识符段的起始地址
CASFESA必须大于0。这意味着FullCAN段必须位于查找表内存的起始部分(偏移0处),并且后面至少跟随着一个有效的显式标识符段(即使该段为空,也需要一个起始地址来界定)。
4.2 FullCAN消息对象布局与信号量机制
每个FullCAN消息对象是一个12字节的数据结构,布局如下表所示:
| 地址偏移 | 位域 | 符号 | 描述 |
|---|---|---|---|
| +0 | 31 | FF | 帧格式:0=标准帧,1=扩展帧 |
| +0 | 30 | RTR | 远程帧请求位 |
| +0 | [25:24] | SEM[1:0] | 信号量位,用于协调CPU与过滤器状态机的访问 |
| +0 | [22:16] | RXDLC[6:0] | 数据长度码 (DLC) |
| +0 | [10:0] | ID[28:18] | 11位标准标识符 |
| +4 | [31:0] | RXDATA[4:1] | 接收到的数据字节1到4 |
| +8 | [31:0] | RXDATA[8:5] | 接收到的数据字节5到8 |
信号量机制是FullCAN模式实现无锁、安全数据访问的关键。它是一个简单的三状态机:
- SEM[1:0] = 01:接受过滤器状态机正在更新此消息对象。CPU不应读取数据。
- SEM[1:0] = 11:接受过滤器已完成更新,新数据已就绪,CPU可以读取。
- SEM[1:0] = 00:CPU正在读取或已经读取了数据,且自上次读取后没有新数据更新。
CPU读取FullCAN数据的推荐流程:
- 轮询或通过FullCAN中断获知某个消息对象有数据更新。
- 读取该消息对象的
SEM位。如果为11,继续下一步;如果为01,则等待。 - 将
SEM位写为00,表示CPU开始读取。 - 读取消息对象的所有数据(12字节)。
- 再次读取
SEM位。- 如果
SEM仍为00,说明读取过程中没有新数据覆盖,读取的数据是完整且一致的。 - 如果
SEM变为01或11,说明在读取过程中,过滤器状态机已经开始或完成了新一轮的数据写入。此时之前读出的数据可能是不完整的(新旧数据混合),必须放弃本次读取结果,重新从步骤2开始。
- 如果
这个机制确保了即使在CPU读取速度较慢,而CAN报文接收频率很高的情况下,也能避免读到“半新半旧”的损坏数据。
4.3 FullCAN模式的优势、局限与配置示例
优势:
- 极低延迟:数据直接存入内存,CPU无需通过寄存器间接访问。
- 确定性高:访问时间是固定的内存读时间,不受中断延迟、总线仲裁等因素影响。
- 减轻CPU负担:CPU可以以轮询或更低优先级的方式处理数据,无需为每个报文进入高优先级中断。
- 数据一致性:通过信号量机制保证。
局限:
- 仅支持标准帧:FullCAN模式只适用于11位标准标识符的报文。
- 占用固定内存:每个ID需要预留12字节,ID较多时占用可观内存。
- 配置相对复杂:需要仔细规划查找表布局和
CAEOTA的地址。
配置示例: 假设我们需要使用FullCAN模式接收ID为0x123和0x456的报文,来自CAN0。
- 规划查找表:FullCAN标识符段从偏移0开始。我们需要写入两个32位字。
- 字0 (地址
CANAFM+0x0):存放ID0x123和0x456。因为要求升序,所以0x123在低半字,0x456在高半字。- 低半字:SCC=0, MDB=0, ID=
0x123。 - 高半字:SCC=0, MDB=0, ID=
0x456。
- 低半字:SCC=0, MDB=0, ID=
- 字0 (地址
- 设置段边界寄存器:
CASFESA= 1 (因为FullCAN段用了1个字,下一个段从偏移1开始)。CASFGSA,CAEFESA,CAEFGSA根据是否需要其他过滤段来设置。假设我们只需要FullCAN,可以将它们都设置为1,表示后面的段为空。CAEOTA= 1 + N。其中N是除FullCAN段外,其他所有段占用的总字数。这里其他段为空,所以N=0,CAEOTA= 1。这意味着FullCAN消息对象段将从偏移1(即第2个字)开始。
- 计算消息对象地址:
- ID
0x123的索引 i = 0,其消息对象地址 =CAEOTA + 12*0= 偏移1字开始。 - ID
0x456的索引 i = 1,其消息对象地址 =CAEOTA + 12*1= 偏移1字 + 12字节。注意,CAEOTA是字地址,而12*i是字节偏移。在计算实际内存地址时,需要将字地址转换为字节地址:(CAEOTA * 4) + (12 * i)。
- ID
- 使能FullCAN模式:设置
CAMODE.EFCAN = 1。
5. 验收滤波器配置实战与搜索算法
理解了原理和结构后,如何动手配置一个满足实际需求的过滤器?本节将结合一个综合示例,一步步拆分配置过程,并深入分析其背后的搜索算法。
5.1 一个综合配置案例
假设我们有一个基于LPC29xx的系统,需要配置CAN0的验收滤波器,要求如下:
- 以FullCAN模式高速处理关键控制指令:ID
0x100(标准帧)。 - 接收一组传感器数据:ID
0x200到0x20F(标准帧)。 - 接收几个特定的扩展帧诊断报文:ID
0x18DA00F1,0x18DB33C2。 - 忽略所有其他报文。
步骤一:规划查找表内存布局我们使用所有五个段。需要计算每个段的大小。
- FullCAN段:1个ID (
0x100)。占1个半字,但按字存取,所以占用1个字。 - 标准帧显式段:本例未使用,设为空。但
CASFESA必须大于0,我们将其设置为下一个字的起始。 - 标准帧组段:1个组,范围
0x200-0x20F。一个组占2个字(下限和上限)。 - 扩展帧显式段:2个ID。占2个字。
- 扩展帧组段:本例未使用,设为空。
设起始地址偏移为字地址。
CASFESA= 1 (FullCAN段占用了字0)CASFGSA=CASFESA= 1 (标准帧显式段为空)CAEFESA=CASFGSA+ 2 = 3 (标准帧组段占用了字1和字2)CAEFGSA=CAEFESA+ 2 = 5 (扩展帧显式段占用了字3和字4)CAEOTA=CAEFGSA= 5 (扩展帧组段为空,表结束)
步骤二:填充查找表内存从基地址CANAFM开始:
- 偏移
0x0:写入FullCAN条目。字 ={SCC:0, MDB:0, ID:0x100} << 16(高半字暂时为空,因为只有一个ID,低半字放0x100)。实际上,我们需要按格式填充一个完整的字,假设我们将高半字的MDB设为1(禁用)作为填充。 - 偏移
0x4(字1):标准帧组的下限字。{SCC:0, MDB:0, ID:0x200}。 - 偏移
0x8(字2):标准帧组的上限字。{SCC:0, MDB:0, ID:0x20F}。 - 偏移
0xC(字3):扩展帧显式ID0x18DA00F1。{SCC:0, ID:0x18DA00F1}。 - 偏移
0x10(字4):扩展帧显式ID0x18DB33C2。{SCC:0, ID:0x18DB33C2}。
步骤三:配置寄存器
- 将计算好的
CASFESA=1,CASFGSA=1,CAEFESA=3,CAEFGSA=5,CAEOTA=5写入对应的边界寄存器。 - 使能FullCAN模式:设置
CAMODE.EFCAN = 1。 - 关闭旁路和关闭模式:设置
CAMODE.ACCBP = 0,CAMODE.ACCOFF = 0,让过滤器生效。
步骤四:处理FullCAN消息对象由于CAEOTA=5,FullCAN消息对象段从字偏移5开始。ID0x100的索引i=0,其消息对象地址为:(5 * 4) + (12 * 0) = 0x14(字节地址)。在软件中,我们可以将这个地址定义为一个指向FullCAN_MsgObj结构体的指针,方便访问。
5.2 搜索算法流程与优先级
当CAN控制器收到一帧报文时,全局验收滤波器的状态机便启动一次搜索。搜索顺序是严格固定的,如下图所示:
收到报文 | v [1] FullCAN段 (标准帧) ---匹配---> 存入FullCAN消息对象,结束。 |不匹配 v [2] 标准帧显式段 ---匹配---> 存入RX缓冲区,结束。 |不匹配 v [3] 标准帧组段 ---匹配---> 存入RX缓冲区,结束。 |不匹配 v [4] 扩展帧显式段 ---匹配---> 存入RX缓冲区,结束。 |不匹配 v [5] 扩展帧组段 ---匹配---> 存入RX缓冲区,结束。 |不匹配 v 报文被丢弃关键规则:
- 首次匹配终止:一旦在某个段找到匹配,立即停止搜索,后续段即使包含该ID也不会被检查。
- 段使能控制:通过设置段起始地址寄存器使某个段“不存在”(相邻寄存器值相等),可以跳过该段的搜索。
- 动态禁用:每个条目(组条目为上下限一对)都有一个
MDB位。软件可以在运行时动态地将某个ID或ID组的MDB设为1,从而临时禁用对该报文的接收,而不需要修改整个查找表结构。这在实现网络管理或功能开关时非常有用。
5.3 常见配置陷阱与调试技巧
- 排序错误:这是最常导致过滤器失效的原因。务必确保每个段内的ID或组下限是严格升序排列的。在初始化代码中,添加一个排序检查函数是很好的实践。
- 地址计算错误:混淆字地址和字节地址。寄存器里存的是字偏移,而
CAEOTA + 12*i中的CAEOTA是字地址,12*i是字节偏移。在实际指针计算时,务必转换正确:消息对象字节地址 = (CAEOTA * 4) + (12 * i)。 - FullCAN模式激活失败:检查三个条件是否同时满足:
EFCAN=1、CASFESA>0、CAEOTA之后有足够空间。特别是CASFESA,如果设为0,FullCAN模式无法激活。 - 过滤器不生效:首先检查
CAMODE寄存器,确认不在关闭模式(ACCOFF=0)且不在旁路模式(ACCBP=0)。然后,使用自测功能发送一个应该被匹配的ID,观察是否能产生接收中断。如果不行,尝试进入旁路模式(ACCBP=1),看报文是否能被接收。如果能,则问题出在查找表配置;如果不能,则问题可能出在CAN控制器基础配置或硬件上。 - 性能考量:查找表越大,搜索时间可能越长。虽然硬件实现通常很快,但在高波特率、高负载的总线上,如果过滤器列表非常长,仍需考虑其对实时性的潜在影响。合理使用组过滤可以减少条目数量。
6. 相关寄存器详解与编程要点
要熟练运用自测和过滤器,必须掌握几个关键寄存器。手册中的表格信息量大,这里提炼出编程中最需要关注的点。
6.1 模式寄存器CCMODE与命令寄存器CCCMD
CCMODE (CAN Controller Mode Register):
STM:自测模式位。只能在复位模式(RM=1)下修改。RM:软件复位模式位。写1进入复位,写0开始正常工作。修改波特率、过滤器配置前,通常需要先进入复位模式。LOM:只听模式。置位后,控制器只接收不发送,也不发送应答位。用于网络监听,控制器会进入错误被动状态。
CCCMD (CAN Controller Command Register):
TR:传输请求。写1启动所选缓冲区的发送。SRR:自接收请求。必须与TR和STBx同时设置才有效。STB1/2/3:选择发送缓冲区1/2/3。RRB:释放接收缓冲区。在读取完接收缓冲区数据后,必须写1释放,以便存储新报文。AT:中止传输。与TR同时设置可实现单次发送。
编程提示:向
CCCMD写命令时,通常是一次性设置多个位。例如,启动缓冲区1自测发送:CCCMD = (1<<5) | (1<<4) | (1<<0);即STB1=1, SRR=1, TR=1。命令寄存器是只写的,读操作无意义。
6.2 验收滤波器模式寄存器CAMODE
CAMODE (CAN Acceptance Filter Mode Register):
EFCAN:使能FullCAN模式。ACCBP:验收滤波器旁路模式。ACCOFF:验收滤波器关闭模式。
模式切换顺序建议:
- 初始化或修改查找表:
ACCOFF = 1。 - 配置查找表内存和边界寄存器。
- 若要动态更新(运行时):
ACCBP = 1,然后修改查找表。 - 启用过滤:
ACCBP = 0,ACCOFF = 0。
6.3 状态寄存器与中断
CCSTAT (CAN Controller Status Register):包含发送完成、接收就绪、总线错误、错误状态等标志。在中断服务程序中,通过读取此寄存器来判断事件源。CCIE (CAN Controller Interrupt Enable Register):用于使能各种中断源,如发送中断、接收中断、错误中断等。FCANIC0/1 (FullCAN Interrupt and Capture Registers):在FullCAN模式下,当某个消息对象更新时,对应的位会被置位,可用于产生中断,通知CPU哪个ID的数据有更新。
中断处理流程要点:
- 普通接收中断:检查
CCSTAT的接收位,读取CCRXBMI、CCRXBID、CCRXBDA/B获取数据,最后向CCCMD写RRB=1释放缓冲区。 - FullCAN中断:检查
FCANIC0/1寄存器,确定是哪个消息对象索引产生了中断。然后按照前述信号量机制读取对应地址的数据。 - 错误处理:务必使能错误中断并处理,特别是总线关闭错误,需要软件干预才能恢复。
7. 总结与最佳实践建议
LPC29xx的CAN控制器自测与全局验收滤波器是一套强大而精密的机制。自测功能为硬件和底层软件调试提供了闭环验证手段,而全局验收滤波器,尤其是FullCAN模式,则为构建高效、实时的CAN通信系统提供了坚实的硬件基础。
回顾几个核心要点:
- 自测是验证手段:本地自测查自身,全局自测验网络。善用它们可以快速定位通信问题是出在软件配置、本地硬件还是网络环境。
- 滤波器是效率关键:合理的过滤规则是降低CPU负载、提升系统实时性的不二法门。优先使用组过滤来接收连续ID,对关键高频报文使用FullCAN模式。
- 配置是精细活:查找表的排序、边界寄存器的计算、FullCAN地址的映射,每一步都需要仔细。建议编写专用的配置函数和验证函数,并在初始化后通过自测进行功能验证。
- 理解搜索优先级:FullCAN段优先级最高。避免将同一个ID配置在多个段,除非你明确需要利用优先级进行动态切换(通过MDB位)。
在实际项目中,我通常会采取以下步骤:
- 系统设计阶段:规划好所有需要收发的CAN ID,将其分类(关键控制、周期数据、诊断信息),并据此设计过滤器分段。
- 驱动实现阶段:封装好过滤器的配置接口,包括查找表构建、排序、寄存器设置。同时实现FullCAN消息对象的映射和访问接口。
- 调试阶段:先使用旁路模式,确保物理层和基础通信正常。然后逐步使能过滤器,并使用自测功能对每个过滤段进行测试。最后,在高负载环境下进行长时间测试,验证稳定性和性能。
LPC29xx的这些特性虽然初次接触会觉得寄存器繁多、配置复杂,但一旦掌握,它们将成为你打造高可靠性嵌入式CAN网络的得力工具。希望这篇深入的解析能帮助你绕过我当年踩过的那些坑,更高效地驾驭这颗芯片的CAN功能。
