


每来一个时钟信号,预定标计数器PSCH:PSC就会减1,直到减到0后,它将会重载TDDRH:TDDR的值,同时TIMH:TIM计数器将会减1。这个过程将重复进行,直到TIMH:TIM计数器的值减到0时,定时器将会产生一个中断信号,同时TIMH:TIM计数器重载周期寄存器PRDH:PRD的值。通过对定时器控制寄存器(TIMERxTCR)的设置,可以让定时器工作在不同的方式。
TIF:定时器中断标志位,写1时将清除中断标志;
TIE:定时器中断使能位,写1时使能中断,写0时不使能中断;
FREE.SOFT:定时器仿真模式选择位:00硬件停止;01软件停止;10自由运行;11自由运行
TRB:重载控制位,当写入1时,PSCH:PSC重载TDDRH:TDDR的值.TIMH:TIM重载PRDH:PRD的值;
TSS:定时器开启位,写入0,开启定时器;写入1,关闭定时器;
现在再分析定时器 0 的中断原理图(图 2.3.4):
CPU TIMER有三个,CPU-Timer 0 、CPU-Timer 1 、 Timer 2 。Timer 2 是给DSP/BIOS操作系统保留的, 如果用户没有使用操作系统,那么Timer 2可以当作普通的CPU定时器使用。这三个定时器的中断信号分别为TINT0, TINT1, TINT2,分别对应于中断向量INT1,INT13,INT14。如下图所示,可以看出,TINT0是经过PIE的,而TINT1/是不经过PIE的。
根据CPU向量表使能
IER |= M_INT13;//使能第 13组中断

PieVectTable结构体对应手册的PIE中断向量表
所以
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TIMER0_INT = &cpu_timer0_isr;//地址赋值给 TIMER0_INT 中断向量
EDIS;
// Step 6. 配置CPU定时器0中断发生时间
ConfigCpuTimer(&CpuTimer0, 200, 1000000);
//ConfigCpuTimer(&CpuTimer1, 200, 500000);
CpuTimer0Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0
IER |= M_INT1;// Enable CPU int1 which is connected to CPU-Timer 0
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;//定时器0在第一组第七个通道(PIE 通道映射)
每1S产生一次中断,当时钟不分频的时候定时时间
time =Freq*Peroid/SYSCLKOUT=200*1000000/200
总结
定时器是设置时间产生中断
取中断服务函数地址给相应PIE中断向量表;
初始化相应定时器
配置相应定时器(产生中断时间)
设置TSS bit = 0表示CPU计时器正在运行
IER寄存器设置(CPU中断向量表)
PIE通道设置
PIE组设置
#include "F28x_Project.h"
#include "F2837xD_Ipc_drivers.h"
void GPIO_Setup(void);
__interrupt void cpu_timer1_isr(void);
void main(void)
{
// Step 1. 初始化系统,锁相环,看门狗,外设时钟
InitSysCtrl();
#ifdef _STANDALONE
#ifdef _FLASH
// CPU2运行程序
IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
#else
// CPU2运行程序
IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_RAM);
#endif
#endif
// FALSH烧写配置
#ifdef _FLASH
InitFlash();
#endif
// Step 2. 初始化GPIO:
InitGpio();
GPIO_Setup();
// Step 3. 清除所有中断;初始化中断向量表;禁止CPU中断。
DINT;/*INTM置1,关中断*/
// 初始化PIE控制寄存器至默认状态,默认状态所有PIE中断被禁止;所有标志位被清除。
InitPieCtrl();
// 禁止所有CPU中断,清除CPU中断相关标志位。
IER = 0x0000;/*禁用CPU中断*/
IFR = 0x0000;/*清除CPU标志*/
// 初始化中断向量表,中断向量表就是采用指针指向中断服务程序入口地址
InitPieVectTable();
// Step 4. 在文件中找到ISR,并将函数地址赋值到对应PIE向量中断表
/*PieVectTable对应手册的中断向量表*/
EALLOW;
// PieVectTable.TIMER0_INT = &cpu_timer0_isr;//地址赋值给 TIMER0_INT 中断向量
PieVectTable.TIMER1_INT = &cpu_timer1_isr;//地址赋值给 TIMER0_INT 中断向量
EDIS;
// Step 5. 初始化CPU定时器0/1/2
InitCpuTimers();
// Step 6. 配置CPU定时器0中断发生时间
// 200MHz CPU Freq, 1 second Period (in uSeconds)选择定时器,CPU频率,定时器周期(单位us)
ConfigCpuTimer(&CpuTimer1, 200, 1000000);/*不分频:200*1000000/200*/
//ConfigCpuTimer(&CpuTimer1, 200, 500000);
CpuTimer1Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0表示CPU计时器正在运行。
// IER |= M_INT1;// Enable CPU int1 which is connected to CPU-Timer 0
IER |= M_INT13;
PieCtrlRegs.PIEIER1.bit.INTx5 = 1;//定时器0在第一组第七个通道(PIE 通道映射)
// Step 7.Enable global Interrupts and higher priority real-time debug events:
EINT; //使能全局中断
ERTM; // 使能全局中断实时调试
// Step 8.
while(1)
{
}
}
void GPIO_Setup()
{
GPIO_SetupPinMux(0, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(0, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(1, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(1, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(2, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(2, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(3, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(3, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(4, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(4, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(5, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(5, GPIO_OUTPUT, GPIO_PUSHPULL);
}
__interrupt void cpu_timer1_isr(void)
{
CpuTimer0.InterruptCount++;//中断次数
// Acknowledge承认 this interrupt to receive more interrupts from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;//中断响应标志位置 1,防止其他PIE组应答
GpioDataRegs.GPATOGGLE.bit.GPIO0 = 1;
GpioDataRegs.GPATOGGLE.bit.GPIO1 = 1;
GpioDataRegs.GPATOGGLE.bit.GPIO2 = 1;
GpioDataRegs.GPATOGGLE.bit.GPIO3 = 1;
GpioDataRegs.GPATOGGLE.bit.GPIO4 = 1;
GpioDataRegs.GPATOGGLE.bit.GPIO5 = 1;
}