CPU定时器配置与使用
目录
- 定时器基础
- 与STM32对比
- 定时器寄存器
- 手动配置定时器
- SysConfig配置定时器
- 实战示例
定时器基础
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
| 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);
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; CpuTimer1Regs.TCR.bit.TRB = 1; CpuTimer1Regs.TCR.bit.TIE = 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) { GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; }
void Timer1_Init_Register(void) { EALLOW;
CpuTimer1Regs.TCR.bit.TSS = 1;
CpuTimer1Regs.TPR.bit.TDDR = 0; CpuTimer1Regs.TPR.bit.PSC = 0;
CpuTimer1Regs.PRD.all = 100000000 - 1;
CpuTimer1Regs.TCR.bit.TRB = 1;
CpuTimer1Regs.TCR.bit.FREE = 1; CpuTimer1Regs.TCR.bit.SOFT = 1;
CpuTimer1Regs.TCR.bit.TIE = 1;
PieVectTable.TIMER1_INT = &cpu_timer1_isr; PieCtrlRegs.PIEIER1.bit.INTx7 = 1; IER |= M_INT1;
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) { CPUTimer_stopTimer(CPUTIMER1_BASE);
CPUTimer_setPeriod(CPUTIMER1_BASE, 100000000);
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); }
|
定时周期计算
公式
1
| 定时周期(秒) = (PRD + 1) × (TDDR + 1) / SYSCLK
|
示例计算
1 2 3 4 5 6 7 8 9 10
|
PRD = 100MHz × 0.001s - 1 = 100,000 - 1 = 99,999 TDDR = 0
PRD = 10,000 - 1 = 9,999 TDDR = 10 - 1 = 9
|
常用定时周期配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| CPUTimer_setPeriod(CPUTIMER1_BASE, 100000); CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
CPUTimer_setPeriod(CPUTIMER1_BASE, 1000000); CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
CPUTimer_setPeriod(CPUTIMER1_BASE, 10000000); CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
CPUTimer_setPeriod(CPUTIMER1_BASE, 100000000); CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
|
SysConfig配置定时器
步骤1: 添加CPU Timer
- 在SysConfig中找到 CPUTIMER
- 点击 “+” 添加定时器实例
- 选择 CPUTIMER1 或 CPUTIMER2
步骤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();
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();
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();
CPUTimer_stopTimer(CPUTIMER1_BASE); CPUTimer_setPeriod(CPUTIMER1_BASE, 50000000); 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;
__interrupt void cpuTimer1ISR(void) { timer1_count++; GPIO_togglePin(LED1_GPIO); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1); }
__interrupt void cpuTimer2ISR(void) { timer2_count++; GPIO_togglePin(LED2_GPIO); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP13); }
void main(void) { Device_init(); Device_initGPIO();
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();
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);
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) { } }
|
示例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();
GPIO_setPadConfig(31, GPIO_PIN_TYPE_STD); GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); GPIO_setPinConfig(GPIO_31_GPIO31);
Interrupt_initModule(); Interrupt_initVectorTable();
CPUTimer_stopTimer(CPUTIMER1_BASE); CPUTimer_setPeriod(CPUTIMER1_BASE, 100000); 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) { 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; }
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);
while(1); }
|
常见问题
1. 定时器不工作?
- 检查是否调用了
CPUTimer_startTimer()
- 检查中断是否正确注册和使能
- 检查是否调用了
EINT 和 ERTM
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