1. 28328335有16个中断线,其中包括2个不可屏蔽的中断(RESET和NMI)与14个可屏蔽的中断
2. 中断机制:
采用3级中断机制,分别为
1.外设级中断
2.PIE级中断
3.CPU级中断
最内核部分为CPU级中断,即CPU只能响应从CPU中断线上过来的中断请求,但F28335中断源很多,CPU没有足够的中断线,只能对中断线进行复用,其复用管理就有了中间层的PIE级中断,外设要能够成功产生中断响应,就需要首先经过外设级中断允许-》PIE允许-》CPU响应。
中断响应顺序:外设中断接收中断响应信号,传送到PIE中断控制器,最后传递CPU中断响应,做出中断响应的中断处理。
3. 28335有12中断组每组有八个中断一共96个中断
不同类别的中断信号,需要找出相对应的中断组及该中断组所对应的子中断信号线,启动该中断时,需要设置对应的信号寄存器。
4. CPU响应中断,就是CPU要去执行相应的中断服务程序,响应过程是CPU将现执行程序的指令地址压入堆栈,跳转到中断服务程序入口地址,中断服务程序的入口地址就是中断向量,这个中断向量用2个16位寄存器存放。入口地址是22位的,地址的低16位保存在向量的低16位;地址的高16位则保存在它的高6位,更高的10位保留。
5. 中断向量映射方式
在F28335中,中断向量表可以被映射到4个不同的存储区域,在实际应用中,F28335只能使用PIE中断向量表映射区域。
此矢量映射由以下模式位/信号控制:
1.VMAP
VMAP可以在状态寄存器1ST1(第3位)中找到。设备重置会将此位设置为1。这个位的状态可以通过写入ST1或SETC/CLRC VMAP指令来修改。对于正常操作,请保留此位元集。
2.M0M1MAP
M0M1MAP可在状态寄存器1ST1(第11位)中找到。设备重置会将此位设置为1。这个位的状态可以通过写入ST1或SETC/CLRC M0M1MAP指令来修改。对于正常的28xx设备操作,该位应该保持设置。M0M1MAP = 0仅保留用于TI测试。
3.ENPIE
ENPIE可以在拼接寄存器(第0位)中找到。重置时,此位的默认值设置为0(禁用PIE)。这个位的状态可以在重置后通过写入拼接寄存器(地址0x0000 0CE0.0)进行修改。
矢量映射M0和M1矢量仅是一种保留模式。在28x的设备上,这些设备被用作SARAM。
M1和M0矢量表映射仅保留用于TI测试。当使用其他向量映射时,M0和M1内存块被视为SARAM块,可以没有任何限制地自由使用。
在设备重置操作后,向量表映射如下表所示
(1)在28x设备上,VMAP和M0M1MAP模式设置为1。在重置时,ENPIE模式被强制设置为0。
(2)复位向量总是从引导ROM中获取。
4.中断操作
复位中断操作过程
PIE模块8个中断分成一组与外部中断一起共用一个CPU中断,总共有12组中断(INT1-INT12)。每组中断有相应的中断标志(PIEIFR)和使能寄存器(PIEIER),这些寄存器控制控制PIE向CPU申请中断。同时CPU还根据PIEIFR和PIEIER寄存器确定执行哪个中断服务程序。在清除PIEIFR和PIEIER的位时,要遵循以下3个规则。
4.1不要用软件编程清楚PIEIFR的位
4.2软件设置中断优先级
4.3使用PIEIER禁止中断
5.中断配置
//(1)使能外设对应的PIE中断:
PieCtrlRegs.PIEIER1.bit.INTx4 = 1; // 使能PIE组1的INT4
//(2)使能外设中断:
XIntruptRegs.XINT1CR.bit.ENABLE= 1; // 使能XINT1
//(3)指定中断向量表中断服务函数地址:
EALLOW; // 修改被保护的寄存器,修改前应添加EALLOW语句
PieVectTable.XINT1 = &EXTI1_IRQn;
EDIS; // EDIS的意思是不允许修改被保护的寄存器
//(4)使能CPU中断及全局中断:
IER |= M_INT1; // 使能CPU中断1(INT1)
EINT; // 开全局中断
//(5)编写中断服务函数
interrupt void EXTI1_IRQn(void)
{
...功能程序
}
6.外部中断配置
void main()
{
int i=0;
InitSysCtrl();
//以下四步是都要做的,初始化最初的中断
InitPieCtrl();//初始化PIE控制寄存器为已知状态,也就是使能位和中断标志位全部失能 DSP2833x_PieCtrl.c里自带的函数
IER = 0x0000;//失能所有CPU级的中断
IFR = 0x0000;//清除所有CPU级的中断标志位
InitPieVectTable();//初始化向量表 DSP2833x_PieVect.c中自带的函数
EXTI1_Init();
while(1)
{
DELAY_US(100);
}
}
void EXTI1_Init(void)
{
EALLOW;//开启写保护
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // GPIO input clock,输出也用这个
EDIS;
EALLOW;
//KEY端口配置
GpioCtrlRegs.GPAMUX1.bit.GPIO12=0; //GPIO功能
GpioCtrlRegs.GPADIR.bit.GPIO12=0;//方向为输入
GpioCtrlRegs.GPAPUD.bit.GPIO12=0;//默认上拉
GpioCtrlRegs.GPAQSEL1.bit.GPIO12 = 0; // 配置时钟采用,0就是与时钟同步。外部中断1(XINT1)与系统时钟SYSCLKOUT同步
EDIS;
//设置 IO 口与中断线的映射关系
EALLOW;
GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 12; // XINT1是GPIO12
EDIS;
//指定中断向量表中断服务函数地址
EALLOW; // 修改被保护的寄存器,修改前应添加EALLOW语句
PieVectTable.XINT1 = &EXTI1_IRQn; // .后面就是选择需要被定义中断向量的是哪个外设,比如DMA什么的 DSP2833x_PieVect.h
EDIS; // EDIS的意思是不允许修改被保护的寄存器
//使能外设对应的 PIE 中断
PieCtrlRegs.PIEIER1.bit.INTx4 = 1; //使能第一中断线中的第四个 先是PIE1组(PIEIER1), 然后.其中的第四个(INTx4) DSP2833x_PieCtrl.h
//设置外部中断触发方式并使能中断 DSP2833x_XIntrupt.h
XIntruptRegs.XINT1CR.bit.POLARITY = 0; // 下降沿触发中断
XIntruptRegs.XINT1CR.bit.ENABLE= 1; // 使能XINT1
IER |= M_INT1; // 使能CPU中断1(INT1)
EINT; // 开全局中断
ERTM;//在debug调试的时候可以使用这个
}
interrupt void EXTI1_IRQn(void)
{
Uint32 i;
for(i=0;i<10000;i++); //键盘消抖动
while(!GpioDataRegs.GPADAT.bit.GPIO12);//判断是否按下,按下就变为低电平
LED2_TOGGLE;//#define LED2_TOGGLE (GpioDataRegs.GPCTOGGLE.bit.GPIO67=1)
PieCtrlRegs.PIEACK.bit.ACK1=1;//对PIEACK清零,如果这里不清零下一次就不会进入中断了(写1就是清零)
}
6.定时器中断
定时器中断1,2一般是给操作系统预留的,不需要经过PIE,直接进入CPU(映射图中只有TIMER0)。使用操作系统时只可用0。
定时器0,1,2的中断信号分别为TINT0,TINT1,TINT2,分别对应于中断向量INT1,INT13,INT14。
配置步骤:
(1)使能定时器时钟
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // CPU Timer 0 SysCtrlRegs.PCLKCR3.bit.CPUTIMER1ENCLK = 1; // CPU Timer 1
SysCtrlRegs.PCLKCR3.bit.CPUTIMER2ENCLK = 1; // CPU Timer 2
(2)初始化定时器参数,包括制定定时器寄存器地址、周期寄存器值、预定标计数器值等
//初始化定时器参数-> 可用InitCpuTimers();直接替代
//指向Timer0的寄存器地址
CpuTimer0.RegsAddr=&CpuTimer0Regs;
//周期寄存器值得配置
CpuTimer0Regs.PRD.all=0xFFFFFFFF;
//设置Timer0的预标计数器值为0
CpuTimer0Regs.TPR.all =0;
CpuTimer0Regs.TPRH.all=0;
//设置Timer0的状态为停止状态
CpuTimer0Regs.TCR.bit.TSS =1;
//重装载使能
CpuTimer0Regs.TCR.bit.TRB =1;
//重置中断计数器
CpuTimer0.InterruptCount =0;
(3)定时器的设置
//定时器配置
ConfigCpuTimer(&CpuTimer0,Freq,Period);
(4)开启定时器中断功能,并使能定时器
//开启定时器中断功能并使能定时器
//设置Timer0的中断入口地址为中断向量表的INT0
PieVectTable.TINT0=&TIM0_IRQn;
//开启定时器功能
CpuTimer0Regs.TCR.bit.TSS=0;
//开启CPU第一组中断并使能第一组中断的第7个小中断,即为Timer0->INT1.7
IER |=M_INT1; //使能CPU中断1(INT1)
PieCtrlRegs.PIEIER1.bit.INTx7=1;
//使能总中断
EINT;
ERTM; //当使用仿真器调试时可开启 DEBUG 中断,即使用 ERTM 语句
EDIS; //开启写保护
(5)编写定时器中断服务函数
interrupt void TIM0_IRQn(void)
{
EALLOW;
PieCtrlRegs.PIEACK.bit.ACK1=1; //清除中断标志位
EDIS;
}
定时器TIMER0的函数配置
//Timer0 初始化函数
//Freq: CPU时钟频率
//Period:定时器周期值,单位us
//T=Freq*Period/150M (s)
void TIM0_Init(float Freq, float Period)
{
EALLOW; //关闭写保护
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // CPU Timer 0
//初始化定时器参数-> 可用InitCpuTimers();直接替代
//指向Timer0的寄存器地址
CpuTimer0.RegsAddr=&CpuTimer0Regs;
//周期寄存器值得配置
CpuTimer0Regs.PRD.all=0xFFFFFFFF;
//设置Timer0的预标计数器值为0
CpuTimer0Regs.TPR.all =0;
CpuTimer0Regs.TPRH.all=0;
//设置Timer0的状态为停止状态
CpuTimer0Regs.TCR.bit.TSS =1;
//重装载使能
CpuTimer0Regs.TCR.bit.TRB =1;
//重置中断计数器
CpuTimer0.InterruptCount =0;
//定时器配置
ConfigCpuTimer(&CpuTimer0,Freq,Period);
//开启定时器中断功能并使能定时器
//设置Timer0的中断入口地址为中断向量表的INT0
PieVectTable.TINT0=&TIM0_IRQn;
//开启定时器功能
CpuTimer0Regs.TCR.bit.TSS=0;
//开启CPU第一组中断并使能第一组中断的第7个小中断,即为Timer0->INT1.7
IER |=M_INT1; //使能CPU中断1(INT1)
PieCtrlRegs.PIEIER1.bit.INTx7=1;
//使能总中断
EINT;
ERTM; //当使用仿真器调试时可开启 DEBUG 中断,即使用 ERTM 语句
EDIS; //开启写保护
}
interrupt void TIM0_IRQn(void)
{
EALLOW;
PieCtrlRegs.PIEACK.bit.ACK1=1; //清除中断标志位
EDIS;
}
定时器TIMER1配置
void TIM1_Init(float Freq, float Period)
{
EALLOW; //关闭写保护
SysCtrlRegs.PCLKCR3.bit.CPUTIMER1ENCLK = 1; // CPU Timer 1
//初始化定时器参数
InitCpuTimers();
//定时器的配置
ConfigCpuTimer(&CpuTimer1,Freq,Period);
//设置定时器的中断入口地址
PieVectTable.XINT13=&TIM1_IRQn;
//开启定时器
CpuTimer1Regs.TCR.bit.TSS =0;
//使能CPU中断(INT13)
IER |=M_INT13;
//使能总中断
EINT;
ERTM; //当使用仿真器调试时可开启 DEBUG 中断,即使用 ERTM 语句
EDIS; //开启写保护
}