关于DSP2812的Timer0定时器配置程序的质疑

关于DSP2812的Timer0定时器配置程序的质疑

个人觉得网上许多关于DSP的CPU定时器Timer 0的配置处有问题——程序中Timer->RegsAddr->PRD.all = temp;的temp应改为(temp-1)。

首先回顾一下定时器工作原理:大体的原理可以看下这个网页DSP2812之定时器

CPU频率到定时器Timer0的中断频率中间需经过2次分频,第一次由预分频器PSCH:PSC,其重载值为(TDDRH:TDDR);第二次由TIMH:TIM计数器,其重载值为(PRDH:PRD)。
先说正确的工作流程。①预分频器先载入TDDRH:TDDR的值,再对CPU脉冲计数,每通过一个脉冲,分频器减1,当计数到0后,产生一个信号通知TIMH:TIM计数器减1,而自身会在下一个脉冲来临时,将TDDRH:TDDR重新载入其中。②TIMH:TIM最开始载入PRDH:PRD,当收到预分频器发来的信号后,它也会减1,直至减为0。此时它会产生一个中断信号,并会在收到下一个预分频器发来的信号后,重载PRDH:PRD。具体的时序图如下(假设PRDH:PRD = TDDRH:TDDR = 2):
Timer0时序图
从时序图可以得知,每产生1个中断信号,共经过了(PRDH:PRD+1)×(TDDRH:TDDR +1)个SYSCLKOUT(即CPU脉冲)。
T = ( P R D H : P R D + 1 ) × T D D R H : T D D R + 1 150 × 10 6 ( s ) T=(PRDH:PRD+1)\times \frac{TDDRH:TDDR+1}{150}\times {{10}^{-6}}(\text{s})

如果要定时1s,则可令TDDRH:TDDR=0,PRDH:PRD=150×106-1。但在程序中ConfigCpuTimer(&CpuTimer0, 150, 1000000);//temp=150 000000.
导致T=1+1/150000000s。虽然微乎其微,但如果换成其他设置方式就会有明显的误差。
我之前怀疑上述对T的计算公式是错的,PRDH:PRD不应该再加1。为此我做了如下验证,令TDDRH:TDDR=50000-1,PRDH:PRD=1,如果有加1,则T=1/1500s,否则T=1/3000s.之后在Timer0的中断中,让SCIRA和SCITA的引脚每隔3000个中断变换一次电平。结果在示波器可以明显看出高低电平分别持续2s,说明PRDH:PRD应该加1。
所以在常见的TDDRH:TDDR=0,ConfigCpuTimer(&CpuTimer0, 150, Y);的配置方式中, ConfigCpuTimer函数里的temp应减1,且计算公式变为
T = ( P R D H : P R D ) × T D D R H : T D D R + 1 150 × 10 6 ( s ) T=(PRDH:PRD)\times \frac{TDDRH:TDDR+1}{150}\times {{10}^{-6}}(\text{s})

部分代码如下

ConfigCpuTimer(&CpuTimer0, 1,1);
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period){

Timer->RegsAddr->TPR.all = 0x4f;
Timer->RegsAddr->TPRH.all = 0xc3;

}

interrupt void TINT0_ISR(void) // CPU-Timer0中断函数
{
CpuTimer0.InterruptCount++;
if(CpuTimer0.InterruptCount<=3000)
{
GpioDataRegs.GPFCLEAR.bit.GPIOF5=1;//低电平
GpioDataRegs.GPFCLEAR.bit.GPIOF4=1;
}
if(CpuTimer0.InterruptCount>3000)
{
GpioDataRegs.GPFSET.bit.GPIOF5=1;//高电平
GpioDataRegs.GPFSET.bit.GPIOF4=1;
}
if(CpuTimer0.InterruptCount==6000) CpuTimer0.InterruptCount=0;
CpuTimer0Regs.TCR.bit.TIF=1; //清除定时器中断标志位
PieCtrl.PIEACK.bit.ACK1=1; //响应同组其他中断
EINT; //开全局中断
}

void InitGpio(void)
{
EALLOW;
GpioMuxRegs.GPFMUX.bit.SCIRXDA_GPIOF5=0;//SCIAR设为GPIO口
GpioMuxRegs.GPFMUX.bit.SCITXDA_GPIOF4=0;//SCIAT设为GPIO口
GpioMuxRegs.GPFDIR.bit.GPIOF5=1;//SCIAR设为输出口
GpioMuxRegs.GPFDIR.bit.GPIOF4=1;
GpioDataRegs.GPFCLEAR.bit.GPIOF5=1;//低电平
GpioDataRegs.GPFCLEAR.bit.GPIOF4=1;
EDIS;
}

猜你喜欢

转载自blog.csdn.net/speedbluey/article/details/89633954