DSP28335笔记 —— 定时器
相比于STM32,DSP28335的定时器好像真的简单了好多,从定时器个数来讲只有3个,时钟源只能是系统时钟,而且计数方向也只有向下计数。
单纯且善良的定时器,好不让人心生喜爱。
定时器介绍
TMS320F28335 的 CPU Time 有三个,分别为 Timer0,Timer1,Timer2,其中 Timer1和Timer2 是为操作系统 DSP/BIOS 保留的,当未移植操作系统时,可用来做普通的定时器。这三个定时器的中断信号分别为 TINT0, TINT1, TINT2,分别对应于中断向量 INT1,INT13,INT14。
定时器的功能如下图所示:
由图可以看出,TCR为0时定时器才可以开始工作;
TDDR(低位)和TDDRH(高位)组成16位寄存器,对系统时钟进行分频;
PRD(低位)和PRDH(高位)组成32位寄存器,储存每次重装载的值,相当于定时周期;
TIM(低位)和TIMH(高位)组成32位寄存器,用作定时器的当前计时的记录值。
对比STM32的时钟,DSP28335的定时器真的更单纯,DSP28335的定时器只能向下计数,而且不和PWM和CAP功能混在一起让人心烦。
中断方面,定时器0的中断信号通过PIE模块进入内核,定时器1、定时器2的中断信号则直接进入内核。
相关寄存器
三个定时器的基本设定是相同,具体了解其中一组即可
大部分寄存器都是写入一个数值,只需要注意TCR寄存器各个位的功能:
定时器代码实验
首先完成主函数框架:
void main()
{
InitSysCtrl();
InitPieCtrl();
InitPieVectTable();
IER = 0x0000;
IFR = 0x0000;
SEG_Init();
LED_Init();
Seg_SetNum(0);
TIM0_Init(150, 1000000);
while(1)
{
GpioDataRegs.GPBTOGGLE.bit.GPIO60 = 1;
delay();
}
}
今天主要内容是定时器的使用,下面只贴出TIM0_Init()功能函数的实现代码
void TIM0_Init(float Freq, float Period)
{
long temp;
DINT;
EALLOW;
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1;
EDIS;
EALLOW;
PieVectTable.TINT0 = &TIM0_IRQ;
EDIS;
EALLOW;
CpuTimer0.RegsAddr = &CpuTimer0Regs;
CpuTimer0.CPUFreqInMHz = Freq;
CpuTimer0.PeriodInUSec = Period;
temp = (long) (Freq * Period);
CpuTimer0.RegsAddr->PRD.all = temp;
CpuTimer0.RegsAddr->TPR.all = 0;
CpuTimer0.RegsAddr->TPRH.all = 0;
CpuTimer0.RegsAddr->TCR.bit.TSS = 1;
CpuTimer0.RegsAddr->TCR.bit.TRB = 1;
CpuTimer0.RegsAddr->TCR.bit.SOFT = 0;
CpuTimer0.RegsAddr->TCR.bit.FREE = 0;
CpuTimer0.RegsAddr->TCR.bit.TIE = 1;
CpuTimer0.InterruptCount = 0;
CpuTimer0.RegsAddr->TCR.bit.TSS = 0;
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
EDIS;
IER |= M_INT1;
EINT;
ERTM;
}
interrupt void TIM0_IRQ(void)
{
static unsigned char i = 0;
i++;
if(i > 9) i = 0;
Seg_SetNum(i);
EALLOW;
CpuTimer0Regs.TCR.bit.TIF = 1;
PieCtrlRegs.PIEACK.bit.ACK1 = 1;
EDIS;
}
在TIM0_Init(float Freq, float Period) 中,第三步的代码是复制TI公司的代码(FILE: DSP2833x_CpuTimers.c)也可以简化成下面的样子。
void TIM0_Init(float Freq, float Period)
{
long temp;
DINT;
EALLOW;
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1;
EDIS;
EALLOW;
PieVectTable.TINT0 = &TIM0_IRQ;
EDIS;
InitCpuTimers();
ConfigCpuTimer(&CpuTimer0,Freq,Period);
EALLOW;
CpuTimer0.RegsAddr->TCR.bit.TSS = 0;
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
EDIS;
IER |= M_INT1;
EINT;
ERTM;
}
PS: 可能有些朋友不太清楚 ConfigCpuTimer(&CpuTimer0,Freq,Period);的三个参数。这里简单注释一下,函数原型为
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)
其中Timer的可选参数有三个,就是分别对应的三个定时器
&CpuTimer0 、 &CpuTimer1 、 &CpuTimer2 ;
Freq 为系统时钟单位MHZ,我用的系统时钟为150MHz,所以我在这里填 150;
Period 为期望的定时周期,单位为us 。我的目标是1s,所以我这里填1000000 ;
可能有朋友会像我一样疑惑为什么没有涉及到预分频的设置。通过阅读源文件,我发现TI公司直接是对系统时钟不分频CpuTimer0.RegsAddr->TPR.all = 0; CpuTimer0.RegsAddr->TPRH.all = 0;
凭借着自己是个32位的计数器,通过肆意改变定时周期的自动装载值来实现不同时间的定时,超霸气,超简便,超赞。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)