ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DSP28335 eCAN从邮箱配置到总线恢复的工程实践

DSP28335 eCAN从邮箱配置到总线恢复的工程实践 简介面向DSP28335开发者的CAN总线通信资料包聚焦TI C28x平台eCAN模块的自发自收Back2Back实现与验证适合嵌入式工程师、自动化领域学习者用于CAN协议调试和入门实践。压缩包共13个文件、大小约137KB包含主程序C文件、CCS工程文件pjt/lkf/gel以及Code Composer Studio生成的调试数据库dbf/cdx/fpt和构建日志log可完整还原eCAN自发自收例程的工程结构。资料从初始化eCAN参数、配置发送邮箱与接收滤波器到通过中断监听FIFO均有对应实例并附已通过测试的工程源码便于直接导入开发环境对照学习。已有313人学习浏览适合希望快速上手DSP28335 CAN通信、理解标准帧/扩展帧配置与总线故障恢复机制的开发者参考。1. 用DSP28335的eCAN之前先搞清楚这个控制器能干什么DSP28335 的 eCAN 控制器很多人一开始都把它当普通 CAN 外设用配置好波特率、打开中断、往邮箱里写数据然后就等着解析出的报文出现在总线上。实际踩过一轮就会承认eCAN 和 STM32 的 bxCAN、SJA1000 这种 BasicCAN 在设计上根本不是一回事——32 个报文邮箱每一个都可以独立设定方向、ID 和局部验收掩码这意味着初始化失败往往不是波特率算错了而是引脚复用、邮箱归属、中断标志哪个环节漏了。本文按照“控制器结构 → 最小初始化 → 收发确认 → 验收滤波与总线恢复”的顺序把使用 DSP28335 的 eCAN 需要锁定的寄存器、参数和排查手段一次说清适合正在移植例程包或者从零写 CAN 驱动的工程师参考。2. eCAN与普通CAN的差异从报文邮箱到发送缓冲区的选型逻辑2.1 eCAN的32个报文邮箱是怎么分布的eCAN 模块在 DSP28335 内部占用的是一段完整的寄存器空间报文邮箱从 MBOX0 到 MBOX31 共 32 个每个邮箱固定 16 字节存放 ID、控制字、数据低 32 位和数据高 32 位。和 BasicCAN 只有 23 个发送缓冲、若干接收缓冲不同eCAN 的每一个邮箱在配置后可以独立工作为发送邮箱或接收邮箱这直接改变了程序结构你不需要在中断里把收到的报文搬来搬去可以让某个邮箱常驻接收某一类 ID来了就置位。但灵活也带来代价。邮箱方向由 CANMD 寄存器统一控制邮箱是否参与收发由 CANME 寄存器决定中断映射由 CANMIL 分配这三个寄存器任何一个和你的预期不一致都会出现“明明往邮箱里写了数据总线上却什么都抓不到”的现象。寄存器全称作用CANMEMailbox Enable对应位置 1邮箱参与收发CANMDMailbox Direction对应位置 1 为接收邮箱置 0 为发送邮箱CANMILMailbox Interrupt Level决定邮箱中断映射到 CAN0INTA 还是 CAN1INTACANMIDMessage ID存放标准帧/扩展帧 ID 及帧格式位MSGCTRLMessage Control数据长度码 DLC、发送优先级 TPLMDL / MDHMailbox Data Low / High8 字节数据场低 32 位和高 32 位所以拿到一个 eCAN 例程包第一步不是看波特率代码而是先确认它用了哪几个邮箱、方向怎么分配。一般我会把低地址邮箱MBOX0~MBOX15留给发送和关键接收高地址邮箱做数据缓存这样排查固件时看邮箱号就能猜到用途。2.2 邮箱方向与ID设定先失能再改参数配置任何一个邮箱顺序必须是“先失能邮箱再改配置最后重新使能”。如果 CANME 对应位是 1 的时候直接改 MSGID 或 MSGCTRL在总线繁忙时可能触发不可预期的发送或接收行为。下面的代码演示把 MBOX0 配成标准帧发送邮箱// 失能邮箱0保证后续配置不会被总线事件打断 ECanaRegs.CANME.all ~0x00000001; // 标准帧 ID 0x123IDE 位为 0 // 位0~位10 是标准帧 ID位31 是 IDE 位 ECanaMboxes.MBOX0.MSGID.all 0x00000123; // DLC1 字节RTR0发送数据帧 ECanaMboxes.MBOX0.MSGCTRL.all 0x00000008; // CANMD 对应位写 0MBOX0 作为发送邮箱 ECanaRegs.CANMD.all ~0x00000001; // 重新使能邮箱0 ECanaRegs.CANME.all | 0x00000001;这段代码里最关键的是 CANME 的“先清后置”。很多人在初始化时直接对 CANME 写整片寄存器值把已经配置好的邮箱方向全部打乱正确做法是用“读-改-写”的方式只操作目标位。MSGID 的低 11 位是标准帧 ID这个布局决定了后续做验收滤波时掩码也要对齐到同样的位段上不是随手写个 32 位掩码就能用的。2.3 自测模式验证邮箱配置是否正确配置完邮箱先不要接外部设备用 eCAN 的自测模式STM做内部回环。自测模式下发送邮箱发出的报文不会出现在 CANRX 引脚上而是直接绕回接收邮箱适合在板子还没有 CAN 收发器或总线上没有其他节点时验证邮箱逻辑。ECanaRegs.CANMC.bit.STM 1; // 进入自测模式 // 向 MBOX0 写入数据后请求发送 ECanaRegs.CANTRS.all 0x00000001; // 稍后检查 MBOX1 的接收挂起位 while ((ECanaRegs.CANRMP.all 0x00000002) 0) { // 等待 MBOX1 收到来自 MBOX0 的报文 }如果这一步能收到说明邮箱方向、ID、DLC 配置链路是通的问题大概率在外部物理层如果收不到先查 CANMD 方向位或 CANME 使能位不要急着怀疑波特率。3. 拿到ecan例程包之后最小工程搭建与初始化代码3.1 引脚复用GPIO30和GPIO31切换成CANTXA与CANRXADSP28335 的 eCAN 功能默认不映射到任何引脚GPIO30 和 GPIO31 上电后是普通 GPIO。很多初始化失败的案例CAN 寄存器配置全对最终发现是引脚还在 GPIO 模式信号根本没有到达 CAN 收发器。这个坑在例程包里最常出现在“只拷贝了 CAN 驱动 .c 文件没有执行引脚复用初始化”的移植过程中。// 将 GPIO30 复用为 CANTXAGPIO31 复用为 CANRXA GpioCtrlRegs.GPAMUX2.bit.GPIO30 1; GpioCtrlRegs.GPAMUX2.bit.GPIO31 1; // 发送引脚配置为输出接收引脚配置为输入 GpioCtrlRegs.GPADIR.bit.GPIO30 1; GpioCtrlRegs.GPADIR.bit.GPIO31 0;GPAMUX2 是 GPIOA 组的第二个复用选择寄存器GPIO30 和 GPIO31 分别占据其中两个 2 位字段写 1 表示选择第一复用功能即 CANTXA 和 CANRXA。GPADIR 的方向设置在这之后执行因为复用功能已经接管引脚方向位本质上决定的是收发器输入输出链路的方向。注意这里的两行方向配置不是可选项缺了接收方向CANRXA 读不到总线上的显性电平。3.2 波特率计算BRP、TSEG1、TSEG2与采样点eCAN 的波特率由 CANBTC 寄存器三个字段共同决定。位时间由三部分组成固定 1 TQ 的同步段、TSEG1传播段加相位缓冲段1、TSEG2相位缓冲段2。总位时间 1 TSEG1 TSEG2采样点百分比 (1 TSEG1) / (1 TSEG1 TSEG2)。BRP 是波特率预分频TI 手册习惯上按“实际分频值 BRP 写入值 1”来理解写 14 相当于 15 分频。500 kbps 是工业 CAN 最常用的速率之一以下参数以 SYSCLKOUT150 MHz 推算位时间取 15 TQ分频取 20得到 150 MHz / (20 × 15) 500 kHz。寄存器写值 BRP19TSEG112TSEG22采样点落在 (112)/15 ≈ 86.7%这个采样点位置对常用双绞线拓扑是合适的。目标波特率BRP 写入值TSEG1TSEG2SJW采样点1 Mbps9122186.7%500 kbps19122186.7%250 kbps39122186.7%SJW 同步跳转宽度这里取 1意味着一帧中最多调整 1 TQ 来补偿节点间时钟偏差。如果总线长度超过 20 米或者线上有多个节点SJW 可以放大到 2但不要超过 TSEG2否则采样点位置会被破坏。3.3 初始化时序从CCR置位到CANES确认eCAN 初始化必须走一遍“请求配置模式 → 配置寄存器 → 退出配置模式”的时序中间不能跳过等待。CANMC 的 CCR 位是配置模式请求CANES 的 CCE 位是配置模式确认两者之间有一个同步过程如果写完 CCR 立即去写 CANBTC寄存器可能被硬件忽略。void ECan_Init(void) { // 引脚复用必须先于eCAN寄存器配置 GpioCtrlRegs.GPAMUX2.bit.GPIO30 1; GpioCtrlRegs.GPAMUX2.bit.GPIO31 1; GpioCtrlRegs.GPADIR.bit.GPIO30 1; GpioCtrlRegs.GPADIR.bit.GPIO31 0; // 1. 请求进入配置模式 ECanaRegs.CANMC.bit.CCR 1; // 2. 等待CCE确认未确认前不要碰配置寄存器 while (ECanaRegs.CANES.bit.CCE 0) { } // 3. 写波特率寄存器 ECanaRegs.CANBTC.all 0; ECanaRegs.CANBTC.bit.BRP 19; // 实际分频20 ECanaRegs.CANBTC.bit.TSEG1 12; // 传播段相位缓冲1 ECanaRegs.CANBTC.bit.TSEG2 2; // 相位缓冲2 ECanaRegs.CANBTC.bit.SJW 1; // 4. 退出配置模式 ECanaRegs.CANMC.bit.CCR 0; while (ECanaRegs.CANES.bit.CCE 1) { } // 5. 使能邮箱0和邮箱1 ECanaRegs.CANME.all 0x00000003; }CCE 位在 CANES 的 bit0它由硬件在完成时钟同步后自动置 1因此初始化代码里必须用 while 轮询等待而不是延时。延时在这种同步场景下不可靠因为时钟状态切换时间与总线波特率、晶振频率都有关系。邮箱使能放在退出配置模式之后是因为 CANME 属于邮箱配置寄存器某些版本的 eCAN 模块在配置模式下不允许直接操作邮箱相关寄存器。4. 数据收发与中断验证CAN报文ID和数据场的四个排查点4.1 发送路径CANTRS置位后必须等待CANTA发送一个报文到邮箱后要把 CANTRS发送请求寄存器对应位置 1硬件才会把邮箱内容送到总线。发送完成与否看 CANTA发送确认寄存器对应位这一位由硬件置 1软件必须在下一帧发送前手动清零。如果上一帧的 CANTA 没有清新帧的发送确认会被旧状态污染轮询发送逻辑容易出现“第一帧正常、第二帧卡死”的现象。// 写数据和ID ECanaMboxes.MBOX0.MSGID.all 0x00000123; ECanaMboxes.MBOX0.MSGCTRL.all 0x00000008; ECanaMboxes.MBOX0.MDL.all 0x11 0; // data[0]0x11对应字节序DBO1 // 请求发送 ECanaRegs.CANTRS.all 0x00000001; // 等待发送完成标志 while ((ECanaRegs.CANTA.all 0x00000001) 0) { } // 清除发送确认位准备下一次发送 ECanaRegs.CANTA.all 0x00000001;如果发送一直不完成检查 CANTRR发送请求取消寄存器它可以在邮箱正在等待仲裁时取消发送。常见做法是CANTRS 置位后轮询 CANTA超时未确认就置位 CANTRR 取消并读取 CANES 的错误标志而不是死等。另外 MDL 的数据字节顺序由 CANMC 的 DBO 位控制DBO1 时 MDL 最低字节是 data[0]解析代码要和发送保持一致。4.2 接收路径先读数据场再清CANRMP接收邮箱收到报文后CANRMP 对应位置 1同时产生中断或供轮询查询。读取报文时注意两点第一数据场必须先读后清 CANRMP第二清 CANRMP 不能写整片 32 位值否则会把同一时刻其他邮箱的挂起位一起清掉。// 轮询MBOX1的接收挂起位 if ((ECanaRegs.CANRMP.all 0x00000002) ! 0) { Uint32 rxLow ECanaMboxes.MBOX1.MDL.all; // 先读数据 // 解析ID标准帧ID在bit0~bit10 Uint32 rxId ECanaMboxes.MBOX1.MSGID.all 0x7FF; // 最后清接收挂起位 ECanaRegs.CANRMP.all 0x00000002; }如果一个接收邮箱的报文来不及读硬件会把新报文覆盖进去同时置位 CANRML 指示报文丢失。CANRML 是丢失状态的锁存位清 CANRMP 不会自动清 CANRML必须单独写 1 清除。排查丢帧时先看 CANRML 是否频繁置位如果是说明中断响应时间超过了总线报文间隔需要把数据处理逻辑挪出中断或在中断里只搬数据不解析。4.3 报文抓不到时先查CANES状态位还是先查物理层抓不到报文时顺序很重要。常见错误是一上来就拿示波器量 CANH/CANL其实更高效的是先读 CANES 和 CANEC 两个寄存器它们能直接告诉你控制器的状态机和错误计数是否已经进入离线状态。寄存器位/字段含义CANES.BO离线状态置 1 表示控制器已退出总线不再参与通信CANES.EW错误警告错误计数达到 96接近被动错误CANES.EP错误被动错误计数达到 128只能被动监听CANEC 低 16 位接收错误计数每次接收错误加 8成功接收减 1CANEC 高 16 位发送错误计数每次发送错误加 8成功发送减 1如果 BO 置位说明控制器已经主动闭嘴这时量波形没有意义。先用软件把错误计数读出来再配合示波器量总线空闲时的隐性电平CANH 和 CANL 都约为 2.5 V以及发送时的差分显性电平。如果 CANH/CANL 始终是 0 V问题在收发器电源或引脚复用如果显性和隐性跳变正常但控制器报错问题在波特率或终端电阻。终端电阻用万用表量 CANH 与 CANL 之间两点间应该接近 60 欧两个 120 欧终端并联。5. CANopen与多机通信场景下的eCAN最佳实践验收滤波与bus-off恢复5.1 用局部验收掩码LAM实现ID级过滤多机通信时如果让所有报文都进中断CPU 会被无关帧打满。eCAN 的每个邮箱对应一个局部验收掩码寄存器 LAM0~LAM31掩码位写 1 表示该位不参与匹配写 0 表示严格匹配。标准帧 ID 的掩码对齐到 MSGID 的 bit0~bit10不是从 bit0 开始顺手写一个 0xFFFF 就能生效的。// 使能邮箱2作为接收邮箱方向置1 ECanaRegs.CANME.all ~0x00000004; ECanaRegs.CANMD.all | 0x00000004; // 期望ID 0x100但bit8~bit10可以任意即匹配0x100~0x1FF ECanaMboxes.MBOX2.MSGID.all 0x00000100; // 掩码bit8~bit10写1忽略其他位严格匹配 ECanaLAMRegs.LAM2.all 0x00000700; ECanaRegs.CANME.all | 0x00000004;这个配置的实际效果是一个滤波器挡住 0x100~0x1FF 共 256 个 ID而不是只收 0x100 一个。CAN 报文里的 ID 本身没有优先级以外的业务含义如何分段完全由应用层协议决定所以滤波规划要跟着协议走不要让掩码跨段匹配。扩展帧的掩码布局不同扩展 ID 占 bit0~bit28掩码也要按 29 位布局写和标准帧混用时建议邮箱分类使用。5.2 bus-off恢复ABO自动恢复与手动重新初始化的取舍总线离线恢复是 CAN 通信里最容易写错的环节。CANMC 的 ABO 位为 1 时控制器检测到 128 次总线空闲后自动恢复ABO 为 0 时必须软件干预。自动恢复省事但在电磁干扰较强的工况下节点会在故障消失后立刻回到总线如果应用层没有准备好会连续冲击正在恢复中的网络。手动恢复更稳妥的做法是检测到 BO 位置 1 后先记录错误原因再重新执行一遍配置模式切换让控制器从头完成同步。这样恢复时间可控故障信息也不会丢失。if (ECanaRegs.CANES.bit.BO 1) { // 进入配置模式重新同步时序 ECanaRegs.CANMC.bit.CCR 1; while (ECanaRegs.CANES.bit.CCE 0) { } // 清错误计数退出配置模式 ECanaRegs.CANMC.bit.CCR 0; while (ECanaRegs.CANES.bit.CCE 1) { } // 复位现场标志 ECanaRegs.CANTA.all 0xFFFFFFFF; ECanaRegs.CANRMP.all 0xFFFFFFFF; }总线恢复后发送错误计数不是立即归零而是在后续成功发送过程中逐步递减。因此恢复后第一帧不要发关键数据先发一个空数据帧试探总线状态等控制器状态回到错误主动再切正式业务。5.3 用回环模式验证采样点并估算总线负载率自测模式除了验证邮箱配置还能用来验证采样点设置是否合理。把 STM 置 1两个节点之间的外部信号路径被绕过控制器用自己的时钟发送和接收。如果此时 CANEC 的错误计数稳定不增长说明位时序在内部一致性上是成立的接上外部总线后如果开始报错问题就缩小到了收发器延时和线缆传播延时这时需要微调 TSEG1 而不是整个波特率。总线负载率是评估网络裕量的直接指标估算公式为负载率 每秒发送位数 / 波特率。一帧标准 CAN 数据帧最坏约 111 位含位填充和帧间隔8 字节数据、10 ms 周期时每秒 100 帧产生约 11100 位在 500 kbps 总线上负载率约 2.2%。负载率超过 30% 时建议缩短报文周期或拆分 ID不要等到错误计数上升才回头检查时序。验证负载率时用 eCAN 的 CANTA 完成次数做统计基准在固定时间窗口内累计发送帧数再按上述公式计算比直接看总线空闲时间更准确。 p a hrefhttps://download.csdn.net/download/weixin_42659791/86681438 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
返回列表