⑴ 了解TMS320F28335的定时器工作原理; ⑵ 了解TMS320F28335的中断设置; 实验设备:
⑴ 装有Windows的PC机一台; ⑵ XDS510仿真器一套; ⑶ YX-F28335A开发板一套; 实验原理及说明: 实验步骤:
➢首先按照实验一配置CCS3.3软件并打开;
➢接着把仿真器的USB及电脑进行连接,将仿真器的另一端JATG端插到YX-F28335A开发板的
JATG针处;
➢点击CCS->Debug->Connect,连接目标板,出现如下图则表示连接成功;
➢将TIMER0目录拷贝到CCS开发环境中的Myproject目录下;
➢在CCS菜单栏点击project->Open……命令,加载TIMER0目录中TIMER0.pjt;
➢在CCS菜单栏点击File->Load Program……命令,加载Debug目录下的TIMER0.out; ➢在CCS中按下图设置断点(在欲设置断点处所在的行双击鼠标即可);
➢在CCS中点击Debug->Run,此时用户可以发现程序运行到断点处,然后查看YX-F28335A开
发板上面的6个LED的状态;
➢在CCS中用Debug->Run,此时程序第二次运行到断点,然后查看YX-F28335A开发板上面的
6个LED的状态,可以多次运行程序来观察YX-F28335A开发板上LED的状态; ➢双击鼠标断点处,将断点去掉,然后点击Debug->Run,再次观看LED变化情况;
实验原理及程序说明:
TMS320F28335片上有3个32位CPU定时器,分别被称为CPU 定时器0、1 和2。每个定时器中均有一个32位减计数器,当计数器减到0时,产生一个中断。在此实验中,使用的是定时器0,当定时器0计时到100ms的时候,程序进入定时器0中断服务函数,用户可以在中断函数中来改变LED的状态,从而实现LED闪烁的效果。 TMS320F28335定时器工作原理如下图所示:
每来一个时钟信号,预定标计数器PSCH:PSC就会减1,直到减到0后,它将会重载
TDDRH:TDDR的值,同时TIMH:TIM计数器将会减1。这个过程将重复进行,直到TIMH:TIM计数器的值减到0时,定时器将会产生一个中断信号,同时TIMH:TIM计数器重载周期寄存器
PRDH:PRD的值。通过对定时器控制寄存器(TIMERxTCR)的设置,可以让定时器工作在不同的方式。
TIF:定时器中断标志位,写1时将清除中断标志;
TIE:定时器中断使能位,写1时使能中断,写0时不使能中断; FREE、SOFT:定时器仿真模式选择位:
00 硬件停止;01 软件停止;10 自由运行;11 自由运行
TRB:重载控制位,当写入1时,PSCH:PSC重载TDDRH:TDDR的值、TIMH:TIM重载
PRDH:PRD的值;
TSS:定时器开启位,写入0,开启定时器;写入1,关闭定时器;
由于TMS320F2833x 系列DSP 片上有非常丰富的外设,每个片上外设均可产生1 个或多个中断请求,所以TMS320F2833x 系列DSP 的中断要比其他处理器复杂。
TMS320F2833x系列DSP 的中断由2级组成,一级是外设中断扩展控制器(PIE),另一级是CPU中断,它们的构成如图所示:
TMSF2833x有32个CPU中断源,包括复位RESET、MNI、EMUINT、ILLEGAL、12 个用户自定义的软件中断USER1~USER12和16个可屏蔽中断(INT1~INT14、RTOSINT 和
DLOGINT),RTOSINT 和DLOGINT由CPU内部的仿真逻辑产生,所有的软件中断属于非屏蔽中断。而F2833x 系列DSP上有很多片上外设,每个片上外设都可能产生1个或多个中断请求,以响应众多的片上外设事件。CPU 没有足够的中断源来管理所有的片上外设中断请求,所以在F28x系列DSP 中设置了一个外设中断扩展控制器(PIE)来管理片上外设和外部引脚引起的中断请求。
F2833x系列DSP的片上外设中断共有96个,被分为12个组,每组内有8个片上外设中断请求,因此96个片上外设中断请求信号可记为INTx.y(x = 1,2,……,12;y = 1,2,……,8)。每个组输出一个中断请求信号给CPU,也即是PIE 的输出INTx(x = 1,2,……,12)对应于CPU中断输入的INT1~INT12。每个中断源对应一个中断向量(对应的中断服务程序ISR的入口地址),无论此中断源是否及别的中断源复用一个CPU中断输入。F28x在片上外设结构0中开辟了一块大小为256×16位(128×32位,对应128个中断向量)的储存空间,专门用作PIE的中断向量表,用于存放每个中断源所对应的中断服务程序(ISR)的入口地址。为什么是128个中断向量呢?在复位时,F2833x的PIE被禁止,所以只有32个CPU中断,所以也只需32个中断向量,而当PIE被使能后,除了32个CPU中断外,还有96个PIE中断,所以需要32 + 96 = 128个中断向量。
具体的中断内容请参考TMS320F2833x External Interface(XINTF)User’s Guide文献。 熟悉TMS320F28335的中断原理后,现在再分析定时器0的中断原理图:
定时器中断信号是经过PIE后,再作为C28x处理器的中断输入信号,并且定时器的时钟信号也是及处理器的时钟同步的。由上面的原理图可知,定时器0属于PIE中断,下面分析PIE模块的框架图:
那么定时器0中断到底属于PIE的哪一组中断呢?又属于这一组的第几个中断呢?带着这两个问题我们来看PIE中断向量表:大家请看下图中红色框里面的TINT0就是定时器0中断,用户请再看两个红勾,横向的INT1代表中断组,纵向的INTx.7是第一组中断的第7个小中断。(具体详细的关于中断的数据资料及配置请用户参考相关手册)
➢定时器0初始化程序如下:
void InitCpuTimers(void) {
// 定时器0初始化 // 指向定时0的寄存器地址 CpuTimer0.RegsAddr = &CpuTimer0Regs; // 设置定时器0的周期寄存器值 CpuTimer0Regs.PRD.all = 0xFFFFFFFF; // 设置预定标计数器值为0 CpuTimer0Regs.TPR.all = 0; CpuTimer0Regs.TPRH.all = 0; // 确保定时器为停止状态: CpuTimer0Regs.TCR.bit.TSS = 1; // 重载使能 CpuTimer0Regs.TCR.bit.TRB = 1; CpuTimer0.InterruptCount = 0; }
➢ 定时器0的设置如下所示:
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; // Freq * Period的值给周期寄存器 // 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每隔一段时间产生一次中断,这段时间的计算公式为:△T= Freq * Period /150000000(s);(其中150000000是CPU的时钟频率,即150MHz的时钟频率)针对此实验,Frep为150,Period为100000,那么△T=0.1s=100ms。
➢中断设置程序过程如下: void InitPieCtrl(void) {
// 关闭CPU总中断 DINT;
// 关闭PIE模块总中断
PieCtrlRegs.PIECTRL.bit.ENPIE = 0; // 关闭所有PIE模块的中断 PieCtrlRegs.PIEIER1.all = 0; PieCtrlRegs.PIEIER2.all = 0; PieCtrlRegs.PIEIER3.all = 0; PieCtrlRegs.PIEIER4.all = 0; PieCtrlRegs.PIEIER5.all = 0; PieCtrlRegs.PIEIER6.all = 0; PieCtrlRegs.PIEIER7.all = 0; PieCtrlRegs.PIEIER8.all = 0; PieCtrlRegs.PIEIER9.all = 0; PieCtrlRegs.PIEIER10.all = 0; PieCtrlRegs.PIEIER11.all = 0; PieCtrlRegs.PIEIER12.all = 0; // 清除所有PIE中断标志位 PieCtrlRegs.PIEIFR1.all = 0; PieCtrlRegs.PIEIFR2.all = 0; PieCtrlRegs.PIEIFR3.all = 0; PieCtrlRegs.PIEIFR4.all = 0; PieCtrlRegs.PIEIFR5.all = 0; PieCtrlRegs.PIEIFR6.all = 0; PieCtrlRegs.PIEIFR7.all = 0; PieCtrlRegs.PIEIFR8.all = 0; PieCtrlRegs.PIEIFR9.all = 0; PieCtrlRegs.PIEIFR10.all = 0; PieCtrlRegs.PIEIFR11.all = 0; PieCtrlRegs.PIEIFR12.all = 0; }
➢中断向量表的初始化函数如下:
void InitPieVectTable(void) //此函数初始化中断向量表,将中断服务函数及向量表关联 { int16 i; Uint32 *Source = (void *) &PieVectTableInit; //中断服务函数入口地址 Uint32 *Dest = (void *) &PieVectTable; //中断向量表 EALLOW; for (i=0; i < 128; i++) *Dest++ = *Source++; //把中断入口地址送给中断向量表,达到关联的目的 EDIS; // Enable the PIE Vector Table PieCtrlRegs.PIECTRL.bit.ENPIE = 1; //使能PIE模块的总中断 }
➢下面的一句话就是告诉定时器0的中断入口地址为中断向量表的INT0 EALLOW; // this is needed to write to EALLOW protected registers PieVectTable.TINT0 = &ISRTimer0; EDIS;
➢下面的两句程序是告诉CPU第一组中断将会产生,并使能第一组中断的第7个小中断 IER |= M_INT1;
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
通过以上中断的设置,定时器0就会每隔100ms进入一次中断服务函数,但是中断服务函数里面需要清除中断标志位,包括清除PIE第一组的中断标志位和定时器0本身的中断标志位。 ➢中断标志位清除函数如下所示: Interrupt void ISR Timer0 (void) {
CpuTimer0.InterruptCount++;
// acknowledge this interrupt to receive more interrupts from group 1 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; CpuTimer0Regs.TCR.bit.TIF=1;
CpuTimer0Regs.TCR.bit.TRB=1;
//改变LED的状态
LED1=~LED1; LED2=~LED2; LED3=~LED3; LED4=~LED4; LED5=~LED5; LED6=~LED6; }
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo9.cn 版权所有 赣ICP备2023008801号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务