CPU定时器的计数复位时,计数寄存器TIMH:TIM加载周期寄存器PRDH:PRD所设定的值,经历一个计数器时钟后,TIMH:TIM内的值就减1,一直减到0,这时产生定时器周期中断事件,并重新装载PRDH:PRD所设定的值,重新开始计数。至于每隔多少时间,计数寄存器TIMH:TIM的值才会减1则由预分频寄存器TPRH:TPR来决定。
TPRH和TPR这两个寄存器由两部分组成,高8位为定时器预分频计数器PSC,低8位是定时器分频TDDR。也即是说,TPRH是由PSCH和TDDRH构成,而TDDR由PSC和TDDR构成。且其工作的原理与51系列单片机定时器计数器类似,复位时,PSCH:PSC加载TDDRH:TDDR所设定的值,然后经过一个CPU时钟,PSCH:PSC的值减1,当PSCH:PSC的值减到0时,会再次装载TDDRH:TDDR所设定的值,并且产生一个计数器时钟,TIMH:TIM减1。CPU定时器0、1、2配置和控制寄存器如表4-1所示
定时器定时时间的公式计算
以上寄存器测值在配置函数ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)中设置。形参Timer为第几位定时器,Freq为定时频率,Period为计时周期。
假若Freq为15,Period为1000000,则时间t = 1*15*1000000/150M = 0.1s (系统时钟频率为150M)。不过这个算式的成立是有条件的,这个条件就是以下两条语句:
Timer->RegsAddr->TPR.all = 0
Timer->RegsAddr->TPRH.all = 0
上文曾提及,定时器的计数时钟是有预分频寄存器TPRH:TPR决定的。CpuTimerxRegs.TPR.all = 0, CpuTimerxRegs.TPRH.all = 0这两句话决定了1个时钟源周期为定时器的时钟周期(即一个SYSCLKOUT,TIMH:TIM减1),若CpuTimerxRegs.TPR.all = y,CpuTimerxRegs.TPRH.all = 0,则计y+1个时钟周期为定时器的时钟周期。X表示0,1,2中的任意值(任意定时器)。
因此,真正的定时时间为:time =TPRH:TPR/SYSCLKOUT*Freq*Peroid。只有当TPRH:TPR=0时,SYSCLKOUT直接作为TIMH:TIM的时钟周期,time =Freq*Peroid/SYSCLKOUT。另外,在定时器配置函数中,
Timer->RegsAddr->TCR.bit.TSS = 1 表示停止定时器 ;
Timer->RegsAddr->TCR.bit.TRB = 1 表示重装定时器;
Timer->RegsAddr->TCR.bit.FREE = 1 表示定时器自由运行;
Timer->RegsAddr->TCR.bit.TIE = 1 表示使能定时器中断。
如果要利用定时器产生一定周期的时间中断,别忘了在主函数中设置响应的中断向量即可。
TI官方头文件DSP2833x_CpuTimers.h程序如下:
// TI File $Revision: /main/4 $
// Checkin $Date: March 20, 2007 15:33:42 $
//###########################################################################
//
// FILE: DSP2833x_CpuTimers.h
//
// TITLE: DSP2833x CPU 32-bit 定时器寄存器定义.
//
// NOTES: CpuTimer1 and CpuTimer2 are reserved for use with DSP BIOS and
// other realtime operating systems.
//
// Do not use these two timers in your application if you ever plan
// on integrating DSP-BIOS or another realtime OS.
//
// For this reason, comment out the code to manipulate these two timers
// if using DSP-BIOS or another realtime OS.
//
//###########################################################################
// $TI Release: DSP2833x/DSP2823x C/C++ Header Files V1.31 $
// $Release Date: August 4, 2009 $
//###########################################################################
#ifndef DSP2833x_CPU_TIMERS_H
#define DSP2833x_CPU_TIMERS_H
#ifdef __cplusplus
extern "C" {
#endif
//---------------------------------------------------------------------------
// CPU 定时器寄存器位定义:
//
//
// TCR: 定时器控制寄存器定义:
struct TCR_BITS { // bits 描述
Uint16 rsvd1:4; // 3:0 保留
Uint16 TSS:1; // 4 定时器启动/停止
Uint16 TRB:1; // 5 定时器重载
Uint16 rsvd2:4; // 9:6 保留
Uint16 SOFT:1; // 10 运行模式
Uint16 FREE:1; // 11 运行模式
Uint16 rsvd3:2; // 12:13 保留
Uint16 TIE:1; // 14 中断使能
Uint16 TIF:1; // 15 中断标志位
};
//定时器控制寄存器
union TCR_REG {
Uint16 all;
struct TCR_BITS bit; //定时器控制寄存器定义
};
// TPR: 预分频低电平寄存器定义:
struct TPR_BITS { // bits 描述
Uint16 TDDR:8; // 7:0 定时计数寄存器
Uint16 PSC:8; // 15:8 预分频计数器低位
};
//预分频低电平寄存器
union TPR_REG {
Uint16 all;
struct TPR_BITS bit; //预分频低电平寄存器定义
};
// TPRH: 预分频高电平寄存器定义:
struct TPRH_BITS { // bits 描述
Uint16 TDDRH:8; // 7:0 定时计数器寄存器
Uint16 PSCH:8; // 15:8 预分频计数器高位
};
//预分频寄存器高电平寄存器
union TPRH_REG {
Uint16 all;
struct TPRH_BITS bit; //预分频高电平寄存器定义
};
// TIM, TIMH: 计数器寄存器定义:
struct TIM_REG {
Uint16 LSW; //低位
Uint16 MSW; //高位
};
//计数器寄存器
union TIM_GROUP {
Uint32 all;
struct TIM_REG half; //计数器寄存器定义
};
// PRD, PRDH: 周期寄存器定义:
struct PRD_REG {
Uint16 LSW; //低位
Uint16 MSW; //高位
};
//周期寄存器
union PRD_GROUP {
Uint32 all;
struct PRD_REG half; //周期寄存器定义
};
//---------------------------------------------------------------------------
// CPU 定时器寄存器文件:
//
struct CPUTIMER_REGS {
union TIM_GROUP TIM; // 计数器寄存器
union PRD_GROUP PRD; // 周期寄存器
union TCR_REG TCR; // 定时器控制寄存器
Uint16 rsvd1; // 保留
union TPR_REG TPR; // 预分频低电平寄存器
union TPRH_REG TPRH; // 预分频高电平寄存器
};
//---------------------------------------------------------------------------
// CPU 定时器支持的变量:
//
struct CPUTIMER_VARS {
volatile struct CPUTIMER_REGS *RegsAddr; //定时器结构体
Uint32 InterruptCount; //中断计数器
float CPUFreqInMHz; //频率
float PeriodInUSec; //周期
};
//---------------------------------------------------------------------------
// 函数原型和外部定义:
//
extern void InitCpuTimers(void); //初始化定时器
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period);
//定时器配置函数
extern volatile struct CPUTIMER_REGS CpuTimer0Regs;
extern struct CPUTIMER_VARS CpuTimer0;
//CpuTimer 1和CpuTimer2预留给DSP BIOS和其他操作系统 如果使用DSP BIOS或其他操作系统注释掉CpuTimer1 CpuTimer2
extern volatile struct CPUTIMER_REGS CpuTimer1Regs;
extern volatile struct CPUTIMER_REGS CpuTimer2Regs;
extern struct CPUTIMER_VARS CpuTimer1;
extern struct CPUTIMER_VARS CpuTimer2;
//---------------------------------------------------------------------------
// 实用定时器操作:
//
// 启动定时器0:
#define StartCpuTimer0() CpuTimer0Regs.TCR.bit.TSS = 0
// 停止定时器0:
#define StopCpuTimer0() CpuTimer0Regs.TCR.bit.TSS = 1
// 重载定时器周期值:
#define ReloadCpuTimer0() CpuTimer0Regs.TCR.bit.TRB = 1
// 读取定时器0计数器寄存器的值:
#define ReadCpuTimer0Counter() CpuTimer0Regs.TIM.all
// 读取定时器0周期寄存器的值:
#define ReadCpuTimer0Period() CpuTimer0Regs.PRD.all
// CpuTimer 1 and CpuTimer2 are reserved for DSP BIOS & other RTOS
// Do not use these two timers if you ever plan on integrating
// DSP-BIOS or another realtime OS.
//
// For this reason, comment out the code to manipulate these two timers
// if using DSP-BIOS or another realtime OS.
// 启动定时器1、2:
#define StartCpuTimer1() CpuTimer1Regs.TCR.bit.TSS = 0
#define StartCpuTimer2() CpuTimer2Regs.TCR.bit.TSS = 0
// 停止定时器1、2:
#define StopCpuTimer1() CpuTimer1Regs.TCR.bit.TSS = 1
#define StopCpuTimer2() CpuTimer2Regs.TCR.bit.TSS = 1
// 重载定时器周期值1、2:
#define ReloadCpuTimer1() CpuTimer1Regs.TCR.bit.TRB = 1
#define ReloadCpuTimer2() CpuTimer2Regs.TCR.bit.TRB = 1
// 读取定时器1、2计数器寄存器的值:
#define ReadCpuTimer1Counter() CpuTimer1Regs.TIM.all
#define ReadCpuTimer2Counter() CpuTimer2Regs.TIM.all
// 读取定时器1、2周期寄存器的值:
#define ReadCpuTimer1Period() CpuTimer1Regs.PRD.all
#define ReadCpuTimer2Period() CpuTimer2Regs.PRD.all
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif // end of DSP2833x_CPU_TIMERS_H definition
//===========================================================================
// End of file.
//===========================================================================
其中的实例程序如下:
// TI File $Revision: /main/4 $
// Checkin $Date: July 9, 2009 10:51:59 $
//###########################################################################
//
// FILE: DSP2833x_CpuTimers.c
//
// TITLE: CPU 32-bit Timers 初始化 & 支持功能.
//
// NOTES: CpuTimer2 is reserved for use with DSP BIOS and
// other realtime operating systems.
//
// Do not use these this timer in your application if you ever plan
// on integrating DSP-BIOS or another realtime OS.
//
//###########################################################################
// $TI Release: DSP2833x/DSP2823x C/C++ Header Files V1.31 $
// $Release Date: August 4, 2009 $
//###########################################################################
#include "DSP2833x_Device.h" // Headerfile Include File
#include "DSP2833x_Examples.h" // Examples Include File
struct CPUTIMER_VARS CpuTimer0;
// 当使用DSP BIOS和其他操作系统,CPU定时器2的代码注释掉
struct CPUTIMER_VARS CpuTimer1;
struct CPUTIMER_VARS CpuTimer2;
//---------------------------------------------------------------------------
// InitCpuTimers:
//---------------------------------------------------------------------------
// 改函数将三个CPU的定时器初始化到一个已知状态.
//
void InitCpuTimers(void) //初始化定时器寄存器
{
// CPU 定时器 0
// 寄存器地址指针和各自计时器初始化:
CpuTimer0.RegsAddr = &CpuTimer0Regs;
// 定时器周期寄存器最大值初始化:
CpuTimer0Regs.PRD.all = 0xFFFFFFFF;
// 预分频寄存器初始化为1 (SYSCLKOUT):
CpuTimer0Regs.TPR.all = 0;
CpuTimer0Regs.TPRH.all = 0;
// 确保定时器0停止:
CpuTimer0Regs.TCR.bit.TSS = 1;
// 重加载计数器周期值:
CpuTimer0Regs.TCR.bit.TRB = 1;
// 复位中断计时器:
CpuTimer0.InterruptCount = 0;
// CpuTimer2 is reserved for DSP BIOS & other RTOS
// Do not use this timer if you ever plan on integrating
// DSP-BIOS or another realtime OS.
// 寄存器地址指针和各自计时器初始化:
CpuTimer1.RegsAddr = &CpuTimer1Regs;
CpuTimer2.RegsAddr = &CpuTimer2Regs;
// 定时器1、2周期最大值初始化:
CpuTimer1Regs.PRD.all = 0xFFFFFFFF;
CpuTimer2Regs.PRD.all = 0xFFFFFFFF;
// 确保定时器停止:
CpuTimer1Regs.TCR.bit.TSS = 1;
CpuTimer2Regs.TCR.bit.TSS = 1;
// 重加载计数器周期值:
CpuTimer1Regs.TCR.bit.TRB = 1;
CpuTimer2Regs.TCR.bit.TRB = 1;
// 复位中断计时器:
CpuTimer1.InterruptCount = 0;
CpuTimer2.InterruptCount = 0;
}
//---------------------------------------------------------------------------
// 配置CpuTimer:
//---------------------------------------------------------------------------
// 这个函数初始化,选择定时器,周期参数指定“频率”和“时间”参数.
// 频率为MHz,时间为us级,定时器配置后保存在停止状态
//
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)
{
Uint32 temp;
// 定时器周期参数初始化:
Timer->CPUFreqInMHz = Freq; //频率
Timer->PeriodInUSec = Period; //周期
temp = (long) (Freq * Period);
Timer->RegsAddr->PRD.all = temp; //周期寄存器设定值为timer
// 预分频寄存器初始化为1 (SYSCLKOUT):
Timer->RegsAddr->TPR.all = 0;
Timer->RegsAddr->TPRH.all = 0;
// 定时器控制寄存器初始化:
Timer->RegsAddr->TCR.bit.TSS = 1; // 1 = 停止定时器, 0 = 启动/重启定时器
Timer->RegsAddr->TCR.bit.TRB = 1; // 1 = 重载计时器
Timer->RegsAddr->TCR.bit.SOFT = 1; // 定时器自由运行
Timer->RegsAddr->TCR.bit.FREE = 1; // 定时器自由运行
Timer->RegsAddr->TCR.bit.TIE = 1; // 0 = 禁止/ 1 = 定时器中断使能
// 复位中断计数器:
Timer->InterruptCount = 0;
}
//===========================================================================
// End of file.
//===========================================================================
参考资料
【TI博客大赛】TI C2000 TMS320F28335定时器配置简介
2.3 关于ConfigCpuTimer()函数的说明
百度文库-ConfigCpuTimer()函数