ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

TMS32F28P550调试踩坑实录:从Boot引脚到ADC/PWM的全流程排障

TMS32F28P550调试踩坑实录:从Boot引脚到ADC/PWM的全流程排障 这块板子刚焊好那天我其实有点轻敌。TMS32F28P550嘛C2000系列的老套路以前玩28379D也没少折腾心想下载个demo点个灯还不是洒洒水。结果程序烧进去板子一点动静都没有串口调试助手打开数据区干干净净。折腾到晚上十一点最后发现是Boot引脚上两个电阻贴反了。这种问题你在任何教程里都看不到但它就是实实在在能卡你一整晚。所以这篇东西我决定把调这块板子踩过的坑、排过的查、翻过的数据手册页面全部实录下来。不是给你抄一遍例程而是把“为什么会这样”“我当时是怎么一步步查出来的”写清楚。如果你也在做TMS32F28P550或者C2000系列其他型号的调试这篇应该能帮你省下几个通宵。1. 这块板子的调试基本盘环境、工具和第一个坑1.1 为什么选TMS32F28P550先说下这颗芯片。TMS32F28P550是TI C2000实时控制家族里的中坚型号150MHz主频带浮点单元和CLA协处理器片上Flash和RAM容量做电机控制、数字电源这类场景都够用。比28379D少了一堆外设但核心的ADC、ePWM、SCI、SPI、CAN一个不缺价格低不少性价比确实香。不过这也意味着它的调试思路和28379D基本一脉相承仿真器用XDS110IDE用CCS代码里先配时钟、再配外设、最后写主循环。如果你之前玩过其他C2000芯片上手难度不大。但恰恰是这种“熟悉感”最容易坑人——我后面踩的坑好几个都是因为想当然。1.2 调试环境的搭建细节我用的环境组合是CCS 12.8Theia版本 XDS110仿真器。这块芯片也支持用UniFlash烧录但在线调试还是CCS顺手。新建工程的时候有个容易忽略的点CCS的工程模板里有不少示例但如果你用的是自己画的板子千万别直接套用示例的链接器cmd文件。提示F28P550的内存map和28379D不一样Flash起始地址、RAM分区、Boot ROM大小都要对照数据手册确认。我当时图省事直接改了个28379D的cmd文件编译倒是过了一运行就进非法ISR。后来老老实实把TMS32F28P550的Flash和RAM段一个一个核对了一遍才正常。1.3 第一次连接仿真器就翻车板子供电仿真器插上CCS里点连接目标板结果报错说“Error connecting to the target”。这个错误在C2000调试里太常见了但原因千奇百怪。我按老经验先查了电源给板子加的是5V输入经过板载LDO转3.3V和1.2V内核电压。用万用表量3.3V和1.2V都有输出数值也正常。再量复位引脚是高电平正常。XDS110的JTAG接线也确认过没接反。那问题出在哪后来我把示波器探头怼到晶振引脚上发现完全没有波形。再一查原来是我开板的时候把晶振的一个负载电容虚焊了导致整个时钟电路不工作。芯片没时钟JTAG自然是连不上的。重新补焊电容连接一次通过。这个教训很有代表性调试遇到“连不上目标板”不要只盯着仿真器配置看先用示波器确认芯片有没有跑起来的最小条件——供电、复位、时钟这三样缺一个都是连不上。2. 上电后程序不运行Boot引脚和供电那点事2.1 现象程序下载成功但外设没反应第一次成功连接仿真器后我在工程里放了个最简单的GPIO翻转程序点下载并运行。CCS显示“Loading Program ... Finished”但板子上的LED就是不肯亮。这里先交代一下背景C2000系列芯片在上电后会先运行Boot ROM里的引导程序根据Boot引脚的电平状态决定是从Flash启动、从RAM启动还是进入SCI/SPI/CAN引导模式。如果Boot引脚配置不对芯片根本不会跳转到用户Flash里的应用程序自然啥都不跑。2.2 排查链路从电源纹波到Boot引脚电平我先用万用表量了GPIO对应引脚的电平发现程序设有输出高但引脚一直是低。再用示波器看3.3V电源纹波在正常范围内排除了供电不足导致的反复复位。然后翻数据手册的Boot ROM章节。F28P550的Boot模式由一个组合逻辑决定具体哪几个GPIO引脚、什么样的电平组合对应什么模式数据手册里给了一张完整的表格。我按照表格用万用表量了我板上那几个Boot引脚的电压发现其中一个引脚的电平被拉高了但我的设计意图是让它默认接地。2.3 根因电阻贴反查原理图那个Boot引脚我设计的是通过10k电阻下拉到地。但量出来引脚却是高电平。顺着走线一看好家伙下拉电阻和隔壁一个上拉电阻贴反了位置。两个都是0402封装丝印又小焊接的时候没看清就贴了上去。这个问题在没有仿真器或者不熟悉Boot机制的人手上可能排查很久。但一旦理解了C2000的启动流程排查方向就很清晰了。注意做C2000板子时Boot引脚的上下拉电阻一定要在原理图评审阶段就确认好。更稳妥的做法是预留0欧电阻或者跳线帽方便调试时切换启动模式避免为了改Boot模式去飞线。3. 串口调试助手收不到数据SCI模块调试实录3.1 现象程序里初始化了SCI但串口助手一片空白Boot问题解决后程序终于跑起来了GPIO翻转也能在示波器上看到波形。接下来我开始调串口打算用串口调试助手打印一些调试信息。代码里初始化了SCI-A模块波特率设置成1152008位数据位、1位停止位、无校验然后在主循环里周期性地发一串字符串。结果串口调试助手打开对应COM口波特率设好点“打开串口”接收区一片空白。而且诡异的是我用示波器去量芯片的TX引脚居然连一点电平跳变都看不到。3.2 第一层排查引脚复用功能是否配置正确C2000的引脚几乎都是多功能复用的同一个引脚既可以做GPIO也可以做SCI、SPI、ePWM等功能。如果代码里只初始化了SCI外设但是没有配置引脚的复用功能那么数据根本不会从引脚输出来。我翻了下代码果然我只配置了SCI模块的寄存器完全没有调用GPIO的引脚复用配置函数。在C2000的驱动库driverlib里类似于GPIO_setPinConfig(GPIO_28_PIN_SCI_RX)这样的调用才是关键。补上之后示波器再看TX引脚已经能看到UART波形了。3.3 第二层排查波特率误差导致乱码波形有了但串口调试助手里收到的是一堆乱码和奇怪的符号。这个现象很有迷惑性一开始我以为是电平和接线问题后来发现其实是波特率不匹配。C2000的SCI波特率生成器由LSPCLK低速外设时钟和波特率寄存器BRR决定。公式是当BRR不等于0时实际波特率 LSPCLK / (8 × (BRR 1))。问题出在我配置系统时钟时把LSPCLK设置为25MHz但我计算BRR时却误用了20MHz。算出来的数值差了20%左右在115200波特率下这个误差直接导致采样点错位收出来全是乱码。重新按照实际LSPCLK计算写入正确的BRR值后串口助手接收区终于出现了一行行整齐的打印信息。3.4 第三层排查USB转串口模块的电平问题还有一个值得提醒的坑是在另一块板子上遇到的芯片的串口是TTL电平0~3.3V而有些USB转串口模块是5V电平。如果直接把5V电平的信号接到芯片的RX引脚长期运行会损坏引脚。反过来如果用带5V电平的RS232接口芯片还需要确认接口芯片是否支持3.3V供电。提示调试串口时建议先用示波器确认TX引脚的波形幅值再决定是否加电平转换芯片。确认过电平后再连接上位机别信“USB转串口模块都兼容3.3V”这种说法。4. ADC采样值乱跳参考电压与采样窗口的完整排查4.1 现象传感器信号稳定但ADC读数忽大忽小串口通了之后我开始调ADC打算采集一个电位器分压的电压值。用万用表量电位器输出端电压稳定在1.65V左右但通过串口打印出来的ADC转换结果却在800到1100之间乱跳12位ADC满量程4095。按1.65V算正确值应该稳定在1350上下这个跳动幅度明显不正常。4.2 第一层排查ADC参考电压的来源C2000的ADC参考电压可以选内部参考或者外部参考具体由板上硬件和寄存器配置决定。我查了下原理图发现板子上VREFHI引脚是悬空的但代码里却配置了使用外部参考电压。外部参考电压引脚悬空ADC的转换结果自然是不确定的。注意C2000的ADC参考电压配置在driverlib里通常有类似ADC_setMode(ADC_BASE, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED)的调用其中还包含了内部参考或外部参考的选择。这里的一个常见坑是有的芯片只有特定ADC模块支持内部参考另外的模块必须接外部参考具体要看数据手册。4.3 第二层排查采样窗口设置太短改成内部参考电压之后读数稳定了一些但跳变还是比预想的大。这时候我开始怀疑采样窗口时间不足。ADC采样过程分为采样阶段和转换阶段。采样阶段的时间由ACQPSAcquisition Prescaler寄存器控制单位为SYSCLK周期。如果采样窗口太短内部采样电容还没充满电就开始转换结果就会偏小且不稳定。尤其是信号源阻抗比较大的时候需要更长的采样时间。C2000的采样时钟计算公式大致是采样时间 (ACQPS 1) × SYSCLK周期。我原来的ACQPS值设的是9采样时间太短。改成28之后再测读数稳定在了1345到1356之间基本符合预期。4.4 第三层排查软件平均和触发源选择硬件层排查完软件层也有一些技巧。C2000的ADC可以设置多种触发源软件触发、定时器触发、ePWM触发等。如果是采样一个较为平稳的直流信号软件触发然后连续采样几次取平均是很实用的做法。我在主循环里连续启动16次ADC转换去掉最大值和最小值再用剩余14次的平均值作为最终结果。串口打印出来的数据跳动幅度进一步缩小到了±2以内。这个处理在工业控制场景里很常见但要注意平均会引入延迟如果ADC采样的目标是高频信号需要权衡平均次数。配置项初始状态调整后现象参考电压外部VREFHI悬空内部参考读数从乱跳变为基本稳定但有偏差ACQPS采样窗口928读数偏差缩小稳定性提升软件滤波无16次去极值平均读数稳定在±2以内5. PWM波形异常从时基到死区的连锁问题5.1 现象ePWM输出波形有毛刺且占空比和预期不符ADC搞定后我开始调试ePWM模块准备输出一对带死区的互补PWM波用于驱动半桥电路。在示波器上观察波形时发现两个问题一是PWM波形上有不少毛刺二是实际输出占空比和设定的50%偏差明显目测只有40%左右。5.2 排查的第一站时基时钟配置ePWM的时基时钟TBCLK由系统时钟EPWMCLK分频得到具体分频系数由寄存器CLKDIV和HSPCLKDIV决定。如果分频配置错了PWM的频率就会和预期不符。但频率本身我是验证过的示波器量出来确实是需要的20kHz所以时基问题暂时排除。5.3 排查的第二站计数器模式与周期值既然频率对了那占空比偏差的根源在比较值CMPA的计算上。ePWM的占空比取决于CMPA与周期寄存器TBPRD的关系。在up-down计数模式下输出翻转点由CMPA决定但my代码里使用的是up-count模式。我当时写了一个通用的配置函数但模式设置没按实际需求改导致占空比比例不对。这个问题的教训很直接代码里到处复制粘贴配置函数的时候一定要检查计数器模式这个参数。同样的CMPA和TBPRD值在up-count和up-down模式下的实际占空比算起来完全不同。5.4 排查的第三站死区寄存器配置和毛刺来源毛刺的问题一开始我以为是布局走线导致的干扰但用示波器看芯片引脚直接输出的波形毛刺依旧存在。这就说明问题出在芯片内部配置上。翻到死区Dead Band子模块发现问题我配置了使能死区生成但DBRED和DBFED两个寄存器都设置的0。理论上死区时间0不应该产生毛刺但实际上互补输出的两个信号在极短时间内的竞争冒险会在上升沿和下降沿产生非常窄的毛刺脉冲。注意死区时间并不是越大越好也不是设成0就没问题。对于电机驱动和电源变换器死区时间需要根据功率管的开关特性计算至少要覆盖器件的关断延迟时间但又不能大到明显影响占空比精度。我最终选择了300ns的死区时间毛刺完全消失占空比控制也保持正常。补一个具体的配置代码段driverlib风格// 配置ePWM1的时基 EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); EPWM_setTimeBasePeriod(EPWM1_BASE, periodValue); EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP); EPWM_setTimeBaseCounter(EPWM1_BASE, 0); // 配置比较值 EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, cmpValue); // 配置动作限定器 EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD); // 配置死区 EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_RED, true); EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_FED, true); EPWM_setDeadBandDelayPulse(EPWM1_BASE, EPWM_DB_RED, 300); EPWM_setDeadBandDelayPulse(EPWM1_BASE, EPWM_DB_FED, 300);这样配置之后示波器上看到的是一对平滑的互补波形死区清晰毛刺消失。6. 调试效率篇CCS里的实时变量观察与串口打印结合6.1 让CCS帮我“看见”ADC数据流在线调试的时候与其一条条看ASCII码不如直接把数据以波形形式显示。CCS自带的Graph工具可以把内存里的一段缓冲区当作波形来显示。我是这么做的在程序里开一个环形缓冲区ADC采样值不断写入然后在CCS中新建一个Graph指定起始地址为这个缓冲区数据类型选16位无符号整型长度设为256。运行程序后Graph能实时显示255个采样点的波形。这在调电机电流环或者电源电压环的时候效果拔群。6.2 Watch窗口和断点配合的调试节奏C2000的调试器支持硬件断点和软件断点但要注意CCS在Flash上跑程序时硬件断点的数量是有限的一般是6个左右具体看芯片。如果你在多个地方设了断点后面设的可能不会生效。遇到“断点不触发”的问题先删掉多余断点再试。用Watch窗口观察变量时如果发现变量名显示为“Could not find symbol”多半是编译器优化掉了这个变量。一个稳妥的办法是把要观察的变量声明成volatile或者在编译选项中降低优化等级。调嵌入式程序时0优化和2优化的差别在调试体验上可以说是天壤之别。6.3 用串口调试助手时间戳定位时序问题硬件在环测试的时候不能老是挂着仿真器跑。我的习惯是程序里用软件定时器产生一个毫秒级时基每次把关键状态比如当前步进电机的目标位置、PWM占空比设定值通过SCI发送到串口调试助手并带上时间戳。串口调助手收到的每一行都有时间标记这样即使没有示波器也能事后分析程序在不同时刻的行为。这个习惯帮我查过一次非常隐蔽的bug程序跑着跑着突然进入非法中断看起来是随机故障。后来通过串口打印的时间戳发现每次故障都发生在同一功能被调用之后顺藤摸瓜定位到了一个数组越界问题。6.4 常见CCS调试问题速查表现象优先级最高的排查方向备注连接目标板失败供电、复位、时钟示波器确认最小系统条件下载后不运行Boot引脚电平对照数据手册Boot表格串口无输出引脚复用配置先量引脚波形再查寄存器串口乱码LSPCLK和BRR匹配实际时钟和计算值不一致最常见ADC结果跳变参考电压和采样窗口内部参考还是外部参考PWM波形毛刺死区寄存器不要设0死区断点不触发断点数量超限或优化等级用volatile修饰观察变量最后再说两句调TMS32F28P550这段时间最大的体会是C2000系列的坑大部分不在芯片本身而在“你以为你懂”的地方。Boot引脚电阻、LSPCLK频率、参考电压选择、死区配置……这些在数据手册里都有写但手册是分散的没有人帮你串成一条线。出问题的时候最快的解决方式不是撸代码而是先拿起万用表和示波器把芯片的工作条件一项项确认过去。如果你手上正在调这块芯片建议先把数据手册里的Boot章节和时钟章节完整看一遍再动手写代码。遇到问题的时候别急着百度先自己推一遍我现在的配置输入是什么芯片实际的执行路径是什么这两者之间哪里可能不一致硬件调试没什么玄学很多时候就是比耐心和细致。希望这篇实录能帮你在F28P550上少走几段弯路调板顺利。
返回列表