一、概述
定时器是用来准确控制时间的工具。DSP为了能够精确的控制时间,以满足控制某些特定事件的要求,定时器是不可缺少的内容。DSP28335内部具有3个32位的CPU定时器,分别是Timer0、Timer1、Timer2,其中Timer2是为操作系统DSP/BIOS保留的,当未移植操作系统时,可用来做普通定时器。这三个定时器的中断信号分别为TINT0,TINT1,TINT2,分别对应中断向量INT1,INT13,INT14。
本节将讲述DSP28335定时器中断的使用方法。分别从定时器工作原理、定时器相关寄存器、定时器中断软件配置方法,三部分进行讲解。
二、定时器工作原理
DSP28335的CPU定时器内部结构如图1所示。
图1 DSP28335的CPU内部结构
从上图可知,定时器有一个预分频模块和一个定时/计数模块,其中预分频模块一个16位的定时器分频寄存器(TDDRH:TDDR)和一个16位的预定标计数器(PSCH:PSC);定时/计数模块包括一个32位的周期寄存器(PRDH:PRD)和一个32位的计数寄存器(TIMH:TIM)。
当系统时钟(SYSCLKOUT)来一个脉冲,PSCH:PSC预定标计数器减1,当PSCH:PSC预定标计数器减到0的时候,预定标计数器产生下溢后向定时器的32位计数器TIMH:TIM错位,即TIMH:TIM计数器减1,同时,PSCH:PSC可以重载定时器分频寄存器(TDDRH:TDDR)的值;当计数器寄存器TIMH:TIM减到0产生下溢的时候,计数器寄存器会重载周期寄存器(PRDH:PRD)的值,同时定时器会产生一个中断信号给CPU。定时器的具体工作原理如图2所示。
图2 CPU定时器工作原理
从图2可以看出,CPU计数时候来一个脉冲,PSC减去1,减到0时候做了两件事情,分别为PSC重新装个值进去,还有是发出一个TIMCLK脉冲,这个脉冲发一个TIM就减去1,直到TIM减到0,然后完成一次计时,完成一次计时后,发生两件事情,一件是TIM值重新装载一下,一件是产生一个中断事件。
从上面的介绍可以看到,如果想要用CPU定时器来计量一段时间的话,需要设定的寄存器有两个,一个是周期寄存器PRDH:PRD,一个是分频器寄存器TDDRH:TDDR。分频器寄存器TDDRH:TDDR决定了CPU定时器计数时每一步的时间。假设系统时钟SYSCLKOUT的值为X(MHz),那么计数器每走一步,所需要的时间为:
因为CPU定时器一个周期计数了(PRDH:PRD+1)次,因此CPU定时器一个周期所计量的时间为:
讲完定时器的原理,再补充一下定时器中断,定时器的中断结构如下图3所示。
图3 定时器中断结构图
定时器中断属于PIE中断,中断信号经过PIE后,再进入处理器,定时器0的中断属于PIE第一组中断中的第7个小中断。
三、定时器相关寄存器
定时器配置和控制寄存器如图4所示。
图4 CPU定时器寄存器列表
三个定时器的寄存器类似,因此只要了解一个定时器的寄存器即可。
(1)定时器控制寄存器TIMERxTCR
图5 定时器控制寄存器
图6 定时器控制寄存器位定义
(2)定时器预定标寄存器
图7 定时器预定标寄存器
图8 定时器预定标寄存器位定义
(3)定时器计数器寄存器
图9 定时器计数器寄存器
图10 定时器计数器寄存器位定义
(4)定时器周期寄存器
图11 定时器周期寄存器
图12 定时器周期寄存器位定义
四、定时器中断软件配置方法
步骤一:使能定时器时钟;
步骤二:初始化定时器参数,包括周期寄存器值、预分频值等;
步骤三:定时器的设置,设置哪个定时器、定时器频率等;
步骤四:开启定时器中断功能,并使能定时器;
步骤五:编写定时器中断服务函数。
具体程序为:
/*
* timer.c
*
* Created on: 2023年7月6日
* Author: CZNDL
*/
#include "DSP2833x_Device.h" // Headerfile Include File
#include "DSP2833x_Examples.h" // Examples Include File
#include "timer.h"
#include "Gpio.h"
//步骤1:使能定时器时钟
//步骤2:初始化定时器参数,包括指定定时器寄存器地址、周期寄存器值、预定标计数值等
//步骤3:定时器设置---设置定时器周期
//步骤4:开启定时器中断功能,并使能定时器
//步骤5:编写中断函数
void Timer0_Init(float Freq,float Period)
{
DINT; // 禁止CPU全局中断
//步骤1:使能定时器时钟
EALLOW;
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; //CPU timer0
EDIS;
//步骤2:初始化定时器参数,包括指定定时器寄存器地址、周期寄存器值、预定标计数值等
CpuTimer0.RegsAddr = &CpuTimer0Regs; //指定定时器0的寄存器地址
CpuTimer0Regs.PRD.all = 0xFFFFFFFF; //设置定时器0的周期寄存器值
CpuTimer0Regs.TPR.all = 0; //设置定时器预定标计数器值为0
CpuTimer0Regs.TPRH.all = 0;
CpuTimer0Regs.TCR.bit.TSS = 1; //确定定时器0为停止状态
CpuTimer0Regs.TCR.bit.TRB = 1; //重载使能
CpuTimer0.InterruptCount = 0;
//步骤3:定时器设置---设置定时器周期
ConfigCpuTimer(&CpuTimer0,Freq,Period);
//步骤4:开启定时器中断功能,并使能定时器
CpuTimer0Regs.TCR.bit.TSS = 0; //开启定时器功能
IER |= M_INT1; //开启CPU第一组中断
PieCtrlRegs.PIEIER1.bit.INTx7 = 1; //使能第一组中断的第7个小中断,即定时器0
EALLOW;
PieVectTable.TINT0 = &TIM0_IRQn; //设置定时器0的中断入口地址为中断向量表的INTO;
EDIS;
EINT; //使能总中断
ERTM;
}
//步骤5:编写定时器中断函数
interrupt void TIM0_IRQn(void)
{
GpioDataRegs.GPCTOGGLE.bit.GPIO75 = 1;
EALLOW;
PieCtrlRegs.PIEACK.bit.ACK1 = 1;
EDIS;
}
其中,ConfigCpuTimer(&CpuTimer0,Freq,Period);
这个函数是TI封装好的,我们只要会用就行。主函数为:
/*
* main.c
*
* Created on: 2023年6月29日
* Author: CZNDL
*/
#include "DSP2833x_Device.h" // Headerfile Include File
#include "DSP2833x_Examples.h" // Examples Include File
#include "Gpio.h"
#include "Exti.h"
#include "timer.h"
void main(void)
{
InitSysCtrl();
//----------------------
InitPieCtrl();
IER = 0x0000; // 禁止CPU中断和清除所有CPU中断标志
IFR = 0x0000;
InitPieVectTable(); //初始化PIE中断向量表,并使其指向中断服务子程序(ISR)
//---------------
GIOP_Init();
EXTI_Init();
Timer0_Init(150,100); //us为单位 ---- 150M主频,计时100us产生中断
while(1)
{
// GpioDataRegs.GPCSET.bit.GPIO75 = 1;
}
}
五、总结
至此,DSP28335定时器中断已讲完。这些处理器外设是电机控制必涉及的,为后续的讲解电机控制作铺垫。
更多精彩内容,请关注"电机人生"微信公众号