一、定时器原理分析
28335有三个定时器定时器0,定时器1,定时器2。其中定时器1,定时器2, 是为操作系统 DSP/BIOS 保留的,当未移植操作系统时,可用来做普通的 定时器。这三个定时器的中断信号分别为 TINT0, TINT1, TINT2,分别对应于中 断向量 INT1,INT13,INT14。定时器的功能如下图所示:
定时器信号来源如图3所示,系统时钟SYSCLKOUT与计数器产生的时钟TIMclk,由此可得定时器定时来源。
二、定时器配置
1、寄存器
定时器控制寄存器 TIMERxTCR,图2中的TCR。
定时器预定标寄存器:PSC、TDDR
定时器计数器TIM
定时器周期寄存器PRD
代码
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
// Prototype statements for functions found within this file.
interrupt void cpu_timer0_isr(void);
void InitLEDGPIO(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; //IO引脚功能
GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; //方向为输出
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO1 = 1;
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO2 = 1;
GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO3 = 1;
EDIS;
}
void LEDOverTurn(void)
{
GpioDataRegs.GPATOGGLE.bit.GPIO0 = 1; //翻转电平
GpioDataRegs.GPATOGGLE.bit.GPIO1 = 1;
GpioDataRegs.GPATOGGLE.bit.GPIO2 = 1;
GpioDataRegs.GPATOGGLE.bit.GPIO3 = 1;
}
void main(void)
{
InitSysCtrl();
// Disable CPU interrupts
DINT;
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2806x_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2806x_DefaultIsr.c.
// This function is found in F2806x_PieVect.c.
InitPieVectTable();
InitLEDGPIO();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TINT0 = &cpu_timer0_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
// Step 4. Initialize the Device Peripheral. This function can be
// found in F2806x_CpuTimers.c
InitCpuTimers(); // For this example, only initialize the Cpu Timers
// Configure CPU-Timer 0, 1, and 2 to interrupt every second:
// 80MHz CPU Freq, 1 second Period (in uSeconds)
ConfigCpuTimer(&CpuTimer0, 90, 1000000);
// To ensure precise timing, use write-only instructions to write to the entire register. Therefore, if any
// of the configuration bits are changed in ConfigCpuTimer and InitCpuTimers (in F2806x_CpuTimers.h), the
// below settings must also be updated.
CpuTimer0Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0 启动定时器,启动中断
// Step 5. User specific code, enable interrupts:
// Enable CPU int1 which is connected to CPU-Timer 0, CPU int13
// which is connected to CPU-Timer 1, and CPU int 14, which is connected
// to CPU-Timer 2:
IER |= M_INT1;
// Enable TINT0 in the PIE: Group 1 interrupt 7
PieCtrlRegs.PIEIER1.bit.INTx7 = 1; //定时器0中断被连接到INT1.7
// Enable global Interrupts and higher priority real-time debug events: 打开CPU中断
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
// Step 6. IDLE loop. Just sit and loop forever (optional):
for(;;);
}
interrupt void cpu_timer0_isr(void)
{
CpuTimer0.InterruptCount++;
// Acknowledge this interrupt to receive more interrupts from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; //中断已经接收,清除挂起位
LEDOverTurn();
}
定时器配置代码
//---------------------------------------------------------------------------
// InitCpuTimers:
//---------------------------------------------------------------------------
// This function initializes all three CPU timers to a known state.
//
void InitCpuTimers(void)
{
// CPU Timer 0
// Initialize address pointers to respective timer registers:
CpuTimer0.RegsAddr = &CpuTimer0Regs;
// Initialize timer period to maximum:
CpuTimer0Regs.PRD.all = 0xFFFFFFFF; //周期寄存器
// Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
CpuTimer0Regs.TPR.all = 0; //预分频寄存器
CpuTimer0Regs.TPRH.all = 0;
// Make sure timer is stopped:
CpuTimer0Regs.TCR.bit.TSS = 1; //1 停止定时器 0 启动定时器
// Reload all counter register with period value:
CpuTimer0Regs.TCR.bit.TRB = 1; //1 装载周期和预分频
// Reset interrupt counters:
//CpuTimer0.InterruptCount = 0;
// Initialize address pointers to respective timer registers:
CpuTimer1.RegsAddr = &CpuTimer1Regs;
CpuTimer2.RegsAddr = &CpuTimer2Regs;
// Initialize timer period to maximum:
CpuTimer1Regs.PRD.all = 0xFFFFFFFF;
CpuTimer2Regs.PRD.all = 0xFFFFFFFF;
// Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
CpuTimer1Regs.TPR.all = 0;
CpuTimer1Regs.TPRH.all = 0;
CpuTimer2Regs.TPR.all = 0;
CpuTimer2Regs.TPRH.all = 0;
// Make sure timers are stopped:
CpuTimer1Regs.TCR.bit.TSS = 1;
CpuTimer2Regs.TCR.bit.TSS = 1;
// Reload all counter register with period value:
CpuTimer1Regs.TCR.bit.TRB = 1;
CpuTimer2Regs.TCR.bit.TRB = 1;
// Reset interrupt counters:
//CpuTimer1.InterruptCount = 0;
//CpuTimer2.InterruptCount = 0;
}
//---------------------------------------------------------------------------
// ConfigCpuTimer:
//---------------------------------------------------------------------------
// This function initializes the selected timer to the period specified
// by the "Freq" and "Period" parameters. The "Freq" is entered as "MHz"
// and the period in "uSeconds". The timer is held in the stopped state
// after configuration.
//
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)
{
Uint32 PeriodInClocks;
// Initialize timer period:
Timer->CPUFreqInMHz = Freq; //表示CPU主频多少MHz
Timer->PeriodInUSec = Period; //定时器溢出周期多少us
PeriodInClocks = (long) (Freq * Period);
Timer->RegsAddr->PRD.all = PeriodInClocks - 1; // Counter decrements PRD+1 times each period 设置周期值
// Set pre-scale counter to divide by 1 (SYSCLKOUT):
Timer->RegsAddr->TPR.all = 0; //预分频值1
Timer->RegsAddr->TPRH.all = 0;
// Initialize timer control register:
Timer->RegsAddr->TCR.bit.TSS = 1; // 1 = Stop timer, 0 = Start/Restart Timer 停止定时器
Timer->RegsAddr->TCR.bit.TRB = 1; // 1 = reload timer 重载定时器
Timer->RegsAddr->TCR.bit.SOFT = 0;
Timer->RegsAddr->TCR.bit.FREE = 0; // Timer Free Run Disabled 遇到软件断点停止计时
Timer->RegsAddr->TCR.bit.TIE = 1; // 0 = Disable/ 1 = Enable Timer Interrupt 打开中断
// Reset interrupt counter:
Timer->InterruptCount = 0;
}