资源链接:

1、tms320f28035中文数据手册.pdf
链接:https://pan.baidu.com/s/1trMohQQ9fIfC1h0yreU4Gg?pwd=1234 提取码: 1234

2、完整工程文件:Example_2803xGpioToggle (2).zip
链接:https://pan.baidu.com/s/1yT7nslO-FIFFZ_Q_Wzj87g?pwd=1234 提取码: 1234

搭建环境:

1、硬件环境:DSP TMS320F28035 开发板 

2、软件环境:基于CCS20.2.0开发

一、F28035定时器中断
1. 定时器原理

F28035内置3个CPU Timer(Timer0/Timer1/Timer2),本质是硬件计数器,工作逻辑如下:

  • 定时器基于DSP主频(默认60MHz)计数,1个时钟周期 = 1/60000000 ≈ 16.67ns;

  • 我们给定时器设置一个“计数上限(PRD寄存器)”,定时器从0开始递增计数;

  • 当计数值达到PRD时,定时器“溢出”,触发一次中断;

  • 中断触发后,CPU暂停当前任务,执行我们写的“中断服务函数”,执行完回到原任务;

  • 定时器溢出后自动重置为0,重新计数,循环往复。

2. 定时器中断的核心公式
RD(计数上限)= (DSP主频 / 中断频率) - 1

示例:要实现1ms(1000Hz)中断一次,代入60MHz主频:

PRD = 60000000 / 1000 - 1 = 59999

→ 定时器从0数到59999,正好耗时1ms,触发一次中断。

3. 中断触发的完整链路

简单说:

定时器溢出只是“触发信号”,

必须通过“PIE组→CPU级→全局”三层使能,

中断才能传到CPU;执行完中断后,必须清除标志,否则会无限触发中断。

二、写定时器中断代码
1. 目标

用Timer0实现1ms中断一次,累计1秒(1000次中断)后翻转GPIO34电平,让LED每秒闪烁1次。

2. 完整代码
#include "DSP28x_Project.h"  // 引用头文件,包含所有寄存器/函数定义

#define LED_PIN    34        // LED引脚,GPIO34属于GPB组
#define LED_ON     1         // 1=拉高点亮
#define TIMER_FREQ 1000      // 定时器中断频率(Hz),1000Hz=1ms中断一次
#define BLINK_FREQ 1         // LED闪烁频率(Hz),1Hz=1秒闪烁一次

// 全局变量:用于中断计数
volatile Uint16 timer_count = 0;
// 声明中断服务函数
interrupt void cpu_timer0_isr(void);
// LED初始化函数
void LED_Init(void)
{
    EALLOW;                                   // 解锁受保护寄存器 
    GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;      // 配置GPIO34为普通GPIO模式
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1;       // 配置GPIO34为输出模式 
    GpioCtrlRegs.GPBPUD.bit.GPIO34 = 1;       // 禁用GPIO34的内部上拉电阻
    EDIS;                                     // 锁定受保护寄存器
    // 设置LED初始电平
    if(LED_ON == 0){
        GpioDataRegs.GPBCLEAR.bit.GPIO34 = 1;
    }else{
        GpioDataRegs.GPBSET.bit.GPIO34 = 1;
    }
}
// 定时器0初始化函数(配置中断)
void Timer0_Init(void)
{
    // 1. 禁用定时器0,进入配置模式
    CpuTimer0Regs.TCR.bit.TSS = 1;            // 停止定时器0
    CpuTimer0Regs.TCR.bit.TRB = 1;            // 重载周期寄存器
    // 2. 配置定时器周期(60MHz主频)
    // 周期计算公式:Period = (主频 / 中断频率) - 1
    CpuTimer0Regs.PRD.all = (Uint32)(60000000.0 / TIMER_FREQ) - 1;
    // 3. 配置定时器控制寄存器
    CpuTimer0Regs.TCR.bit.TIE = 1;            // 使能定时器0中断
    CpuTimer0Regs.TCR.bit.FREE = 1;           // 调试时定时器继续运行
    CpuTimer0Regs.TCR.bit.SOFT = 0;
    // 4. 配置PIE中断控制器
    EALLOW;
    PieVectTable.TINT0 = &cpu_timer0_isr;     // 映射定时器0中断服务函数
    EDIS;
    
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;        // 使能PIE组1的7号中断(TINT0)
    IER |= M_INT1;                            // 使能CPU级的INT1中断
    EINT;                                     // 使能全局中断
    ERTM;                                     // 使能实时模式中断
    // 5. 启动定时器0
    CpuTimer0Regs.TCR.bit.TSS = 0;            // 启动定时器0
}
// 定时器0中断服务函数(中断发生时执行)
interrupt void cpu_timer0_isr(void)
{
    // 1. 清除中断标志(必须!否则会一直进入中断)
    CpuTimer0Regs.TCR.bit.TIF = 1;            // 清除定时器0中断标志
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // 清除PIE组1的中断挂起标志
    // 2. 计数到指定值后翻转LED
    timer_count++;
    if(timer_count >= (TIMER_FREQ / BLINK_FREQ))
    {
        timer_count = 0;                      // 重置计数器
        GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;// 翻转LED电平
    }
}
void main(void)
{
    // 1. 系统初始化
    InitSysCtrl();          // 关闭看门狗+配置系统时钟(60MHz)+初始化外设时钟
    DINT;                   // 关闭全局中断
    InitPieCtrl();          // 初始化PIE控制器
    IER = 0x0000;           // 清除CPU中断使能寄存器
    IFR = 0x0000;           // 清除CPU中断标志寄存器
    InitPieVectTable();     // 初始化PIE中断向量表
    // 2. 外设初始化
    LED_Init();             // LED GPIO初始化
    Timer0_Init();          // 定时器0初始化(含中断配置)
    // 3. 主循环
    while(1)
    {
    }
}
三、代码核心模块
1. 定时器初始化

代码行

作用原理

CpuTimer0Regs.TCR.bit.TSS = 1

停止定时器,避免配置时计数

CpuTimer0Regs.PRD.all = 59999

设置计数上限,决定中断频率

PieVectTable.TINT0 = &cpu_timer0_isr

中断向量表映射,指定中断执行的函数

PieCtrlRegs.PIEIER1.bit.INTx7 = 1

开启PIE组1.7中断(Timer0专属,详见下图)

EINT()

开启全局中断总开关

2. 主函数:初始化顺序

系统初始化 → 关闭全局中断 → PIE控制器初始化 → 外设初始化 → 开启中断 → 主循环

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐