打印

“简简单单DSP”系列学习活动——TIME0学习

[复制链接]
594|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Roses|  楼主 | 2017-9-6 11:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
TIME0学习

2812除了通用定时器GP TIMER(事件管理器里面的定时器)还有TIME0 TIME 1 TIME2 三个CPU定时器,但是TIME1 TIME2保留给时时操作系统(例如DSP_BIOS)使用,只有TIME0开放给用户。
下面介绍定时器0的工作过程:
1、TIME0是一个32位的定时器,即有一个32位的计数器,这个32位的计数器是有两个16为计数器组成,分别是低16位TIM和高16为TIMH(一般这么写TIMH:TIM),32位的计数器递减计数到0,产生定时器0中断。有一个32位的定时器周期寄存器,也是有俩个16的组成,低16位TIMER0PRD和高16位TIMER0PRDH(PRDH:PRD)。其实就和影子寄存器是一样的。32位的定时计数器是不能写的,它是靠32位的定时器周期寄存器装载计数值的。有两种情况可以装载,一种是32位的定时计数器递减到0,还有一种是控制寄存器TIMX0TCR的第六位TRB决定,TRB=1,自动装载。在初始化定时器的时候不知道你的计数器初值是多少,所以在开启定时器前(TIMX0TCR的第五位TSS决定,TSS=1停止),先把32位的定时器周期寄存器赋值,再使TRB=1,这样就把初始值装载到32位的定时计数器里面。
2、要计算定时器0定时的时间,只知道32位的定时计数器的计数值是多少还不行,还要知道记一个数的时间,这个由系统时钟SYSCLKOUT(PLL倍频后的)和俩个16位的定时器预定标计数器决定。预定标计数器和32位的定时器计数器一样,也是有一个和影子寄存器差不多的寄存器,TIMER0TPR和TIMER0TPRH俩个寄存器都是16位的,但是每个寄存器有俩个八位的不一样的功能的东西组成,高八位是预定标计数器(PSC),低八位是像影子寄存器一样的(TDDR),两个寄存器的话就是(PSCH:PSC)和(TDDRH:TDDR)。预定标计数器的功能就相当于把时钟分频。每一个SYSCLKOUT时钟,预定标计数器就会减1,直到预定标计数器等于0后的第一个时钟(TIMH:TIM)才会减一。(TDDRH:TDDR)就像PSCH:PSC的影子寄存器一样,PSCH:PSC递减到0后的第一个SYSCLKOUT时钟,TDDRH:TDDR的值自动装载到PSCH:PSC里面,即每TDDRH:TDDR+1个SYSCLKOUT时钟,TIMH:TIM才会减1.PSCH:PSC和TIMH:TIM一样不能写,只能是影子寄存器装载,它的装载有两种方法,和TIMH:TIM得那两种装载方法一样。所以在初始化的时候,也是
在开启定时器前(TIMX0TCR的第五位TSS决定,TSS=1停止),先把TDDRH:TDDR赋值,再使TRB=1,这样就把初始值装载到PSCH:PSC里面。
3、定时器0C代码分析
在库函数DSP281x_CpuTimer.c中,包括初始化函数InitCpuTimers()和配置函数ConfigCpuTimer()。在主函数中先调用InitCpuTimers()对CPU定时器进行初始化,然后调用ConfigCpuTimer()对所需要的定时器进行周期等参数的设置。
4、InitCpuTimers()函数代码
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;

// Reload all counter register with period value:

CpuTimer0Regs.TCR.bit.TRB = 1;

// Reset interrupt counters:

CpuTimer0.InterruptCount = 0;
}
5、ConfigCpuTimer()代码
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)
{

Uint32
temp;
        

// Initialize timer period:


Timer->CPUFreqInMHz = Freq;

Timer->;PeriodInUSec = Period;

temp = (long) (Freq * Period);

Timer->RegsAddr->;PRD.all = temp;

/*temp周期寄存器的值*/

// Set pre-scale counter to divide by 1 (SYSCLKOUT):分频设置      

Timer->RegsAddr->TPR.all
= 0;

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 = 1;

Timer->RegsAddr->TCR.bit.FREE = 1;
// Timer Free Run

Timer->RegsAddr->TCR.bit.TIE = 1;
// 0 = Disable/ 1 = Enable Timer Interrupt
        

// Reset interrupt counter:

Timer->InterruptCount = 0;
}
这个代码是配置定时器的周期的,即定时的时间,它的输入参数有三个:
truct CPUTIMER_VARS *Timer:选择哪个定时器,即是选择TIME0还是TIME1、TIME2.如果选择TIME0的话应该在调用这个还是的时候的实参是&CpuTimer0

float Freq:这个是你的系统频率,即SYSCLKOUT的值
float Period:这个是定时计数器的周期寄存器的值,即影子寄存器的值,也就是记多少个数。
这个默认状态下分频倍数是1,也就是 Period的就是定时器定时的时间,但是单位是微秒。
6、在主函数中怎么调用
以TIME0,100M的系统频率,定时1S为例:

ConfigCpuTimer(&CpuTimer0, 100, 1000000)
配置完之后,还要开计数

StartCpuTimer0();//启动定时器0

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

709

主题

1023

帖子

7

粉丝