资讯动态

TMS320F28335例程包使用指南:从导入到外设驱动封装

发布时间:2026/10/17 8:23:56 来源:尧图企业网站定制
简介这份资源是面向TI TMS320F28335浮点DSP的编程例程合集适合嵌入式初学者入门与有经验的开发者快速搭建工程模板。芯片广泛用于工业控制、电机驱动、电力电子与自动化领域例程覆盖GPIO按键输入、EPWM脉宽调制、外部中断、ECAP捕获、ADC与ADC2模数转换、SCI串口通信、SPI回环测试以及CPU定时器等核心外设基本涵盖实际项目常用的功能模块。压缩包为rar格式共1930个文件以d依赖文件、obj目标文件、h头文件、c源码、mk与makefile构建脚本、asm汇编启动代码、xml与ccxml配置、map映射及out输出文件为主整体约4.72MB目录按模块组织便于对照查阅与移植。目前已有831人学习下载。读者可借此理解各外设的初始化流程、中断响应机制与数据传输配置方法并直接复用代码框架缩短开发周期遇到疑问还可通过作者邮箱获取支持。1. 拿到 TMS320F28335 例程包先别急着烧录如果你手上正捏着一块 F28335 的板子配套的例程包也刚下载完第一反应多半是打开 CCS 直接点烧录。我劝你先停一下。TMS320F28335 属于 C2000 系列的浮点 DSP主频 150MHz带 FPU 和 12 位 ADC工业控制里做电机驱动、数字电源、逆变器的工程师对它再熟悉不过。但它的例程包和 STM32 那种“下载即跑”的生态完全不同——时钟树、PLL、外设时钟使能、GPIO 复用、中断向量表任何一环没配对程序就是跑不起来而且不报错只是没反应。这份 TMS320F2833x 例程包的价值在于它把底层寄存器配置和驱动框架都摊开了适合想从寄存器层面吃透 F28335 的人也适合拿它当项目起点做二次开发。但前提是你得知道怎么用。2. 例程包的结构与工程导入从文件夹到可编译工程2.1 先认清目录里有什么拿到一个 TMS320F2833x 例程包别急着双击 .c 文件。先花五分钟把目录结构摸清楚后面能省掉大量“找不到头文件”的时间。典型的例程包一般包含这几类内容目录/文件作用常见坑DSP2833x_headers/寄存器头文件、外设结构体定义路径没加进 include 就满屏未定义DSP2833x_common/通用源文件如DSP2833x_SysCtrl.c、DSP2833x_Gpio.c漏加 .c 文件导致链接报错cmd/链接命令文件如F28335.cmd选错 cmd 导致程序跑飞examples/或projects/各外设例程如 GPIO、SCI、ePWM、ADC例程之间共用头文件路径要统一lib/可能包含 IQmath、FPU 库库版本和 CCS 版本不匹配这里最关键的是cmd文件夹。F28335 的存储映射分 Flash 和 RAM 两种运行模式对应的 cmd 文件不一样。很多人第一次跑例程编译通过了但程序没反应八成是 cmd 选错——把 Flash 的 cmd 用在 RAM 调试上或者反过来。2.2 在 CCS 里建工程并挂载例程假设你用的是 CCSCode Composer Studio版本不限操作逻辑大同小异。我一般不会直接打开例程自带的 .project 文件因为路径一变就报错而是新建一个空工程再把文件挂进去。# 假设例程包解压在 D:/dsp/F28335_examples # 工程工作区放在 D:/dsp/workspace # 第一步确认例程包里有这些关键文件 ls D:/dsp/F28335_examples/DSP2833x_common/source/ # 应该看到 DSP2833x_SysCtrl.c、DSP2833x_Gpio.c、DSP2833x_PieCtrl.c 等 ls D:/dsp/F28335_examples/DSP2833x_headers/include/ # 应该看到 DSP2833x_Device.h、DSP2833x_Examples.h 等上面这段不是让你真在 Windows 下敲 ls而是提醒你动手前先确认源文件和头文件都在。常见情况是例程包只给了头文件和主程序通用驱动 .c 文件缺失这时候你得从官方库补或者从其他例程里拷。在 CCS 里的操作步骤File → New → CCS Project芯片选 TMS320F28335编译器版本按你装的选。右键工程 → Add Files把DSP2833x_common/source/下需要的 .c 文件加进来。注意不是全加比如你只跑 GPIO 例程SysCtrl、Gpio、PieCtrl 这几个是必须的SCI 的可以先不加。右键工程 → Properties → Build → Include Options添加两个路径DSP2833x_headers/include和DSP2833x_common/include。在 Linker 的 File Search Path 里把对应的 cmd 文件加进来。调试阶段用 RAM 版 cmd量产再换 Flash 版。2.3 编译前必须检查的三个配置工程挂好了不代表能跑。F28335 的例程有个特点很多配置写在DSP2833x_Examples.h里通过宏定义切换。编译前重点看三处第一DSP2833x_Examples.h里的CPU_RATE和PLL相关宏。F28335 外部晶振常见是 30MHz经过 PLL 倍频到 150MHz。如果这个宏和你板子上的晶振对不上系统时钟就是错的后面所有定时器、串口波特率全乱。第二DSP2833x_SysCtrl.c里的InitSysCtrl()函数。这个函数负责配置 PLL、外设时钟、看门狗。有些例程为了演示方便会把看门狗关掉你二次开发时如果没注意看门狗没开程序跑飞了都不知道。第三中断向量表。F28335 的中断分 PIE 三级外设级、PIE 级、CPU 级。例程里通常在DSP2833x_PieVect.c里注册中断服务函数。如果你自己加了中断忘了在 PieVect 表里挂函数中断永远不会进。// 以 GPIO 翻转为例典型的 main 结构 #include DSP2833x_Device.h #include DSP2833x_Examples.h void main(void) { // 第一步初始化系统控制PLL、外设时钟、看门狗 InitSysCtrl(); // 第二步初始化 GPIO把 GPIO0 配成输出 EALLOW; // 允许写保护寄存器 GpioCtrlRegs.GPAMUX1.bit.GPIO0 0; // 0 表示普通 IO GpioCtrlRegs.GPADIR.bit.GPIO0 1; // 1 表示输出 EDIS; // 关闭写保护 // 第三步主循环翻转电平 for(;;) { GpioDataRegs.GPATOGGLE.bit.GPIO0 1; // 翻转 GPIO0 DELAY_US(500000); // 延时 500ms } }这段代码的逻辑说明EALLOW和EDIS是 F28335 特有的写保护机制GPIO 复用和方向寄存器受保护不解除保护写进去无效。GPATOGGLE是翻转寄存器写 1 就翻转比读-改-写安全。DELAY_US是官方提供的微秒级延时依赖 CPU 频率宏所以前面说的CPU_RATE必须配对。参数说明GPAMUX1控制 GPIO0~15 的复用写 0 是普通 IO写 1 是外设功能。GPADIR写 1 输出写 0 输入。这些寄存器在DSP2833x_Gpio.h里有结构体定义直接点进去看位域就行。3. 外设例程逐个拆GPIO、SCI、ePWM、ADC 怎么跑通3.1 GPIO 与中断最基础也最容易翻车GPIO 例程看起来最简单但 F28335 的 GPIO 有几个坑。第一GPIO 分组A 组 0~31B 组 32~63C 组 64~87每组有自己的 MUX、DIR、QUAL 寄存器。第二输入限定Qualification默认是打开的采样窗口 6 个周期。如果你做按键输入不加消抖配置读到的电平可能跳来跳去。// GPIO 输入中断配置示例GPIO12 下降沿触发 EALLOW; GpioCtrlRegs.GPAMUX1.bit.GPIO12 0; // 普通 IO GpioCtrlRegs.GPADIR.bit.GPIO12 0; // 输入 GpioCtrlRegs.GPAQSEL1.bit.GPIO12 0; // 与系统时钟同步不用采样窗口 GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL 12; // XINT1 选择 GPIO12 EDIS; XIntruptRegs.XINT1CR.bit.POLARITY 0; // 0 下降沿触发 XIntruptRegs.XINT1CR.bit.ENABLE 1; // 使能 XINT1 // 在 PIE 向量表里注册 XINT1 的中断服务函数 EALLOW; PieVectTable.XINT1 xint1_isr; EDIS; PieCtrlRegs.PIEIER1.bit.INTx4 1; // XINT1 对应 PIE 第 1 组第 4 个 IER | M_INT1; // 使能 CPU 中断 1 EINT; // 开全局中断逻辑说明GPAQSEL1设为 0 表示输入信号与系统时钟同步适合干净的数字信号如果是机械按键建议设成采样窗口模式或者软件消抖。GPIOXINT1SEL决定哪个 GPIO 映射到 XINT1F28335 的 XINT1 只能从 GPIO0~31 里选。中断服务函数里必须手动清除 PIE 应答位否则中断只进一次。参数说明XINT1CR的POLARITY位0 是下降沿1 是上升沿2 是双边沿。PIEIER1的INTx4对应 XINT1这个映射关系在数据手册的 PIE 表里有别记错。3.2 SCI 串口波特率对不上是头号问题SCI 例程跑不通九成是波特率问题。F28335 的 SCI 波特率由LSPCLK分频得到而LSPCLK又来自系统时钟。如果你改了 PLL 但没改LSPCLK分频波特率就偏了。// SCI-A 初始化目标波特率 9600 void InitScia(void) { EALLOW; GpioCtrlRegs.GPAMUX2.bit.GPIO28 1; // GPIO28 配成 SCIRXDA GpioCtrlRegs.GPAMUX2.bit.GPIO29 1; // GPIO29 配成 SCITXDA EDIS; SciaRegs.SCICCR.all 0x0007; // 1 停止位无校验8 数据位 SciaRegs.SCICTL1.all 0x0003; // 使能 TX 和 RX SciaRegs.SCICTL2.all 0x0003; // 使能 RX 中断和 TX 中断 // 波特率计算BRR LSPCLK / (SCIBAUD * 8) - 1 // 假设 LSPCLK 37.5MHz9600 波特率 SciaRegs.SCIHBAUD 0x0001; SciaRegs.SCILBAUD 0x0044; // 0x0144 324对应 37.5M/(9600*8)-1 ≈ 487 // 注意上面这个值要按实际 LSPCLK 算别照抄 SciaRegs.SCICTL1.bit.SWRESET 1; // 退出复位 }逻辑说明SCI 的波特率寄存器是 16 位的高 8 位和低 8 位分开写。计算公式是BRR LSPCLK / (波特率 × 8) - 1。LSPCLK默认是SYSCLKOUT / 4如果系统时钟 150MHzLSPCLK就是 37.5MHz。很多人抄例程时没注意例程的LSPCLK配置直接抄 BRR 值结果波特率差一倍。参数说明SCICCR的 bit0~2 是字符长度bit2 是停止位数量bit5 是校验使能。SCICTL1的 bit0 是 RX 使能bit1 是 TX 使能bit5 是 SWRESET写 1 退出复位。配置完必须写 SWRESET 才能生效。3.3 ePWM电机控制的核心死区配置是重点ePWM 是 F28335 在工业控制里最值钱的外设。例程一般会给一个简单的 PWM 输出但实际做电机驱动死区、载波频率、同步、触发 ADC 这些都要配。// ePWM1 配置10kHz PWM带死区 void InitEPwm1(void) { EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC 0; // 配置前先停止所有 TB 时钟 EDIS; EPwm1Regs.TBPRD 3750; // 周期 150MHz / (2 × 10kHz) 7500这里用增减计数 EPwm1Regs.TBPHS.half.TBPHS 0; // 相位清零 EPwm1Regs.TBCTR 0; // 计数器清零 EPwm1Regs.TBCTL.bit.CTRMODE 2; // 增减计数模式 EPwm1Regs.TBCTL.bit.PHSEN 0; // 禁止相位加载 EPwm1Regs.TBCTL.bit.HSPCLKDIV 0; // 高速时钟不分频 EPwm1Regs.TBCTL.bit.CLKDIV 0; // 时钟不分频 EPwm1Regs.CMPA.half.CMPA 1875; // 占空比 50% EPwm1Regs.AQCTLA.bit.CAU 2; // 计数上升沿等于 CMPA 时置高 EPwm1Regs.AQCTLA.bit.CAD 1; // 计数下降沿等于 CMPA 时置低 // 死区配置上升沿延时 100ns下降沿延时 100ns EPwm1Regs.DBCTL.bit.OUT_MODE 3; // 使能上升沿和下降沿延时 EPwm1Regs.DBCTL.bit.POLSEL 2; // EPWMxA 不反转EPWMxB 反转 EPwm1Regs.DBRED 15; // 100ns × 150MHz 15 EPwm1Regs.DBFED 15; EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC 1; // 启动 TB 时钟 EDIS; }逻辑说明增减计数模式下周期 2 × TBPRD / SYSCLKOUT。TBPRD 3750对应 10kHz。AQCTLA配置动作限定决定 CMPA 匹配时输出怎么变。死区配置里DBRED和DBFED是死区时间对应的计数值100ns × 150MHz 15。POLSEL 2表示 EPWMxA 不反转、EPWMxB 反转这样两路输出互补。参数说明TBCLKSYNC在配置前必须清零配置完再置 1否则多个 ePWM 模块之间相位不同步。CMPA是 16 位但实际有效位数取决于TBPRD。死区时间别设太大否则输出电压畸变。3.4 ADC采样精度和触发源F28335 的 ADC 是 12 位、16 通道但实际有效精度受参考电压和采样窗口影响。例程一般给软件触发采样实际项目里常用 ePWM 触发。// ADC 初始化软件触发采样通道 A0 void InitAdc(void) { EALLOW; SysCtrlRegs.PCLKCR0.bit.ADCENCLK 1; // 使能 ADC 时钟 EDIS; AdcRegs.ADCTRL1.bit.RESET 1; // 复位 ADC DELAY_US(100); AdcRegs.ADCTRL1.bit.RESET 0; AdcRegs.ADCTRL1.bit.ACQ_PS 0xF; // 采样窗口 16 个 ADCCLK AdcRegs.ADCTRL1.bit.CPS 0; // 核心时钟 ADCCLK / 1 AdcRegs.ADCTRL3.bit.ADCCLKPS 3; // ADCCLK HSPCLK / (2 × 3) 25MHz AdcRegs.ADCTRL3.bit.SMODE_SEL 0; // 顺序采样 AdcRegs.ADCTRL1.bit.SEQ_CASC 1; // 级联模式SEQ1 和 SEQ2 合成 16 通道 AdcRegs.ADCMAXCONV.bit.MAX_CONV1 0; // 只转换 1 个通道 AdcRegs.ADCCHSELSEQ1.bit.CONV00 0; // 选择 ADCINA0 AdcRegs.ADCTRL2.bit.SOC_SEQ1 1; // 软件触发 SEQ1 }逻辑说明ADCCLKPS决定 ADC 时钟F28335 的 ADC 最高时钟 25MHz超了精度下降。ACQ_PS是采样窗口窗口太短采样电容充不满读数偏小。SEQ_CASC 1把两个 8 通道序列器合成 16 通道适合多通道采集。参数说明ADCMAXCONV的MAX_CONV1是 SEQ1 的转换通道数减一写 0 表示 1 个通道。ADCCHSELSEQ1的CONV00写通道号0 对应 ADCINA0。软件触发写SOC_SEQ1 1硬件触发则配置ADCTRL2的SOC_SEQ1由 ePWM 触发。4. 避坑与排查那些让例程跑不起来的细节4.1 编译通过但程序没反应现象CCS 里编译零错误零警告烧录后 GPIO 不翻转、串口没输出。原因最常见的是 cmd 文件选错。RAM 调试用了 Flash 的 cmd程序被链接到 Flash 地址但调试时没烧到 FlashCPU 取指取到空区域。另一个可能是InitSysCtrl()里看门狗没关程序在初始化阶段就被复位了。解决调试阶段统一用 RAM 版 cmd确认DSP2833x_SysCtrl.c里DisableDog()被调用。如果用的是 Flash 调试确认 CCS 的 On-Chip Flash 配置里烧录了程序。4.2 中断进不去现象中断使能了PIE 也配了但中断服务函数就是不执行。原因F28335 的中断要过三关——外设级、PIE 级、CPU 级。任何一级没使能都进不去。常见漏配是IER寄存器没置位或者EINT没执行。另一个坑是 PIE 应答位没清第一次中断进去后PIE 标志一直挂着后续中断被阻塞。解决按顺序检查PieCtrlRegs.PIEIERx、IER、EINT。中断服务函数里第一句就写PieCtrlRegs.PIEACK.all PIEACK_GROUPx清对应组的应答。4.3 串口乱码现象串口助手收到数据但全是乱码。原因波特率不匹配。F28335 的LSPCLK默认是SYSCLKOUT / 4但有些例程会改这个分频。如果你抄了例程的 BRR 值但自己的LSPCLK不一样波特率就偏了。另一个可能是晶振频率和例程假设的不一致。解决先确认自己板子的晶振频率再算LSPCLK最后按公式算 BRR。用示波器量 TX 引脚看一个位的时间对不对。如果差得不多检查SCIBAUD寄存器的高低位有没有写反。4.4 ePWM 输出波形不对现象示波器上看 ePWM 输出频率不对或者占空比不对或者两路没有互补。原因TBPRD和计数模式不匹配。增减计数模式下周期是2 × TBPRD / SYSCLKOUT如果你按递减计数算的TBPRD频率就差一倍。死区配置里POLSEL设错两路输出可能同相。解决先确认TBCTL.CTRMODE再算TBPRD。用示波器量 EPWMxA 和 EPWMxB看死区时间是否对称。如果两路同相检查DBCTL.POLSEL。4.5 ADC 采样值跳动大现象ADC 读回来的值不稳定跳动几十个 LSB。原因采样窗口太短采样电容没充满。或者参考电压不稳或者模拟地和数字地没处理好。F28335 的 ADC 对电源噪声敏感VDDA和VSSA的滤波电容不能省。解决加大ACQ_PS先设到最大 16 个 ADCCLK 试。检查ADCCLKPS确保 ADCCLK 不超过 25MHz。硬件上模拟电源加磁珠和电容模拟地单点接地。5. 从例程到项目把驱动封装成可复用的模块例程跑通只是第一步。真正做项目你不会每次都在 main 里堆寄存器配置。我一般会把每个外设的初始化封装成独立函数放在单独的 .c 文件里头文件只暴露初始化接口和关键参数宏。// bsp_gpio.h #ifndef BSP_GPIO_H #define BSP_GPIO_H #include DSP2833x_Device.h // GPIO 方向定义 #define GPIO_DIR_IN 0 #define GPIO_DIR_OUT 1 void Bsp_Gpio_Init(void); void Bsp_Gpio_SetDir(Uint16 pin, Uint16 dir); void Bsp_Gpio_Toggle(Uint16 pin); #endif// bsp_gpio.c #include bsp_gpio.h void Bsp_Gpio_Init(void) { EALLOW; // 默认全部配成普通 IO方向输入 GpioCtrlRegs.GPAMUX1.all 0; GpioCtrlRegs.GPAMUX2.all 0; GpioCtrlRegs.GPADIR.all 0; EDIS; } void Bsp_Gpio_SetDir(Uint16 pin, Uint16 dir) { Uint16 group pin / 32; Uint16 bit pin % 32; EALLOW; if(group 0) { if(dir GPIO_DIR_OUT) GpioCtrlRegs.GPADIR.all | (1UL bit); else GpioCtrlRegs.GPADIR.all ~(1UL bit); } // B 组、C 组类似略 EDIS; }逻辑说明把 GPIO 按组操作避免每次改一个引脚就动整个寄存器。GPAMUX1.all 0一次性把所有 A 组引脚配成普通 IO比逐位写快。SetDir里用位操作不影响其他引脚。参数说明pin是全局引脚编号0~87。group和bit的换算关系是pin / 32和pin % 32。注意 F28335 的 GPIO 分组不是均匀的A 组 32 个B 组 32 个C 组 24 个写的时候要按实际寄存器来。封装完之后main 函数就干净了void main(void) { InitSysCtrl(); Bsp_Gpio_Init(); Bsp_Gpio_SetDir(0, GPIO_DIR_OUT); for(;;) { Bsp_Gpio_Toggle(0); DELAY_US(500000); } }从那以后我每次拿到新的 F28335 例程包都强制走一遍这个流程先看 cmd 和时钟配置再跑 GPIO 验证最小系统然后逐个外设拆开封装最后才往项目里集成。这套习惯帮我省掉了大量“编译通过但跑不起来”的后悔药时间。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑