3. 定时器中断实现精确延时
任务定义
在TI C2000系列DSP(以TMS320F28335为例)上,利用CPU定时器0(CPU-Timer 0)产生周期中断,在中断服务函数中翻转GPIO34电平,实现精确的1ms定时中断与500ms周期方波输出。通过示波器或逻辑分析仪测量GPIO34波形周期,验证定时精度。
硬件连接
实现原理
CPU定时器0是C2000内核自带的32位递减计数器。定时器时钟源为系统时钟SYSCLKOUT(本案例配置为150MHz),经过预定标器分频后驱动计数器递减。当计数器递减到0时,产生TINT0中断请求,并自动重装载PRD寄存器中的周期值。在中断服务函数中翻转GPIO34电平,即可获得精确的定时方波输出。
代码实现
// main.c - TMS320F28335 CPU-Timer0 精确延时中断示例
#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
// 中断周期定义:1ms @ 150MHz SYSCLKOUT
#define TIMER0_PERIOD 150000L // 150MHz × 1ms = 150,000个时钟周期
// GPIO34翻转标志
volatile Uint32 g_toggleCount = 0;
// 中断服务函数原型
interrupt void cpu_timer0_isr(void);
void InitGpio34(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX2.bit.GPIO34 = 0; // 配置为GPIO功能
GpioCtrlRegs.GPADIR.bit.GPIO34 = 1; // 配置为输出
GpioDataRegs.GPASET.bit.GPIO34 = 1; // 初始输出高电平
EDIS;
}
void InitCpuTimer0(void)
{
// 定时器时钟 = SYSCLKOUT / (预定标器+1)
// 此处预定标器设为0,即不分频,定时器时钟 = 150MHz
CpuTimer0.RegsAddr = &CpuTimer0Regs;
// 设置周期寄存器
CpuTimer0Regs.PRD.all = TIMER0_PERIOD - 1; // 周期值(递减到0产生中断)
CpuTimer0Regs.TPR.all = 0; // 预定标器 = 0
CpuTimer0Regs.TPRH.all = 0;
// 初始化计数器值
CpuTimer0Regs.TIM.all = TIMER0_PERIOD - 1;
// 中断控制
CpuTimer0Regs.TCR.bit.TSS = 1; // 停止定时器
CpuTimer0Regs.TCR.bit.TRB = 1; // 重装载
CpuTimer0Regs.TCR.bit.FREE = 0; // 仿真暂停时定时器也暂停
CpuTimer0Regs.TCR.bit.SOFT = 0;
// 使能定时器中断
CpuTimer0Regs.TCR.bit.TIE = 1; // 使能定时器中断
// 中断向量表映射
EALLOW;
PieVectTable.TINT0 = &cpu_timer0_isr;
EDIS;
}
interrupt void cpu_timer0_isr(void)
{
// 翻转GPIO34
GpioDataRegs.GPADAT.bit.GPIO34 ^= 1;
g_toggleCount++;
// 清除中断标志
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
void main(void)
{
// 系统初始化(时钟150MHz,PLL配置等)
InitSysCtrl();
// 禁止全局中断
DINT;
// 初始化PIE控制寄存器
InitPieCtrl();
// 清除PIE中断标志并禁用
IER = 0x0000;
IFR = 0x0000;
// 初始化PIE向量表
InitPieVectTable();
// 初始化GPIO34
InitGpio34();
// 初始化CPU定时器0
InitCpuTimer0();
// 使能CPU中断INT1(定时器0中断挂在INT1.7)
IER |= M_INT1;
// 使能PIE中断组1的第7通道
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// 启动定时器0
CpuTimer0Regs.TCR.bit.TSS = 0;
// 使能全局中断
EINT;
ERTM;
// 主循环:空转,所有工作由中断完成
for(;;)
{
// 可在此添加低优先级任务
}
}
关键配置说明
| 参数 | 值 | 说明 |
|---|---|---|
| SYSCLKOUT | 150 MHz | 系统时钟(由InitSysCtrl配置) |
| 定时器预定标器 | 0 | 不分频,定时器时钟=150MHz |
| PRD周期值 | 149,999 | 150,000个时钟周期 = 1ms |
| 中断周期 | 1 ms | 每1ms进入一次ISR |
| GPIO34翻转频率 | 500 Hz | 每1ms翻转一次,方波周期2ms |
工程文件与编译
本案例基于TI官方例程框架,需要以下文件:
- DSP2833x_GlobalVariableDefs.c — 定义CpuTimer0Regs等全局寄存器结构体
- DSP2833x_PieCtrl.c — PIE控制器初始化
- DSP2833x_PieVect.c — PIE向量表初始化
- DSP2833x_SysCtrl.c — 系统时钟与外设时钟使能
- DSP2833x_CpuTimers.c — 定时器配置辅助函数(可选)
在CCS工程中添加上述源文件,包含头文件路径后编译。系统时钟配置为150MHz(PLLCR=10, DIVSEL=0)。
验证方法
测试步骤:
- 将GPIO34引脚连接示波器探头,示波器地线接开发板GND;
- 编译下载程序,运行后观察GPIO34输出波形;
- 测量方波周期,预期为2.000ms(频率500Hz);
- 连续测量10个周期,记录最大偏差。
判定标准:
- 波形为占空比50%的方波,无毛刺抖动;
- 实测周期在1.998ms~2.002ms范围内(误差±0.1%);
- 长时间运行(>1小时)周期稳定,无累积漂移。
预期输出:GPIO34输出周期2.000ms、频率500.0Hz的方波(由1ms中断周期翻转得到,该结果由定时器配置直接决定)。
注意事项
- 定时器中断服务函数应保持精简,避免在ISR中执行耗时操作导致定时溢出;
- 若系统时钟不是150MHz,需按实际频率重新计算TIMER0_PERIOD值;
- PIEACK_GROUP1必须在ISR末尾清除,否则后续中断无法响应;
- GPIO34在F28335上属于GPIOA组,操作寄存器为GPADAT/GPASET/GPACLEAR。