DSP

28335的CPU定时器解析

2019-07-13 11:37发布

声明:本文的主要内容来自TI公司的参考指南《TMS320x2833x, 2823x System Control and Interrupts Reference Guide》,附带一小部分本人对该模块的理解,水平有限,仅供参考.

一、简介:

28335的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的。

二、工作原理

定时器的结构框图如下:简单描述如下:在SYSCLKOUT时钟信号的驱动下,当预分配计数器(PSCH:PSC)的值大于0的时候,每来一个脉冲,预分配计数器的值就减1,当预分配计数器中的值减到0的时候,自动将(TDDRH:TDDR)中的值装载到预分配计数器中,同时,产生一个脉冲输出,在这个脉冲的作用下,32位计数器(TIMH:TIM)中的值也会减1,当减到0的时候,自动将32位周期寄存器(PRDH:PRD)中的值装载到32位计数器(TIMH:TIM)中,同时产生一个中断信号。

三、相关寄存器

每个定时器寄存器类似,以定时器0为例总结一下就是下图:比较怪异的是PSCH和PSC并没有放到一个16位寄存器中,而是分别拆开放到了两个寄存器中;TDDRH和TDDR同理。但是芯片厂家就是这么设计的,你只管用就好了。下面把TI对各个寄存器的介绍粘贴了过来,每个寄存器的功能在原理分析的时候都讲的差不多了,这里就不一一分析了单独讲一下控制寄存器吧:TIF(中断标志位):当计数器减到0的时候,该位自动置1,写1清零TIE(中断使能位):写0禁止,写1使能FREE、SOFT:这两位是仿真模式位,决定了在高级语言仿真中遇到断电时定时器的状态。如果FREE位为1,则在遇到断点的时候,定时器继续运行(自由运行)。在这种情况下,不管SOFT位的状态;若FREE为0,当SOFT是0则立马停止计数;当SOFT是1则当(TIMH:TIM)减到0的时候停止计数。TRB:重装位,写一的时候将PRDH:PRD的值装载到TIMH:TIM,将TDDRH:TDDR的值装载到PSCH:PSC。读该位时,总是0TSS:(停止状态位) :写0开始计数,置1停止计数。当复位时,该位为0,立即开始计数。

四、CPU定时器的使用

首先解读一下官方的定时器配置函数// // 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 temp; // // Initialize timer period // Timer->CPUFreqInMHz = Freq;//这个参数其实是SYSCLKOUT的频率,以MHz为单位,通常为150 Timer->PeriodInUSec = Period; temp = (long) (Freq * Period); Timer->RegsAddr->PRD.all = temp;//把TEMP的值赋值到周期寄存器 // // Set pre-scale counter to divide by 1 (SYSCLKOUT)不分频,SYSCLKOUT直接驱动32位计数器(TIMH:TIM) // Timer->RegsAddr->TPR.all = 0; Timer->RegsAddr->TPRH.all = 0; // // Initialize timer control register // // // 1 = Stop timer, 0 = Start/Restart Timer // Timer->RegsAddr->TCR.bit.TSS = 1;//停止定时器 Timer->RegsAddr->TCR.bit.TRB = 1; // 1 = reload timer 重装 Timer->RegsAddr->TCR.bit.SOFT = 1; Timer->RegsAddr->TCR.bit.FREE = 1; // Timer Free Run 自由模式 // // 0 = Disable/ 1 = Enable Timer Interrupt // Timer->RegsAddr->TCR.bit.TIE = 1; //开启定时器中断 // // Reset interrupt counter // Timer->InterruptCount = 0; }
通过以上分析,可以看出SYSCLKOUT没有经过预分频(分频系数为1)直接驱动计数器。 所以如下配置就是每1S产生一次中断,因为当时钟不分频的时候定时时间time =Freq*Peroid/SYSCLKOUT,这个就不多解释了。  ConfigCpuTimer(&CpuTimer0, 150, 1000000);


配置完了定时器之后,需要配置PIE中断,写定时器中断服务函数,开CPU级中断,最后开始计数就可以了。 具体的可以参考官方的历程。