DSP 定时器中断

1.定时器介绍

1.1 定时器工作原理

        TMS320F28335的CPU Time有三个,分别为Timer0,Timer1,Timer2,其中Timer1和Timer2是为操作系统DSP/BIOS保留的,当未移植操作系统时,Timer0、Timer1和Timer2可用来做普通的定时器。这三个定时器的中断信号分别为TINT0, TINT1, TINT2,分别对应于中断向量INT1,INT13,INT14。Timer0中断经过PIE模块,而Timer1和Timer2是直接连接到内核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。定时器的中断结构如下图所示:

        定时器0中断属于 PIE 中断,中断信号经过 PIE 后,再进入处理器,定时器 0 的中断属于 PIE 第一组中断中的第 7 个小中断。

 1.2 定时器相关寄存器

 (1)定时器控制寄存器TIMERxTCR

 

 2.定时器配置步骤

   定时器相关库函数在DSP2833x_CpuTimers.c文件中
(1)使能定时器时钟

EALLOW;
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // CPU Timer 0
EDIS;

(2)初始化定时器参数,包括制定定时器寄存器地址、周期寄存器值、预定标计数器值等

//指向定时器0的寄存器地址
CpuTimer0.RegsAddr = &CpuTimer0Regs;
//设置定时器0的周期寄存器值
CpuTimer0Regs.PRD.all  = 0xFFFFFFFF;
//设置定时器预定标计数器值为0
CpuTimer0Regs.TPR.all  = 0;
CpuTimer0Regs.TPRH.all = 0;
//确保定时器0为停止状态
CpuTimer0Regs.TCR.bit.TSS = 1;
//重载使能
CpuTimer0Regs.TCR.bit.TRB = 1;
// Reset interrupt counters:
CpuTimer0.InterruptCount = 0;

(3)定时器的设置

TI提供的库函数“DSP2833x_CpuTimers.c”内已经有函数实现

void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period);

该函数有 3 个参数,第 1 个表示哪个定时器,第 2 个表示定时器频率,第 3 个表示定时器周期值。函数具体内部实现代码如下:

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;

	// 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 = 0;
	Timer->RegsAddr->TCR.bit.FREE = 0;     // Timer Free Run Disabled
	Timer->RegsAddr->TCR.bit.TIE = 1;      // 0 = Disable/ 1 = Enable Timer Interrupt

	// Reset interrupt counter:
	Timer->InterruptCount = 0;
}

(4)开启定时器中断功能,并使能定时器

//设置定时器0的中断入口地址为中断向量表的INT0
EALLOW;
PieVectTable.TINT0 = &TIM0_IRQn;
EDIS;
//开始定时器功能
CpuTimer0Regs.TCR.bit.TSS=0;
//开启CPU第一组中断并使能第一组中断的第7个小中断,即定时器0
IER |= M_INT1;
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
//使能总中断
EINT;
ERTM;

(5)编写定时器中断服务函数

interrupt void TIM0_IRQn(void)
{
	......功能程序
}

3.硬件设计

本实验使用到硬件资源如下:

(1)D1、D2指示灯

(2)定时器0

4.软件设计

本章所要实现的功能是:通过Timer0中断控制 D2 指示灯闪烁,主函数控制 D1 指示灯闪烁提示系统运行状态。程序框架如下:

(1)Timer0软件实验:

//---------------------------------------------------------------------------
// 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;
	Timer->PeriodInUSec = Period;
	temp = (long) (Freq * Period);
	Timer->RegsAddr->PRD.all = 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 = 0;
	Timer->RegsAddr->TCR.bit.FREE = 0;     // Timer Free Run Disabled
	Timer->RegsAddr->TCR.bit.TIE = 1;      // 0 = Disable/ 1 = Enable Timer Interrupt

	// Reset interrupt counter:
	Timer->InterruptCount = 0;
}
//定时器0初始化函数
//Freq:CPU时钟频率(150MHz)
//Period:定时周期值,单位us
void TIM0_Init(float Freq, float Period) //Freq CPU主频,Period 定时周期
{
	EALLOW;
	SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // CPU Timer 0
	EDIS;

	//设置定时器0的中断入口地址为中断向量表的INT0
	EALLOW;
	PieVectTable.TINT0 = &TIM0_IRQn;
	EDIS;

	//指向定时器0的寄存器地址
	CpuTimer0.RegsAddr = &CpuTimer0Regs;
	//设置定时器0的周期寄存器值
	CpuTimer0Regs.PRD.all  = 0xFFFFFFFF;
	//设置定时器预定标计数器值为0
	CpuTimer0Regs.TPR.all  = 0;
	CpuTimer0Regs.TPRH.all = 0;
	//确保定时器0为停止状态
	CpuTimer0Regs.TCR.bit.TSS = 1;
	//重载使能
	CpuTimer0Regs.TCR.bit.TRB = 1;
	// Reset interrupt counters:
	CpuTimer0.InterruptCount = 0; //可以不用调用

	ConfigCpuTimer(&CpuTimer0, Freq, Period);

	//开始定时器功能
	CpuTimer0Regs.TCR.bit.TSS=0;
	//开启CPU第一组中断并使能第一组中断的第7个小中断,即定时器0
	IER |= M_INT1; //#define M_INT1  0x0001
	PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
	//使能总中断
	EINT;
	ERTM;	//使能仿真调试中断

}

interrupt void TIM0_IRQn(void)
{
	EALLOW;
	LED2_TOGGLE;
	PieCtrlRegs.PIEACK.bit.ACK1=1;	//中断执行完成后 清除中断标志
	EDIS;
}
/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main()
{
	int i=0;

	InitSysCtrl();

	InitPieCtrl();
	IER = 0x0000;
	IFR = 0x0000;
	InitPieVectTable();

	LED_Init();
	TIM0_Init(150,500000);//150MHZ, 500ms

	while(1)
	{
		i++;
		if(i%2000==0)
		{
			LED1_TOGGLE;
		}
		DELAY_US(100);
	}
}

(2)Timer1软件实验:

void TIM1_Init(float Freq, float Period)
{
	EALLOW;
	SysCtrlRegs.PCLKCR3.bit.CPUTIMER1ENCLK = 1; // CPU Timer 1
	EDIS;

	EALLOW;
	PieVectTable.XINT13 = &TIM1_IRQn;
	EDIS;

	// Initialize address pointers to respective timer registers:
	CpuTimer1.RegsAddr = &CpuTimer1Regs;
	// Initialize timer period to maximum:
	CpuTimer1Regs.PRD.all  = 0xFFFFFFFF;
	// Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
	CpuTimer1Regs.TPR.all  = 0;
	CpuTimer1Regs.TPRH.all = 0;
	// Make sure timers are stopped:
	CpuTimer1Regs.TCR.bit.TSS = 1;
	// Reload all counter register with period value:
	CpuTimer1Regs.TCR.bit.TRB = 1;
	// Reset interrupt counters:
	CpuTimer1.InterruptCount = 0;

	ConfigCpuTimer(&CpuTimer1, Freq, Period);

	CpuTimer1Regs.TCR.bit.TSS=0;

	IER |= M_INT13;//不需要配置PIECtrl

	EINT;
	ERTM;

}

interrupt void TIM1_IRQn(void)
{
	EALLOW;
	LED3_TOGGLE;
	EDIS;
}
/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main()
{
	int i=0;

	InitSysCtrl();

	InitPieCtrl();
	IER = 0x0000;
	IFR = 0x0000;
	InitPieVectTable();

	LED_Init();
	TIM1_Init(150,500000);

	while(1)
	{
		i++;
		if(i%2000==0)
		{
			LED1_TOGGLE;
		}
		DELAY_US(100);
	}
}

(3)Timer2软件实验:

void TIM2_Init(float Freq, float Period)
{
	EALLOW;
	SysCtrlRegs.PCLKCR3.bit.CPUTIMER2ENCLK = 1; // CPU Timer 2
	EDIS;

	EALLOW;
	PieVectTable.TINT2 = &TIM2_IRQn;
	EDIS;

	// Initialize address pointers to respective timer registers:
	CpuTimer2.RegsAddr = &CpuTimer2Regs;
	// Initialize timer period to maximum:
	CpuTimer2Regs.PRD.all  = 0xFFFFFFFF;
	// Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
	CpuTimer2Regs.TPR.all  = 0;
	CpuTimer2Regs.TPRH.all = 0;
	// Make sure timers are stopped:
	CpuTimer2Regs.TCR.bit.TSS = 1;
	// Reload all counter register with period value:
	CpuTimer2Regs.TCR.bit.TRB = 1;
	// Reset interrupt counters:
	CpuTimer2.InterruptCount = 0;

	ConfigCpuTimer(&CpuTimer2, Freq, Period);

	CpuTimer2Regs.TCR.bit.TSS=0;

	IER |= M_INT14;//不需要配置PIECtrl

	EINT;
	ERTM;

}

interrupt void TIM2_IRQn(void)
{
	EALLOW;
	LED4_TOGGLE;
	EDIS;

}
/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main()
{
	int i=0;

	InitSysCtrl();

	InitPieCtrl();
	IER = 0x0000;
	IFR = 0x0000;
	InitPieVectTable();

	LED_Init();
	TIM2_Init(150,1000000);

	while(1)
	{

		i++;
		if(i%2000==0)
		{
			LED1_TOGGLE;
		}
		DELAY_US(100);
	}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值