CPU定时器配置与使用

目录

  1. 定时器基础
  2. 与STM32对比
  3. 定时器寄存器
  4. 手动配置定时器
  5. SysConfig配置定时器
  6. 实战示例

定时器基础

F280049C有3个32位CPU定时器:

  • Timer0: 保留给实时操作系统(RTOS)使用
  • Timer1: 用户可用
  • Timer2: 用户可用

定时器特性

  • 位宽: 32位递减计数器
  • 时钟源: SYSCLK(系统时钟)
  • 预分频: 16位预分频器(1-65536)
  • 中断: 每个定时器有独立中断
  • 工作模式: 连续模式或单次模式

定时器工作原理

1
2
SYSCLK → 预分频器 → 32位计数器 → 中断
(÷N) (递减到0)

与STM32对比

定时器类型对比

特性 STM32 F280049C
定时器类型 基本/通用/高级定时器 CPU定时器
计数方向 向上/向下/中心对齐 仅向下计数
位宽 16位/32位 32位
PWM功能 支持 不支持(使用ePWM)
输入捕获 支持 不支持

配置流程对比

1
2
3
4
5
6
7
8
9
10
11
12
13
// STM32 HAL库
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 99;
htim2.Init.Period = 999;
HAL_TIM_Base_Init(&htim2);
HAL_TIM_Base_Start_IT(&htim2);

// F280049C DriverLib
CPUTimer_setPeriod(CPUTIMER1_BASE, 100000000);
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
CPUTimer_enableInterrupt(CPUTIMER1_BASE);
CPUTimer_startTimer(CPUTIMER1_BASE);

定时器寄存器

主要寄存器

1. TIMERxTIM - 计数器寄存器

1
CpuTimer1Regs.TIM.all = 0xFFFFFFFF;  // 设置计数初值

2. TIMERxPRD - 周期寄存器

1
CpuTimer1Regs.PRD.all = 100000000;  // 设置周期值

3. TIMERxTPR - 预分频寄存器

1
2
CpuTimer1Regs.TPR.bit.TDDR = 0;     // 预分频值
CpuTimer1Regs.TPR.bit.PSC = 0; // 预分频计数器

4. TIMERxTCR - 控制寄存器

1
2
3
4
CpuTimer1Regs.TCR.bit.TSS = 0;      // 0=启动, 1=停止
CpuTimer1Regs.TCR.bit.TRB = 1; // 1=重载计数器
CpuTimer1Regs.TCR.bit.TIE = 1; // 1=使能中断
CpuTimer1Regs.TCR.bit.FREE = 1; // 调试时继续运行

手动配置定时器

方法1: 直接寄存器操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "F28x_Project.h"

// 定时器中断服务函数
__interrupt void cpu_timer1_isr(void)
{
// 翻转LED
GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;

// 清除中断标志
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

void Timer1_Init_Register(void)
{
EALLOW;

// 1. 停止定时器
CpuTimer1Regs.TCR.bit.TSS = 1;

// 2. 设置预分频器(SYSCLK = 100MHz)
CpuTimer1Regs.TPR.bit.TDDR = 0; // 预分频 = TDDR + 1 = 1
CpuTimer1Regs.TPR.bit.PSC = 0;

// 3. 设置周期(1秒 = 100,000,000个时钟周期)
CpuTimer1Regs.PRD.all = 100000000 - 1;

// 4. 重载计数器
CpuTimer1Regs.TCR.bit.TRB = 1;

// 5. 配置为连续模式
CpuTimer1Regs.TCR.bit.FREE = 1;
CpuTimer1Regs.TCR.bit.SOFT = 1;

// 6. 使能定时器中断
CpuTimer1Regs.TCR.bit.TIE = 1;

// 7. 配置PIE中断
PieVectTable.TIMER1_INT = &cpu_timer1_isr;
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
IER |= M_INT1;

// 8. 启动定时器
CpuTimer1Regs.TCR.bit.TSS = 0;

EDIS;
}

方法2: DriverLib库函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "driverlib.h"
#include "device.h"

// 定时器中断服务函数
__interrupt void cpuTimer1ISR(void)
{
GPIO_togglePin(31);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}

void Timer1_Init_DriverLib(void)
{
// 1. 初始化定时器(100MHz系统时钟)
CPUTimer_stopTimer(CPUTIMER1_BASE);

// 2. 设置周期(1秒 = 100,000,000个时钟周期)
CPUTimer_setPeriod(CPUTIMER1_BASE, 100000000);

// 3. 设置预分频器(0 = 不分频)
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);

// 4. 重载计数器
CPUTimer_reloadTimerCounter(CPUTIMER1_BASE);

// 5. 配置为连续模式
CPUTimer_setEmulationMode(CPUTIMER1_BASE,
CPUTIMER_EMULATIONMODE_RUNFREE);

// 6. 使能定时器中断
CPUTimer_enableInterrupt(CPUTIMER1_BASE);

// 7. 注册中断服务函数
Interrupt_register(INT_TIMER1, &cpuTimer1ISR);
Interrupt_enable(INT_TIMER1);

// 8. 启动定时器
CPUTimer_startTimer(CPUTIMER1_BASE);
}

定时周期计算

公式

1
定时周期(秒) = (PRD + 1) × (TDDR + 1) / SYSCLK

示例计算

1
2
3
4
5
6
7
8
9
10
// SYSCLK = 100MHz
// 需要1ms定时

// 方法1: 不使用预分频
PRD = 100MHz × 0.001s - 1 = 100,000 - 1 = 99,999
TDDR = 0

// 方法2: 使用预分频
PRD = 10,000 - 1 = 9,999
TDDR = 10 - 1 = 9 // 预分频10

常用定时周期配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 1ms定时(SYSCLK = 100MHz)
CPUTimer_setPeriod(CPUTIMER1_BASE, 100000);
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);

// 10ms定时
CPUTimer_setPeriod(CPUTIMER1_BASE, 1000000);
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);

// 100ms定时
CPUTimer_setPeriod(CPUTIMER1_BASE, 10000000);
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);

// 1秒定时
CPUTimer_setPeriod(CPUTIMER1_BASE, 100000000);
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);

SysConfig配置定时器

步骤1: 添加CPU Timer

  1. 在SysConfig中找到 CPUTIMER
  2. 点击 “+” 添加定时器实例
  3. 选择 CPUTIMER1CPUTIMER2

步骤2: 配置参数

1
2
3
4
5
CPUTIMER Instance: CPUTIMER1
├── Timer Period (μs): 1000 (1ms)
├── Enable Interrupt: ✓
├── Emulation Mode: Run Free
└── Start Timer: ✓

步骤3: 配置中断

Interrupt 模块中:

1
2
├── Enable INT_TIMER1: ✓
└── Register Interrupt Handler: ✓

步骤4: 使用生成的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "board.h"

// 中断服务函数(需要手动实现)
__interrupt void INT_myCPUTIMER1_ISR(void)
{
GPIO_togglePin(31);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}

void main(void)
{
Device_init();
Device_initGPIO();

// 初始化中断
Interrupt_initModule();
Interrupt_initVectorTable();

// 调用SysConfig生成的初始化
Board_init();

EINT;
ERTM;

while(1)
{
// 主循环
}
}

实战示例

示例1: LED定时闪烁(1Hz)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "driverlib.h"
#include "device.h"

#define LED_GPIO 31

__interrupt void cpuTimer1ISR(void)
{
GPIO_togglePin(LED_GPIO);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}

void main(void)
{
Device_init();
Device_initGPIO();

// 配置LED
GPIO_setPadConfig(LED_GPIO, GPIO_PIN_TYPE_STD);
GPIO_setDirectionMode(LED_GPIO, GPIO_DIR_MODE_OUT);
GPIO_setPinConfig(GPIO_31_GPIO31);

// 初始化中断
Interrupt_initModule();
Interrupt_initVectorTable();

// 配置定时器1(500ms)
CPUTimer_stopTimer(CPUTIMER1_BASE);
CPUTimer_setPeriod(CPUTIMER1_BASE, 50000000); // 0.5秒
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
CPUTimer_reloadTimerCounter(CPUTIMER1_BASE);
CPUTimer_setEmulationMode(CPUTIMER1_BASE,
CPUTIMER_EMULATIONMODE_RUNFREE);
CPUTimer_enableInterrupt(CPUTIMER1_BASE);

// 注册中断
Interrupt_register(INT_TIMER1, &cpuTimer1ISR);
Interrupt_enable(INT_TIMER1);

// 启动定时器
CPUTimer_startTimer(CPUTIMER1_BASE);

EINT;
ERTM;

while(1)
{
// 主循环空闲
}
}

示例2: 多定时器应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "driverlib.h"
#include "device.h"

#define LED1_GPIO 0
#define LED2_GPIO 1

volatile uint32_t timer1_count = 0;
volatile uint32_t timer2_count = 0;

// 定时器1中断(100ms)
__interrupt void cpuTimer1ISR(void)
{
timer1_count++;
GPIO_togglePin(LED1_GPIO);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}

// 定时器2中断(500ms)
__interrupt void cpuTimer2ISR(void)
{
timer2_count++;
GPIO_togglePin(LED2_GPIO);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP13);
}

void main(void)
{
Device_init();
Device_initGPIO();

// 配置LED
GPIO_setPadConfig(LED1_GPIO, GPIO_PIN_TYPE_STD);
GPIO_setDirectionMode(LED1_GPIO, GPIO_DIR_MODE_OUT);
GPIO_setPinConfig(GPIO_0_GPIO0);

GPIO_setPadConfig(LED2_GPIO, GPIO_PIN_TYPE_STD);
GPIO_setDirectionMode(LED2_GPIO, GPIO_DIR_MODE_OUT);
GPIO_setPinConfig(GPIO_1_GPIO1);

// 初始化中断
Interrupt_initModule();
Interrupt_initVectorTable();

// 配置定时器1(100ms)
CPUTimer_stopTimer(CPUTIMER1_BASE);
CPUTimer_setPeriod(CPUTIMER1_BASE, 10000000);
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
CPUTimer_reloadTimerCounter(CPUTIMER1_BASE);
CPUTimer_setEmulationMode(CPUTIMER1_BASE,
CPUTIMER_EMULATIONMODE_RUNFREE);
CPUTimer_enableInterrupt(CPUTIMER1_BASE);
Interrupt_register(INT_TIMER1, &cpuTimer1ISR);
Interrupt_enable(INT_TIMER1);
CPUTimer_startTimer(CPUTIMER1_BASE);

// 配置定时器2(500ms)
CPUTimer_stopTimer(CPUTIMER2_BASE);
CPUTimer_setPeriod(CPUTIMER2_BASE, 50000000);
CPUTimer_setPreScaler(CPUTIMER2_BASE, 0);
CPUTimer_reloadTimerCounter(CPUTIMER2_BASE);
CPUTimer_setEmulationMode(CPUTIMER2_BASE,
CPUTIMER_EMULATIONMODE_RUNFREE);
CPUTimer_enableInterrupt(CPUTIMER2_BASE);
Interrupt_register(INT_TIMER2, &cpuTimer2ISR);
Interrupt_enable(INT_TIMER2);
CPUTimer_startTimer(CPUTIMER2_BASE);

EINT;
ERTM;

while(1)
{
// 可以在这里使用timer1_count和timer2_count
}
}

示例3: 定时器软件延时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "driverlib.h"
#include "device.h"

volatile uint32_t ms_counter = 0;

__interrupt void cpuTimer1ISR(void)
{
ms_counter++;
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}

void delay_ms(uint32_t ms)
{
uint32_t start = ms_counter;
while((ms_counter - start) < ms);
}

void main(void)
{
Device_init();
Device_initGPIO();

// 配置LED
GPIO_setPadConfig(31, GPIO_PIN_TYPE_STD);
GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
GPIO_setPinConfig(GPIO_31_GPIO31);

// 初始化中断
Interrupt_initModule();
Interrupt_initVectorTable();

// 配置定时器1(1ms)
CPUTimer_stopTimer(CPUTIMER1_BASE);
CPUTimer_setPeriod(CPUTIMER1_BASE, 100000); // 1ms
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
CPUTimer_reloadTimerCounter(CPUTIMER1_BASE);
CPUTimer_setEmulationMode(CPUTIMER1_BASE,
CPUTIMER_EMULATIONMODE_RUNFREE);
CPUTimer_enableInterrupt(CPUTIMER1_BASE);
Interrupt_register(INT_TIMER1, &cpuTimer1ISR);
Interrupt_enable(INT_TIMER1);
CPUTimer_startTimer(CPUTIMER1_BASE);

EINT;
ERTM;

while(1)
{
GPIO_writePin(31, 1);
delay_ms(500);
GPIO_writePin(31, 0);
delay_ms(500);
}
}

示例4: 定时器测量代码执行时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "driverlib.h"
#include "device.h"

void Timer_Init_ForProfiling(void)
{
// 配置定时器2用于性能测量(不使能中断)
CPUTimer_stopTimer(CPUTIMER2_BASE);
CPUTimer_setPeriod(CPUTIMER2_BASE, 0xFFFFFFFF); // 最大周期
CPUTimer_setPreScaler(CPUTIMER2_BASE, 0);
CPUTimer_reloadTimerCounter(CPUTIMER2_BASE);
CPUTimer_setEmulationMode(CPUTIMER2_BASE,
CPUTIMER_EMULATIONMODE_RUNFREE);
CPUTimer_startTimer(CPUTIMER2_BASE);
}

uint32_t Get_Timer_Ticks(void)
{
return CPUTimer_getTimerCount(CPUTIMER2_BASE);
}

float Get_Elapsed_Time_us(uint32_t start_ticks, uint32_t end_ticks)
{
uint32_t elapsed = start_ticks - end_ticks; // 递减计数器
return (float)elapsed / 100.0f; // 100MHz = 10ns per tick
}

void main(void)
{
Device_init();

Timer_Init_ForProfiling();

// 测量代码执行时间
uint32_t start = Get_Timer_Ticks();

// 要测量的代码
for(int i = 0; i < 1000; i++)
{
__asm(" NOP");
}

uint32_t end = Get_Timer_Ticks();

float time_us = Get_Elapsed_Time_us(start, end);
// time_us 包含执行时间(微秒)

while(1);
}

常见问题

1. 定时器不工作?

  • 检查是否调用了 CPUTimer_startTimer()
  • 检查中断是否正确注册和使能
  • 检查是否调用了 EINTERTM

2. 定时不准确?

  • 确认系统时钟频率(SYSCLK)
  • 检查周期计算是否正确
  • 考虑中断延迟和处理时间

3. 如何选择定时器?

  • Timer0: 保留给RTOS
  • Timer1/Timer2: 用户应用

4. 中断优先级?

  • Timer1: PIE Group 1.7
  • Timer2: PIE Group 13.14
  • 可通过PIE配置优先级

5. 调试时定时器停止?

1
2
3
// 设置为调试时继续运行
CPUTimer_setEmulationMode(CPUTIMER1_BASE,
CPUTIMER_EMULATIONMODE_RUNFREE);

下一步

学习完定时器后,继续学习:


参考资料

  • TMS320F28004x Technical Reference Manual - CPU Timers
  • C2000Ware DriverLib API Guide - CPUTimer Module
  • CPU Timer Example Code in C2000Ware