• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

DSP学习笔记

最近在学习DSP,想把自己的学习感想,记录下来,大家讨论一下。

DSP的三级中断机制,分别是外设级,PIE级和CPU级,也就是说,对于一个具体的外设中断请求,我们需要三级的许可。

CPU相当于分组,分成了12个小组,而PIE是CPU组里边的成员每个小组又有8个成员。PIE的英语称作Peripheral interrupt Expansion  block

专门处理外设中断的扩展模块。很准确的描述了PIE的含义。

书上用了一个使用CPU定时器0的周期中断来控制LED灯的例子。

CPU定时器0在完成一个周期的计数之后,会产生一个周期中断,设置CPU定时器0的周期为1S,每隔1S进入一次周期中断,在中断服务程序里边

改变了GPIO引脚的电平。

 

void main(void)

{    InitSysCtrl();  //初始化系统函数

      DINT; 

      IER = 0x0000;   //禁止CPU中断 

      IFR = 0x0000;   //清除CPU中断标志  

      这两个寄存器分别是中断使能寄存器和中断标志寄存器,说明这个程序里边的中断时可屏蔽中断,

      InitPieCtrl();  //初始化PIE控制寄存器

      InitPieVectTable(); //初始化PIE中断向量表  

      InitPeripherals(); //初始化Cpu定时器模块  I

      nitGpio(); //初始化GPIO

      PieCtrl.PIEIER1.bit.INTx7 =1; //使能PIE模块中的Cpu定时器0的中断       I

      ER|=M_INT1;  //开CPU中断   

      EINT;  //使能全局中断   

      ERTM;  //使能实时中断  

      ConfigCpuTimer(&CpuTimer0, 150, 1000000); //Cpu定时器0的周期为1s  

      StartCpuTimer0(); //启动Cpu定时器0  for(;;) {    }

}

 

以上的MIAN的主程序,下边是DSP28_PIEVECT.H这个头文件,书上说定义了PIE的中断向量,我觉得这个头文件还有一个重点
就是定义了PINT的指针,指向了中断。之后要去找找这个PINT的指针在哪里。
#ifndef DSP28_PIE_VECT_H
#define DSP28_PIE_VECT_H

// 定义一个名称为PINT的指针,指向中断:

typedef interrupt void(*PINT)(void);

// 定义中断向量表:
struct PIE_VECT_TABLE {

//中断向量表起始地址为0x3FFFC0, 在BOOT ROM还是XINTF ZONE7 取决于引脚XMP/MC的状态
//当XMP/MC=0时,向量表在BOOT ROM内;当XMP/MC=1,向量表在XINTF ZONE7内

      PINT     PIE1_RESERVED; ........ 
      // 非外设中断:
      PINT     XINT13;    // XINT13
      .....      
// PIE组1外设中断向量:
      PINT     PDPINTA;   // EV-A
     .....           
// PIE组2外设中断向量:
      PINT     CMP1INT;   // EV-A
      ........      
// PIE组3外设中断向量:
      PINT     T2PINT;    // EV-A
    ........      
// PIE组4外设中断向量:
      PINT     CMP4INT;   // EV-B
      ........     
// PIE组5外设中断向量:
      PINT     T4PINT;    // EV-B
     .......
.........
extern struct PIE_VECT_TABLE PieVectTable;


#endif  

 

InitPieCtrl这个函数对PIE的中断使能寄存器进行初始化,对应上图画红圈的寄存器。

程序里边第一步先是给PieCtrl.PIECRTL.bit.ENPIE = 0;对PIE控制寄存器的ENPIE位置0,此时PIE块是无效的。

第二步,对PIE中断使能寄存器设置,这个寄存器一共有12个分别为PIEIERx,而每个寄存器正好有8位,对应每个CPU小组里边的8个成员。

也就是说这个PIE中断使能寄存器有96个分别使能每个成员中断。对应上边图中的开关闭合对应每个CPU小组里边的8个成员。也就是说这个PIE中断使能寄存器有96个分别使能每个成员中断。对应上边图中的开关闭合

第三步,对PIE中断标志寄存器设置,和中断使能寄存器类似分成12组,每个组有8个成员,一共12个寄存器,每个寄存器8位。书上说当中断激活的时候,各个寄存器位置1,当中断被处理完成或者向该位写0,该为清0.还不能理解--------------------------------------------------------------------------------

void InitPieCtrl(void)
{
	// 禁止PIE模块
	PieCtrl.PIECRTL.bit.ENPIE = 0;

	// 禁止PIE所有中断
	PieCtrl.PIEIER1.all = 0;
	PieCtrl.PIEIER2.all = 0;
	PieCtrl.PIEIER3.all = 0;	
	PieCtrl.PIEIER4.all = 0;
	PieCtrl.PIEIER5.all = 0;
	PieCtrl.PIEIER6.all = 0;
	PieCtrl.PIEIER7.all = 0;
	PieCtrl.PIEIER8.all = 0;
	PieCtrl.PIEIER9.all = 0;
	PieCtrl.PIEIER10.all = 0;
	PieCtrl.PIEIER11.all = 0;
	PieCtrl.PIEIER12.all = 0;

	// 清除所有PIEIFR的中断标志位
	PieCtrl.PIEIFR1.all = 0;
	PieCtrl.PIEIFR2.all = 0;
	PieCtrl.PIEIFR3.all = 0;	
	PieCtrl.PIEIFR4.all = 0;
	PieCtrl.PIEIFR5.all = 0;
	PieCtrl.PIEIFR6.all = 0;
	PieCtrl.PIEIFR7.all = 0;
	PieCtrl.PIEIFR8.all = 0;
	PieCtrl.PIEIFR9.all = 0;
	PieCtrl.PIEIFR10.all = 0;
	PieCtrl.PIEIFR11.all = 0;
	PieCtrl.PIEIFR12.all = 0;

	// 使能PIE模块
	PieCtrl.PIECRTL.bit.ENPIE = 1;
	PieCtrl.PIEACK.all = 0xFFFF;
}	
下边是DSP28_PieVect.c对PIE中断向量初始化,执行完这个程序之后,各个中断函数有了入口地址。const struct PIE_VECT_TABLE PieVectTableInit = {省去}
void InitPieVectTable(void)
{
	int16	i;
	Uint32 *Source = (void *) &PieVectTableInit;
	Uint32 *Dest = (void *) &PieVectTable;
		
	EALLOW;	
	for(i=0; i < 128; i++)
		*Dest++ = *Source++;	
	EDIS;

	// 使能PIE向量表
	PieCtrl.PIECRTL.bit.ENPIE = 1;	
			
}
   for(i=0; i < 128; i++)注意这里赋值了128次

这个程序大概就是设置定时器0的周期为1S,每隔1S进入一次周期中断  

ConfigCpuTimer(&CpuTimer0, 150, 1000000);        //Cpu定时器0的周期为1s  StartCpuTimer0(); //启动Cpu定时器0       

void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)
{
	Uint32 	temp;
	
	Timer->CPUFreqInMHz = Freq;
	Timer->PeriodInUSec = Period;
	temp = (long) (Freq * Period);
	Timer->RegsAddr->PRD.all = temp;  //给定时器周期寄存器赋值

	Timer->RegsAddr->TPR.all  = 0;    //给定时器预定标寄存器赋值
	Timer->RegsAddr->TPRH.all  = 0;
	
	// 初始化定时器控制寄存器:
	Timer->RegsAddr->TCR.bit.TIF=1;   //清除中断标志位
	Timer->RegsAddr->TCR.bit.TSS = 1; //停止定时器 
	Timer->RegsAddr->TCR.bit.TRB = 1; //定时器重装,将定时器周期寄存器的值装入定时器计数器寄存器
	Timer->RegsAddr->TCR.bit.SOFT = 1;
	Timer->RegsAddr->TCR.bit.FREE = 1;     
	Timer->RegsAddr->TCR.bit.TIE = 1; //使能定时器中断
	
	Timer->InterruptCount = 0;        //初始化定时器中断计数器
}
然后每计数1S进入一次中断在中断里边编写了灯闪硕的代码
interrupt void  TINT0_ISR(void)      // CPU-Timer0中断函数
{
   CpuTimer0.InterruptCount++;
   
   if(CpuTimer0.InterruptCount==1)  
   {
      GpioDataRegs.GPFCLEAR.bit.GPIOF14=1;  //XF引脚低电平,D3亮
   }
   
   if(CpuTimer0.InterruptCount==2)
   {
      GpioDataRegs.GPFSET.bit.GPIOF14=1;    //XF引脚高电平,D3灭
      CpuTimer0.InterruptCount=0;
   }
   
   CpuTimer0Regs.TCR.bit.TIF=1;  //清除定时器中断标志位
   PieCtrl.PIEACK.bit.ACK1=1;    //响应同组其他中断
   EINT;  //开全局中断
}
 
全部回复(6)
正序查看
倒序查看
dobetter
LV.7
2
2015-09-01 15:22
攒个
0
回复
2015-09-01 16:02
0
回复
2015-09-07 14:46
xue xue xue xue xxue
0
回复
2016-05-08 22:09
@wuqishengli
xuexuexuexuexxue
很好
0
回复
2016-06-04 12:04
@空军通信兵
很好
本人表示看不懂,现在在谢谢...
0
回复
zhouboak
LV.8
7
2017-05-20 11:03
@dy-xq5gLF1q
[图片]本人表示看不懂,现在在谢谢...
关注
0
回复