MC68HC908AT32的MSCAN08控制器配置实战:从寄存器到CAN节点开发

📅 2026/6/21 15:33:20
MC68HC908AT32的MSCAN08控制器配置实战:从寄存器到CAN节点开发
1. 项目概述从芯片手册到实战配置如果你正在开发基于MC68HC908AT32这类老牌8位微控制器的CAN总线节点比如一个车载诊断接口、一个工业现场的远程I/O模块或者一个老式设备的通信网关那么你肯定绕不开它的MSCAN08控制器。手册里那几十页密密麻麻的寄存器描述是不是看得你头大每个比特位都认识但连起来就不知道从何下手了。我当年第一次调MSCAN08的时候也这样感觉像在解一本天书。但后来在几个汽车电子项目里摸爬滚打把CAN通信从调不通调到稳定跑上几个月不出错才真正把这些寄存器给“盘”明白了。今天我就以一个过来人的身份带你把这些枯燥的寄存器表格还原成一套清晰的、可实操的配置逻辑。我们不止看“它是什么”更要弄懂“为什么要这么设”以及“实际配置时有哪些坑”。简单说MSCAN08就是嵌在MC68HC908AT32芯片里的一个CAN协议处理器。你的软件CPU不需要去操心比特填充、CRC计算、错误帧这些底层脏活累活只需要通过一组映射到内存地址的寄存器从$0500开始告诉MSCAN08“波特率用多少”、“我只想接收ID是0x123的消息”、“有数据来了记得打断我一下”。它就会自动完成从物理层到数据链路层的所有协议处理。这个过程的核心就是与这些控制寄存器的对话。搞懂了它们你就能让这个沉默的硬件模块按照你的意志在CAN总线上可靠地收发数据。下面我们就从最核心的配置流程开始一步步拆解。2. 核心思路模块化配置流程拆解面对几十个寄存器最忌讳的就是一头扎进去逐个比特位研究。我的经验是按照一个清晰的、阶段化的流程来配置不仅效率高而且不容易出错。整个MSCAN08的初始化配置可以归纳为以下四个核心阶段你必须按顺序进行第一阶段模块复位与全局开关这是所有操作的起点。通过设置模块控制寄存器0CMCR0的SFTRES软复位位让MSCAN08进入一个已知的、可配置的初始状态。在这个状态下许多关键的配置寄存器如总线定时、标识符过滤才允许被写入。这就好比给设备上电自检你必须先让它“停下来听你说话”。第二阶段通信脉搏——总线定时配置这是决定通信能否成功的基础。你需要根据外部晶振频率和你期望的CAN总线波特率如125kbps, 250kbps, 500kbps精确计算并设置总线定时寄存器0和1CBTR0, CBTR1。这里涉及到三个核心概念波特率预分频器BRP、时间段1TSEG1、时间段2TSEG2和同步跳转宽度SJW。配置错误轻则通信错误频发重则根本无法同步到总线。这一步是纯数学计算必须仔细。第三阶段信息筛选器——标识符验收过滤CAN总线是广播式的总线上所有消息所有节点都能“听”到。但你的节点可能只关心其中特定的几条消息。标识符验收过滤器就是MSCAN08的“耳朵”它只把符合条件的数据放入接收缓冲区并通知CPU。通过配置标识符接受控制寄存器CIDAC、接受寄存器CIDAR0-3和掩码寄存器CIDMR0-3你可以设置最多4个过滤器灵活地筛选标准帧或扩展帧。这是降低CPU中断负载、提升系统实时性的关键。第四阶段事件管家——中断与缓冲区管理配置完成后MSCAN08就开始工作了。它如何通知你“数据收到了”、“发送成功了”或“出错了”这就需要通过中断使能寄存器CRIER, CTCR和标志寄存器CRFLG, CTFLG来建立通信机制。你是选择让CPU不断轮询Polling查看状态标志还是让MSCAN08在事件发生时主动触发中断Interrupt通常为了效率我们选择中断模式。同时你还需要管理好3个发送缓冲区和2个接收缓冲区前台/后台了解它们的优先级TBPR和空满状态TXE, RXF。核心心得配置的“锁”与“钥匙”手册里反复强调一点CBTR0, CBTR1, CIDAC, CIDAR, CIDMR这些寄存器只有在SFTRES1软复位状态时才能被写入。这是很多新手容易栽跟头的地方。我的习惯是上电或需要重新配置时先写CMCR0让SFTRES1然后配置所有定时和过滤参数最后再写CMCR0清除SFTRES让模块退出复位状态开始尝试同步总线。这个顺序就是打开配置锁的钥匙。3. 核心细节解析与实操要点理解了整体流程我们深入每个阶段的核心寄存器看看它们具体如何工作以及配置时的“魔鬼细节”。3.1 第一阶段模块控制寄存器CMCR0/1—— 总开关与模式选择模块控制寄存器0CMCR0地址$0500是MSCAN08的“大脑皮层”。SFTRES (Bit 0) - 软复位这是最重要的位。置1时模块进入复位状态中止一切通信但错误计数器保持不变。只有在此状态下才能配置总线定时和过滤器。清除此位后模块会尝试重新同步到总线等待11个连续的隐性位。SYNCH (Bit 4) - 同步状态这是一个只读状态位。当它为1时表示MSCAN08已经成功同步到CAN总线上可以参与通信。在你清除SFTRES后应该轮询或等待中断来确认此位是否置1这是后续发送操作的前提。SLPRQ/SLPAK (Bit 2/3) - 睡眠请求与应答用于低功耗管理。你设置SLPRQ1请求睡眠模块在总线空闲后会进入睡眠并置位SLPAK。总线活动会将其唤醒。注意这是一个握手过程检查SLPAK是确认进入睡眠状态的关键。模块控制寄存器1CMCR1地址$0501则定义了模块的工作模式。LOOPB (Bit 2) - 环回自测试模式调试神器。置1后发送器的输出直接反馈给接收器忽略实际物理引脚。这样无需连接其他CAN节点就能测试你的软件收发流程是否正确。在硬件焊接好后先用环回模式验证基本功能能排除很多软件问题。WUPM (Bit 1) - 唤醒模式选择唤醒条件。0总线任一“显性”边沿即唤醒1只有持续超过twup时间的“显性”电平才能唤醒可有效防止噪声引起的误唤醒。CLKSRC (Bit 0) - 时钟源选择MSCAN08模块的系统时钟来源这直接关系到后续的波特率计算。需要根据你的MCU主时钟生成电路来正确选择。3.2 第二阶段总线定时寄存器CBTR0/1—— 计算通信的“心跳”这是配置中最需要计算的部分直接决定通信的物理层稳定性。CAN总线的一个位时间被划分为4个段同步段SYNC_SEG固定1个时间单位tSCL用于同步时钟边沿。传播时间段Propagation Segment补偿网络物理延迟包含在时间段1TSEG1中。相位缓冲段1Phase Buffer Segment 1即TSEG1的剩余部分可在重同步时延长。相位缓冲段2Phase Buffer Segment 2即TSEG2可在重同步时缩短。CBTR0地址$0502BRP5-BRP0波特率预分频器。tSCL系统时钟周期 2 × (BRP值 1) /fOSC。其中fOSC是MSCAN08的输入时钟频率。BRP值范围1-64用于将高频的系统时钟分频到合适的位时间基准。SJW1-SJW0同步跳转宽度。定义了在一次重同步中一个位时间可以被动态调整的最大tSCL周期数1-4。用于补偿节点间的时钟累积误差。在长距离或高波特率下建议设置大一些如3或4。CBTR1地址$0503SAMP采样模式。1每位采样3次取多数值抗噪性好适用于较低波特率或噪声环境0每位采样1次适用于高波特率。TSEG1[3:0] 和 TSEG2[2:0]定义时间段1和时间段2的长度单位是tSCL。它们的值需要查表手册表23-7获得并非直接写入数值。例如TSEG10b0100表示时间段1长度为5个tSCL因为TSEG1值1才是实际长度。波特率计算公式波特率 fOSC / [ (BRP值) × (1 TSEG1值 TSEG2值) ]举个例子假设fOSC 8MHz目标波特率125kbps。我们选择BRP4则tSCL周期 2*(41)/8MHz 1.25us。每个位时间需要的tSCL周期数 8MHz / (125kbps * 4) 16。所以1 TSEG1 TSEG2 16。我们可以选择TSEG110(实际11个tSCL)TSEG24(实际5个tSCL)采样点位于(1TSEG1)/总时间 ≈ 75%的位置这是一个常用且稳定的配置。实操要点采样点的选择采样点位于TSEG1结束处的设置在工程中至关重要。建议将其设置在位时间的75%-80%左右。过早容易受到信号边沿振铃的影响过晚则留给重同步调整的余地TSEG2太小。使用像Vector的XCAN或Kvaser的CANKing等专业工具配合其总线分析功能可以辅助你优化这个参数。3.3 第三阶段标识符验收过滤器CIDAC/CIDAR/CIDMR—— 设置通信的“门禁”CAN总线消息以标识符ID开头。MSCAN08提供了灵活的硬件过滤机制减轻CPU负担。CIDAC地址$0508IDAM1-IDAM0设置过滤器模式。00单个32位过滤器01两个16位过滤器10四个8位过滤器11过滤器关闭不接受任何消息。通常对于标准帧11位ID两个16位模式最常用可以设置两个独立的ID或一个ID范围。IDHIT1-IDHIT0只读位。指示当前前台接收缓冲区中的消息是匹配了哪个过滤器0-3。这在诊断时非常有用。CIDAR0-3 和 CIDMR0-3这是配置的核心。接受寄存器CIDAR存放你期望的ID模式掩码寄存器CIDMR决定CIDAR中哪些位需要严格匹配。掩码位AMx0表示“必须匹配”。对应位的验收码ACx必须与接收到的消息ID对应位相等。掩码位AMx1表示“不关心”。该位无论接收ID是什么都算匹配。对于标准帧11位ID只使用CIDAR0/1和CIDMR0/1。ID的分布是CIDAR0的Bit7-Bit0对应ID10-ID3CIDAR1的Bit7-Bit5对应ID2-ID0Bit4-Bit0未使用。配置时CIDMR1的低5位通常设为11111不关心。配置示例假设我们只接收标准帧ID为0x123的消息。将0x123转换为11位二进制001 0010 0011。映射到寄存器ID10-ID3 (0010 0011) 0x23 放入CIDAR0。ID2-ID0 (001) 左移到CIDAR1的高三位即CIDAR1 00100000 0x20。设置掩码我们希望所有位都严格匹配所以CIDMR0 0x00 CIDMR1 0xE0高3位为0需匹配低5位为1不关心。设置CIDAC的IDAM为01两个16位过滤器模式。这样只有ID精确等于0x123的消息才会被接收。3.4 第四阶段中断与缓冲区管理—— 建立高效的事件响应机制MSCAN08通过标志位和中断来与CPU交互。接收器标志寄存器CRFLG地址$0504与中断使能寄存器CRIER地址$0505RXF接收缓冲区满标志。这是最常用的标志。当有新消息存入前台接收缓冲区时置1。CPU读取消息后必须向该位写1来清除它以释放缓冲区。WUPIF, RWRNIF, TWRNIF, RERRIF, TERRIF, BOFFIF, OVRIF分别对应唤醒、接收警告、发送警告、接收错误被动、发送错误被动、总线关闭、数据溢出等事件标志。它们通常与CRIER中对应的使能位配合使用。中断使能策略对于常规数据收发使能RXFIE即可。对于需要严格监控总线健康的系统如汽车ECU建议同时使能BOFFIE总线关闭和OVRIE溢出。错误警告中断RWRNIE/TWRNIE可用于早期预警。发送器标志寄存器CTFLG地址$0506与控制寄存器CTCR地址$0507TXE0-TXE2三个发送缓冲区的“空”标志。为1表示缓冲区空闲可写入新消息为0表示缓冲区已装载正在发送或等待发送。启动发送的关键操作是配置好发送缓冲区ID、数据、长度等后向对应的TXE位写0。发送成功后MSCAN08会自动将其置1。ABTRQ/ABTAK发送中止请求与应答。用于在消息发出前取消发送。TXEIE0-TXEIE2发送空中断使能。当发送完成TXE由0变1时触发中断通知CPU可以准备下一帧数据。这在流式发送中很有用。发送缓冲区优先级寄存器TBPR 当多个发送缓冲区都就绪TXE0时MSCAN08内部会进行仲裁。PRIO值越小优先级越高。优先级相同则按缓冲区编号0,1,2决定。在实时性要求高的系统中务必为关键消息配置更高的优先级。避坑指南寄存器访问的原子性与顺序访问时机手册明确警告当TXE0发送缓冲区忙时不要写入该缓冲区的任何寄存器包括TBPR当RXF1接收缓冲区满时不要读取该缓冲区的数据寄存器。否则可能破坏数据完整性。在读写前后务必检查这些状态位。错误计数器读取接收/发送错误计数器CRXERR/CTXERR是动态变化的。手册建议进行两次读取以验证值是否稳定避免读到变化中的中间值。初始化顺序再次强调1) 置位SFTRES2) 配置CBTR0/1, CIDAC, CIDAR, CIDMR3) 配置CRIER, CTCR等中断4) 清除SFTRES5) 等待SYNCH置位。这个顺序不能乱。4. 实操过程从零构建一个CAN节点理论说再多不如动手调一遍。我们假设一个场景用MC68HC908AT32制作一个简单的CAN数据转发节点将接收到的特定ID0x100的标准帧数据原样用另一个ID0x200发送出去。波特率设为125kbps使用8MHz时钟。4.1 硬件与软件环境准备硬件上你需要一块MC68HC908AT32的开发板或自制电路连接一个CAN收发器如TJA1050到CANH和CANL总线。软件上你需要一个针对HC08的C编译器如CodeWarrior的HC08版本或汇编器以及一个编程/调试器。首先在代码中定义寄存器地址方便操作/* MSCAN08 寄存器地址定义 (基于手册地址) */ #define CMCR0 (*(volatile unsigned char *)0x0500) #define CMCR1 (*(volatile unsigned char *)0x0501) #define CBTR0 (*(volatile unsigned char *)0x0502) #define CBTR1 (*(volatile unsigned char *)0x0503) #define CRFLG (*(volatile unsigned char *)0x0504) #define CRIER (*(volatile unsigned char *)0x0505) #define CTFLG (*(volatile unsigned char *)0x0506) #define CTCR (*(volatile unsigned char *)0x0507) #define CIDAC (*(volatile unsigned char *)0x0508) #define CIDAR0 (*(volatile unsigned char *)0x0510) #define CIDAR1 (*(volatile unsigned char *)0x0511) #define CIDMR0 (*(volatile unsigned char *)0x0514) #define CIDMR1 (*(volatile unsigned char *)0x0515) /* 发送缓冲区结构 (假设使用缓冲区0) */ #define TXIDR0 (*(volatile unsigned char *)0x0520) /* 发送ID寄存器0 */ #define TXIDR1 (*(volatile unsigned char *)0x0521) /* 发送ID寄存器1 */ #define TXDLR (*(volatile unsigned char *)0x0525) /* 数据长度码 */ #define TXDSR0 (*(volatile unsigned char *)0x0526) /* 数据段寄存器0 */ /* ... 其他数据寄存器 */ #define TBPR0 (*(volatile unsigned char *)0x053D) /* 发送缓冲区0优先级 */4.2 分步初始化代码实现以下是核心的初始化函数我加了详细注释void MSCAN_Init(void) { /* 第一步进入软复位状态解锁配置寄存器 */ CMCR0 | 0x01; // 设置SFTRES位 /* 第二步配置总线定时 - 125kbps 8MHz */ // 计算BRP4, TSEG110 (11tq), TSEG24 (5tq), SJW3 (4tq), 1次采样 // CBTR0: SJW1,SJW0 1,0 (3); BRP5-BRP0 0,0,0,1,0,0 (4) CBTR0 0x80 | 0x04; // 0x84 // CBTR1: SAMP0; TSEG22-TSEG20 1,0,0 (4); TSEG13-TSEG10 1,0,1,0 (10) CBTR1 0x00 | 0x20 | 0x0A; // 0x2A /* 第三步配置标识符验收过滤器 - 只接受ID0x100的标准帧 */ // 标准帧0x100: 二进制 001 0000 0000 // CIDAR0: ID10-ID3 0000 0000 - 0x00 // CIDAR1: ID2-ID0000, 左移后高三位为000, 低五位无关 - 0x00 CIDAR0 0x00; CIDAR1 0x00; // CIDMR0: 所有位必须匹配 - 0x00 // CIDMR1: 高三位(对应ID2-ID0)必须匹配低五位无关 - 1110 0000 0xE0 CIDMR0 0x00; CIDMR1 0xE0; // 设置过滤器模式为两个16位过滤器 CIDAC 0x10; // IDAM1,IDAM0 0,1 /* 第四步配置中断 */ CRIER 0x01; // 仅使能接收缓冲区满中断(RXFIE) CTCR 0x00; // 禁用所有发送空中断采用查询方式发送 /* 第五步退出软复位开始同步 */ CMCR0 ~0x01; // 清除SFTRES位 /* 第六步可选等待同步完成 */ while((CMCR0 0x10) 0) { // 等待SYNCH位被置1 // 可以加入超时机制 } }4.3 数据收发功能实现初始化完成后我们实现中断服务程序ISR来处理接收以及一个发送函数。/* 接收中断服务例程 (简化框架) */ #pragma interrupt_handler CAN_RX_ISR void CAN_RX_ISR(void) { unsigned char status CRFLG; if(status 0x01) { // 检查RXF标志 // 1. 从接收缓冲区读取数据 (地址例如0x0540开始) unsigned char rx_id_high *(volatile unsigned char*)0x0540; unsigned char rx_id_low *(volatile unsigned char*)0x0541; unsigned char rx_dlc *(volatile unsigned char*)0x0545; unsigned char rx_data[8]; for(int i0; i8; i) { rx_data[i] *(volatile unsigned char*)(0x0546 i); } // 2. 处理数据这里我们准备将其转发ID改为0x200 // 将数据拷贝到发送缓冲区 TXIDR0 0x00; // 0x200的高8位ID (0010 0000 00 - 取ID10-ID3: 0000 0000) TXIDR1 0x40; // 低3位ID2-ID0000左移后为010 00000 0x40 TXDLR rx_dlc 0x0F; // 复制数据长度码 for(int i0; i(rx_dlc 0x0F); i) { *(volatile unsigned char*)(0x0526 i) rx_data[i]; } // 3. 启动发送 (使用发送缓冲区0) CTFLG ~0x01; // 向TXE0位写0启动发送。注意手册要求写0但通常操作是写1清标志这里启动发送是写0。 // 4. 清除接收中断标志 (写1清除) CRFLG 0x01; // 只清除RXF位 } // 其他中断标志处理... } /* 发送函数 (查询方式) */ unsigned char CAN_SendFrame(unsigned int id, unsigned char dlc, unsigned char *data) { // 检查是否有空闲的发送缓冲区 (以缓冲区0为例) if((CTFLG 0x01) 0) { // TXE0为0表示忙 return 0; // 发送失败缓冲区忙 } // 配置发送ID (标准帧) TXIDR0 (unsigned char)(id 3); // ID高8位 TXIDR1 (unsigned char)((id 0x07) 5); // ID低3位左移 // 配置数据长度码 TXDLR dlc 0x0F; // 拷贝数据 for(int i0; i(dlc 0x0F); i) { *(volatile unsigned char*)(0x0526 i) data[i]; } // 设置优先级 (可选) TBPR0 0; // 最高优先级 // 启动发送 CTFLG ~0x01; // 清除TXE0位 (写0)以启动发送 return 1; // 发送成功 }4.4 主程序流程主程序负责初始化和提供应用逻辑。void main(void) { // 初始化系统时钟、GPIO等 SysInit(); // 初始化MSCAN模块 MSCAN_Init(); // 全局中断使能 asm(cli); // 假设使用汇编指令开启中断具体取决于编译器 while(1) { // 主循环可以处理其他任务或进行轮询发送 // 例如定时发送状态帧 // if(timer_expired) { // unsigned char data[2] {0xAA, 0x55}; // CAN_SendFrame(0x300, 2, data); // } // ... // 低功耗模式管理 // if(no_task) { // CMCR0 | 0x04; // 设置SLPRQ请求睡眠 // asm(wait); // 进入等待模式 // } } }5. 常见问题与排查技巧实录即使按照手册配置在实际调试中你还是会遇到各种问题。下面是我踩过的一些坑和解决方法。5.1 通信根本不通无法同步症状SYNCH位永远为0用示波器或CAN分析仪看不到节点发出任何报文。排查步骤检查物理层这是第一步也是最容易出错的一步。测量CANH和CANL之间的差分电压静态时应为2.5V左右。检查终端电阻120欧姆是否在总线两端正确连接。这是最常被忽略的问题。检查时钟配置确认CLKSRC位设置是否正确计算波特率用的fOSC是否是你以为的那个值。用示波器测量MSCAN模块的输入时钟引脚。验证软复位流程确认你是在SFTRES1的状态下配置的CBTR和CIDxR寄存器。一个简单的验证方法是在初始化后读取这些寄存器的值看是否和你写入的一致。检查环回模式将CMCR1的LOOPB位置1然后自己发送一帧数据。如果能在接收端收到说明软件配置和CPU与MSCAN之间的接口是好的问题出在物理层或总线同步上。计算波特率容错CAN总线要求节点间波特率误差小于1%。重新核算你的波特率配置确保TSEG1TSEG2的值在允许范围内通常8-25个tSCL。使用在线CAN波特率计算器辅助验证。5.2 能发送但收不到或能收到但发送错误症状本节点发送后其他节点能收到但本节点收不到回应的ACK或数据或者本节点接收正常但一发送就触发错误中断。排查步骤检查过滤器配置这是接收不到的头号原因。确认你设置的ID、掩码和模式IDAM是否正确。一个调试技巧先将过滤器完全打开。设置CIDMR00xFF, CIDMR10xFF所有位不关心CIDAC设为两个16位过滤器模式。如果此时能收到所有报文说明过滤器配置过严。检查发送缓冲区状态机发送的流程是等待TXE1- 写入ID、DLC、数据 -对TXE位写0。很多新手会错误地去“置位”TXE写1实际上写1是MSCAN模块在发送完成后自动做的写0才是CPU启动发送的命令。仔细检查你的发送代码。检查错误计数器读取CRXERR和CTXERR寄存器。如果发送错误计数器CTXERR快速增加说明发送的报文在总线上产生了错误如格式错误、填充错误可能与其他节点波特率不匹配或物理层有问题。如果达到255模块会进入“总线关闭”状态BOFFIF置位此时必须重新初始化软复位才能恢复。检查ACK在CAN总线中发送节点必须收到至少一个其他节点发出的“显性”ACK位。如果收不到发送节点会报“应答错误”并重发。确保总线上至少有两个正常工作的节点。5.3 中断不触发或频繁误触发症状配置了中断但永远进不去ISR或者莫名其妙频繁进入ISR。排查步骤确认全局中断和模块中断已使能除了设置CRIER或CTCR中的具体中断使能位还要确保CPU的全局中断开关是打开的。对于HC08可能需要操作CCR寄存器。清除中断标志的姿势要对MSCAN的中断标志CRFLG,CTFLG是写1清除。在中断服务程序里你必须读取标志位判断来源然后向对应的位写1来清除它。常见的错误是CRFLG 0xFF;这样会清除所有标志可能掩盖其他未处理的中断条件。更安全的做法是CRFLG (10);只清除处理过的RXF位。防止误唤醒如果使用了睡眠模式且唤醒中断WUPIF频繁误触发可以尝试将WUPM位设为1使能低通滤波并检查总线线路是否有噪声。中断向量表配置确保你的链接器脚本或启动代码正确地将MSCAN的中断服务程序地址填入了对应的中断向量通常是$FFDC和$FFDD需要查具体芯片手册这里仅为示例。5.4 数据溢出与缓冲区管理混乱症状OVRIF溢出中断被置位或者发现收到的数据帧丢失、错乱。排查步骤理解双接收缓冲区机制MSCAN有前台和后台两个接收缓冲区。CPU从前台缓冲区读取数据。当后台缓冲区被新报文填充后只有在前台缓冲区被释放RXF被CPU清除的情况下才会交换到前台。如果CPU处理太慢新报文会覆盖后台缓冲区的旧报文导致丢失并可能置位OVRIF。及时清除RXF在你的接收ISR中读完数据后要立刻清除RXF标志释放缓冲区。这是最高优先级的操作。提升CPU处理速度或使用DMA如果报文速率很高考虑优化ISR代码只做最必要的拷贝将处理逻辑放到主循环。或者如果MCU支持研究是否可以通过DMA将接收缓冲区的数据自动搬运到内存。发送缓冲区优先级如果高优先级消息总是被低优先级消息阻塞检查TBPR寄存器的配置。确保关键消息所在缓冲区的PRIO值更小。调试CAN通信一个CAN总线分析仪如PCAN-USB, Kvaser Leaf是必不可少的。它能让你直观地看到总线上每一帧报文、错误帧、过载帧能准确测量波特率是定位物理层和协议层问题的终极利器。不要试图只用逻辑分析仪看波形来猜那会事倍功半。