新闻详情

新闻详情

首页 / 资讯中心 / 详情

TMS320F28035 eCAN主从通信调试:回环模式为何不能替代总线互测

发布时间:2026/9/8 3:52:40来源:尧图网络
TMS320F28035 eCAN主从通信调试:回环模式为何不能替代总线互测
简介面向TMS320F28035嵌入式开发者这是一份基于CCS5环境的eCAN主机/从机通信测试完整工程。代码采用C语言与汇编混合编写覆盖芯片初始化、时钟配置60MHz及eCAN 1MHz波特率设定可通过宏定义灵活切换主机或从机模式适合需要快速验证CAN通信或学习28035的工程师与学生。压缩包内共146个文件约308KB包含头文件、C源码、汇编启动文件、CMD链接命令文件及CCS工程配置等目录结构完整源文件不依赖外部引用导入CCS5即可编译使用。其中CMD文件支持直接修改后烧写至片内Flash与CCS3的烧写方式有所不同。资源由TI controlSUITE部分代码改编仅供学习交流。目前已有1134人学习对eCAN协议调试和CCS5工程迁移具有参考价值。 做 TMS320F28035 eCAN 主机从机通信测试的时候我几乎把回环测试当成了万能自检单板发送数据帧回环模式下收得好好的结果一旦切到标准模式、两块板一互联主节点就报发送失败从节点那边根本等不到任何报文。这个现象在 CAN 调试里非常典型几乎每个刚接触 eCAN 的人都会撞上。实际上 eCAN 的正常模式依赖总线应答机制而回环模式完全绕开了这条链路所以回环通不等价于总线通。本文把我从硬件接线、eCAN 初始化、邮箱配置到主从收发链路调通的全过程记录一遍重点讲透回环测试为什么不能替代总线互测以及标准模式下发送失败该怎么一步步排查适合正在调 TMS320F28035 CAN 通信的工程师参考。1. 项目背景eCAN 主从测试到底在测什么1.1 两块 28035 完成主从收发这个项目要什么很多项目用 DSP 做电机控制或数据采集主控板需要把运行状态发给从板或者接收从板的传感器数据。TMS320F28035 内部集成的是增强型 CAN 控制器也就是 eCAN兼容 CAN 2.0B 协议支持标准帧和扩展帧还有 32 个邮箱。和 UART 这种一对一、只能自发自收对比CAN 最大的特点是多主、广播、带应答每个节点都能发也都能收但一个帧发出去之后总线上至少得有一个节点完成应答否则发送节点会进入错误状态这个机制是理解本次问题的关键。主从通信的模式其实不复杂主机给从机发命令帧从机解析命令后再回一帧状态数据。这里涉及两个实际问题一是邮箱方向怎么分配二是两个节点之间 ID 怎么规划才不会收错。我做的测试板把主机邮箱 0 配成发送、邮箱 1 配成接收从机反过来邮箱 0 发应答、邮箱 1 收命令用最原始的方式先验证通路。1.2 从回环到互联的调试路径我最初用的是 TI 例程里的 loopback 模式也就是把发送邮箱的数据直接在内部转给接收邮箱不经过引脚也不上总线。当时的测试结果很顺利发送邮箱置位请求之后接收邮箱立刻挂起数据完全一致于是我以为代码没问题直接把模式切到 normal结果发送请求一直得不到应答错误寄存器里发送错误计数持续上涨。后来我又做了一组对比测试把主机和从机分别单独接在 CAN 分析仪上各自发送两边都能发出去但一旦把主机和从机直接相连主机发帧从机就收不到。这种“单测全通、互联不通”的场景和很多 485 Modbus 工程里主机、从机分别测试都正常接在一起反而异常的情况很像排查思路也相通先验证物理链路再查配置一致性最后看协议层的解析逻辑。2. 硬件链路设计为什么回环正常接上总线就不行2.1 28035 eCAN 的物理层与收发器选择很多人容易忽略一个事实DSP 的 CAN 控制器引脚出来的只是 TX 和 RX 数字信号必须外接 CAN 收发器芯片才能形成 CANH 和 CANL 差分总线。收发器负责把控制器发来的逻辑电平转换成差分信号同时把总线上的差分信号还原成逻辑电平给控制器接收。我用的是 SN65HVD2303.3V 供电和 28035 的 IO 电平刚好匹配也有不少人选 TJA1050但 TJA1050 是 5V 供电需要额外处理电平匹配问题新手建议直接用 3.3V 的 HVD230 或 ISO1050 这类隔离型收发器。回环模式根本不需要物理层参与控制器内部的发送路径直接接到接收路径等于自己做了一个“假的总线”所以收发器有没有焊、引脚有没有接对、终端电阻有没有上回环测试通通看不出来。这也是为什么回环测试过了正常模式却始终发不出去的第一嫌疑就是硬件链路本身。2.2 终端电阻和共地区别从一开始就存在高速 CAN 总线规范要求在总线两端各接一个 120 欧姆终端电阻两个电阻并联后的等效阻抗约 60 欧姆。没有终端电阻或者只在一端接电阻高速信号在总线末端反射接收节点的采样点就会偏移短距离、低速的时候可能侥幸能通但一旦距离超过几十厘米、波特率上到 500k数据就会开始偶发错误。我测试时踩的坑就在这里主机板上有 120 欧姆终端电阻从机板没有主机和从机之间的线长大概 40 厘米用 500k 波特率跑。主机的发送错误计数器一路涨到 96从机却完全没有收到任何帧。后来把从机端也接上 120 欧姆电阻两边共地问题立刻消失。两块板卡各自有独立电源供电时还必须把两个板卡的 GND 连在一起确保它们有相同的参考地。CAN 是差分信号不假但收发器内部的接收比较器仍然需要共模范围如果地电位差异太大共模电压超出收发器允许范围同样会收不到任何数据。很多“单测正常、互联异常”的问题根源就是地没有共。3. 代码初始化eCAN 配置不是抄一遍就行3.1 引脚复用与时钟使能TMS320F28035 的 CANRX 和 CANTX 分别复用 GPIO18 和 GPIO19上电复位后默认是 GPIO 功能必须先配置成 eCAN 外设引脚同时打开 eCAN 外设时钟否则后续所有寄存器操作都不会生效。我在代码里先做了这两步很多人只配了邮箱忘了引脚复用测了一下午都没反应。void InitECan(void) { EALLOW; // 使能 eCAN 外设时钟 SysCtrlRegs.PCLKCR0.bit.ECANAENCLK 1; // GPIO18 配置为 CANRXGPIO19 配置为 CANTX GpioCtrlRegs.GPAMUX1.bit.GPIO18 1; GpioCtrlRegs.GPAMUX1.bit.GPIO19 1; EDIS; }引脚复用看起来简单但有一个细节容易踩28035 的引脚复用寄存器 GPAMUX1 的控制位是两位一组GPIO18 对应 bit 5-4GPIO19 对应 bit 7-6。置为 01 是外设功能 1也就是 eCAN 功能置为 10 可能是别的外设功能。如果只是把寄存器整体赋值很容易把其他 GPIO 的复用关系一起改掉所以推荐使用位域方式修改只操作当前需要改的位。3.2 500kbps 波特率是怎么算出来的波特率配置是 eCAN 初始化里最容易出错也最隐蔽的一环。28035 的 eCAN 模块时钟来自系统时钟 SYSCLKOUT主频 60MHz 时 CAN 外设时钟就是 60MHz。CAN 位时间由三部分组成同步段、传播时间段 1、相位缓冲段 2换算到寄存器上就是 BRP、TSEG1、TSEG2 三个值。位时间的计算公式是位时间 (BRP 1) × (1 TSEG1 1 TSEG2 1) 个 CAN 时钟周期。其中 TSEG1 和 TSEG2 寄存器里存的值会各自加 1才是真实的时间量子数。这个细节很多人都会忽略拿着例程里的数字直接抄结果波特率差一截。我想得到 500kbps在 60MHz 时钟下的位时间应该是 60MHz / 500k 120 个时钟周期。把 BRP 设为 5也就是预分频 6那么后面三段总共需要 120 / 6 20 个时间量子。让同步段占 1TSEG1 设成 14、寄存器加 1 得到 15TSEG2 设成 3、寄存器加 1 得到 4三段加起来 1 15 4 20正好满足要求。// 配置位时序500kbpsSYSCLKOUT 60MHz ECanRegs.CANBTC.bit.BRP 5; // 预分频 6 ECanRegs.CANBTC.bit.TSEG1 14; // 15 个时间量子 ECanRegs.CANBTC.bit.TSEG2 3; // 4 个时间量子 ECanRegs.CANBTC.bit.SJW 2; // 同步跳转宽度波特率不一致是主从互联失败的高频原因。如果两块板子系统时钟不同或者一块用的是内部晶振、一块用的外部晶振实际频率有偏差两边即使配了同样的数值位时间也会不同。一个排查技巧是用小范围的 BRP 组合固定位时间但让采样点落在位时间的 70% 到 80% 附近容错性会更好。我的配置采样点约在 80%实测稳定。3.3 邮箱分配和 ID 过滤主从节点差异邮箱是 eCAN 的核心资源28035 有 32 个邮箱每个邮箱可以独立配置为发送或者接收。工程上有个原则发送邮箱和接收邮箱分开避免同一邮箱既要发又要收造成的状态混乱。我的主节点邮箱 0 是发送邮箱 1 是接收从节点相反邮箱 0 发应答、邮箱 1 收命令。邮箱方向由 CANMD 寄存器控制位为 1 表示发送邮箱位为 0 表示接收邮箱。使能邮箱由 CANME 寄存器控制修改邮箱配置前最好先把对应位清零配置完再置位否则在有些硅片版本上会出现配置不生效的情况。void CAN_InitMailbox(unsigned int tx_id, unsigned int rx_id) { EALLOW; // 先使能 mailbox0 和 mailbox1 ECanRegs.CANME.all 0x03; // 邮箱0发送邮箱1接收 ECanRegs.CANMD.all 0x01; // 邮箱0发送邮箱 ECanMbox.MBOX0.MSGID.bit.STDID tx_id; ECanMbox.MBOX0.MSGID.bit.IDE 0; // 标准帧 ECanMbox.MBOX0.MSGCTRL.bit.DLC 8; // 8 字节数据 // 邮箱1接收邮箱 ECanMbox.MBOX1.MSGID.bit.STDID rx_id; ECanMbox.MBOX1.MSGID.bit.IDE 0; ECanMbox.MBOX1.MSGCTRL.bit.DLC 8; EDIS; }ID 过滤是另一个坑。接收邮箱会把自己配置的 STDID 和帧的 ID 做匹配只有在 ID 一致时才接收。初次调通时我建议把邮箱掩码全放开也就是接收所有 ID等通信链路确认没问题之后再收紧过滤规则这样能少一层变量。如果一开始就想严格控制必须保证发送帧的 ID 和接收邮箱的 STDID 完全一致包括 IDE 位是标准帧还是扩展帧否则数据会被悄悄丢掉而且不产生任何错误标志。4. 主从通信流程的完整实现4.1 主节点发送数据帧主节点发送一个数据帧逻辑上就是把要发送的 ID 和数据长度写入对应邮箱再把数据写入邮箱的数据字段最后置位 CANTRS 寄存器请求发送。发送是否成功要看 CANTA 寄存器是否有应答位这个应答位表示控制器已经成功把帧送上总线并且总线上有节点完成了 ACK。void CAN_SendFrame(unsigned int std_id, unsigned long data_l, unsigned long data_h) { // 清发送请求防止上一次未完成的干扰 ECanRegs.CANTRS.bit.TRS0 0; // 写入 ID 和数据 ECanMbox.MBOX0.MSGID.bit.STDID std_id; ECanMbox.MBOX0.MSGID.bit.IDE 0; ECanMbox.MBOX0.MDL.all data_l; ECanMbox.MBOX0.MDH.all data_h; // 请求发送 ECanRegs.CANTRS.bit.TRS0 1; // 等待发送应答 while (ECanRegs.CANTA.bit.TA0 0) { // 超时保护工程中必须有 } // 清除应答标志 ECanRegs.CANTA.bit.TA0 1; }这段代码里有一个必须强调的点等待 CANTA 置位时绝对不能死等。我在测试时就是死等结果发送失败时程序直接卡死在 while 循环里连错误寄存器都看不到。正确的做法是加一个超时计数器比如循环 10000 次还没等到应答就退出然后去读 CANES 错误寄存器。CANTA 一旦置位就必须软件清零不然下一次发送会直接跳过等待造成时序混乱。4.2 从节点接收与应答从节点接收数据时直接轮询 CANRMP 寄存器对应接收邮箱的挂起位置 1代表收到了新帧。此时读邮箱数据读完后将挂起位写 1 清除相当于告诉控制器“我已经处理完了可以接收下一帧”。void CAN_CheckAndReply(unsigned int tx_id) { if (ECanRegs.CANRMP.bit.RMP1 1) { unsigned long rx_l ECanMbox.MBOX1.MDL.all; unsigned long rx_h ECanMbox.MBOX1.MDH.all; // 在这里做命令解析再发送应答帧 CAN_SendFrame(tx_id, rx_l, rx_h); // 清除接收挂起 ECanRegs.CANRMP.bit.RMP1 1; } }如果只是做最基本的收发测试接收邮箱只需要读数据、清标志。但在主从机互答的场景里从机收到命令后还要回一帧应答这时要注意从机自身的发送邮箱 ID 必须和主机的接收邮箱 ID 一致。很多人的问题就出现在这里主节点以为自己在等 ID 0x101从节点应答的帧 ID 却是 0x102两边都对“ID 规划”各执一词结果主节点明明收到帧了却因为邮箱过滤不匹配直接丢弃。所以主从通信协议里ID 表应该作为协议文档的一部分提前定好。比如 0x100 是主机下发命令0x101 是从机返回状态0x102 是广播帧。所有节点必须使用同一张 ID 表不能只在自己的代码里随便填。5. 问题排查实录标准模式发不出去的常见原因5.1 从错误寄存器看问题遇到标准模式发送失败第一步不是改代码而是读错误状态寄存器 CANES。CANES 的低 16 位包含错误状态标志高 16 位分别是接收错误计数 REC 和发送错误计数 TEC。发送计数持续增加说明控制器一直在尝试发送但总线上没有节点应答或者总线本身没有形成有效的电平。void CAN_PrintErrorStatus(void) { unsigned short rec ECanRegs.CANES.bit.REC; unsigned short tec ECanRegs.CANES.bit.TEC; // 工程中可以通过串口或调试器查看这两个值 }错误计数超过 127 以后控制器会进入 Bus-off 状态主动断开总线这时候不管怎么发都不会有反应。恢复方式是写 CANMC 的 ABO 位也就是自动总线恢复或者重新初始化 CAN 模块。我完成主机、从机互联测试之后发现主机 TEC 停在 96 左右不涨就是典型的“发送了但没人应答”状态而不是真正的硬件短路。5.2 常见问题速查表现象可能原因排查方法回环正常标准模式发不出去总线上没有第二个节点应答或收发器链路不正常用 CAN 分析仪挂总线观察能否收到帧两板互联后都不通终端电阻缺失或只在一端接两端各接 120 欧姆电阻测总线静态电压时通时不通两个节点波特率不一致统一时钟源检查位时序配置用示波器比较位宽发送成功但对方收不到接收邮箱 ID 过滤不匹配先放开掩码确认帧 ID 和邮箱 STDID 一致刚开始正常跑一会就通不了错误计数积累进入 Bus-off读 CANES 确认错误状态检查总线物理层两块板独立接分析仪都正常互联就不行地电位不一致或者收发器方向控制问题必须共地检查 STB/RS 引脚状态当初让我卡了很久的还有 STB 引脚。SN65HVD230 的 STB 是待机控制引脚拉低进入正常工作模式拉高进入待机模式待机模式下收发器不驱动总线总线电平全靠终端电阻微弱上拉接上去谁都发不了。我用 3.3V 电平的 HVD230 时把 STB 直接接地就解决了但换成 TJA1050 这类芯片时对应的控制引脚逻辑可能相反一定要看具体芯片手册。5.3 排查工具与实测数据做 CAN 通信测试示波器和 CAN 分析仪建议至少准备一个。我最初只靠万用表测 CANH 和 CANL 的直流电压判定不了帧格式有没有问题。后来接上 CAN 分析仪把波特率设成 500k发现主机确实在周期性地往总线上发数据但每个帧都带错误帧标志。这说明问题不在控制器配置而在物理层的反射因为一个终端电阻缺失隐性电平不稳定接收节点在帧尾 ACK 位附近采样失败导致发送节点重发、错误帧频发。遇到这种情况调整顺序很重要先把物理层修好再谈代码。我当时已经改了三天代码最后只是补齐一个 120 欧姆电阻就全通了。这次经历让我养成了一个习惯凡是 CAN 互联测试第一步永远先量一下 CANH 对地、CANL 对地电压正常情况下应该是 2.5V 左右再量 CANH 和 CANL 之间的阻值总线正常时两端电阻并联后应该在 60 欧姆左右。写在最后的调试体会28035 的 eCAN 本身并不复杂复杂的往往是“回环通、标准模式不通”这种问题背后混合的物理层和协议层因素。我现在做 CAN 通信起步测试一律先走一遍固定流程确认两块板共地确认总线两端终端电阻确认收发器非待机状态然后把邮箱过滤全放开用 CAN 分析仪验证总线上的帧和 ID最后再逐步收紧过滤规则、加入错误处理。顺序对了问题通常半小时内就能定位。如果你也在调 TMS320F28035 的主从通信建议第一次先砍掉所有“智能优化”只用两个邮箱一个发一个收波特率直接用 500kID 固定两个值跑通后再往上加功能。CAN 通信的结构化排查方法可以复用到很多通信协议上这套思路本身比一两个例程更值得沉淀。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

面向AI辅助软件开发的架构设计:从模型接入到Agent编排的工程实践 2026/9/8 5:22:57

面向AI辅助软件开发的架构设计:从模型接入到Agent编排的工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
WorkBuddy 实测:10 套 MCP 服务横向测评与 Skill 边界全解析 2026/9/8 5:22:57

WorkBuddy 实测:10 套 MCP 服务横向测评与 Skill 边界全解析

如果你最近在折腾 WorkBuddy,多半绕不开两个词:Skill 和 MCP。我见过很多人把 Skill 当成 MCP 的替代品,也有人把 MCP server 当成“装了就完事”的插件,结果配了十个连接器,实际能稳定用上的没几个。这篇文章不会讲花…

阅读更多 →
Rust智能指针深度解析:从Box到Arc掌握内存安全与所有权 2026/9/8 5:22:57

Rust智能指针深度解析:从Box到Arc掌握内存安全与所有权

1. 为什么每个 Rust 开发者都得过智能指针这一关Rust 的所有权系统、借用检查、生命周期这“三座大山”,几乎每个入门的人都在上面栽过跟头。但等你真正开始写项目,比如用 esp32 做嵌入式开发、写 async 运行时、或者在线给进程打补丁这类底层工具时&…

阅读更多 →
深入理解Requests源码:从Session到HTTPAdapter的接口测试底层封装 2026/9/8 5:22:57

深入理解Requests源码:从Session到HTTPAdapter的接口测试底层封装

很多同学用 Python 的 Requests 库写接口测试,基本停留在“会调requests.get()”“会带headers”“会解析.json()”的层面。一旦遇到复杂的鉴权、代理切换、连接池复用、重试策略、流式响应,或者需要在一个自动化测试平台里把请求底层统一接管时&#xf…

阅读更多 →
Qt MVP架构实战:异步事件驱动与三层解耦完整指南 2026/9/8 5:22:57

Qt MVP架构实战:异步事件驱动与三层解耦完整指南

Qt 架构设计实战:MVP三层解耦与异步事件驱动完整落地指南最近在做一个桌面设备监测工具,界面需要实时刷新曲线、处理串口数据、响应按钮操作,还要在后台跑耗时的数据解析任务。项目早期为了赶进度,直接在 QWidget 里塞逻辑&#x…

阅读更多 →
骚扰电话识别与处置:特征计算、规则引擎到模型评分的落地链路 2026/9/8 5:19:57

骚扰电话识别与处置:特征计算、规则引擎到模型评分的落地链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞