系列文章目录
对28335的中断配置、运行机制及传输速率了解是很有必要的,本文就F28335的中断的简介与配置进行简要说明。
文章目录
一、问题简述
使用串口F28335的SCIB 在接收字符中断的时候,主程序一直在运行,若在此时对程序的运行模式等进行操作(切换到SCIA进行发送处理操作),将可能会使得程序跳出原本中断的模式(即SCIB接收中断模式)。原因使用串口波特率数据传输过程中,传输速度比较慢,CPU主频运行速度很高,在接收下一个字符中断产生之前,主程序可能会在这个间隙运行到模式切换的语句,从而导致程序跳出了原本的模式。因此对28335的中断配置、运行机制及传输速率了解是很有必要的,本文就F28335的中断的简介与配置进行简要说明。
二、F28335中断简述
F28335有很多外设资源,相对应的中断源也有很多。
F28335的中断源可分为片内外设中断源
:PWM、CAP、QEP、定时器等;
片外中断源
:外部中断输入引脚XINT1、XINT2引入的外部中断源。
这些中断源将中断请求信号传递给内核就需要中断线,F28335的中断线是有限的。F28335内部有16个中断线,其中包括2个不可屏蔽中断(RESET和NMI)
与14个可屏蔽中断
。可屏蔽中断通过相应的中断使能寄存器使用或者禁止产生的中断,在这14个可屏蔽中断中,其中定时器1和定时器2产生的中断请求通过INT13、INT14中断
线到达CPU,这两个中断已经预留给实时操作系统,因此剩下的12个可屏蔽中断
可供外部中断和处理器内部单元使用。
1.中断简述的图片描述
2.中断管理模块PIE
从上面的中断概述和图片看出(INT1 to INT12)12个可屏蔽中断与96个中断之间通过PIE(Peripheral Interrupt Expansion (PIE) Block) 进行连接。PIE 模块用于将多个中断源多路复用为一组较小的中断输入。 PIE 模块最多可支持 96 个外设中断。 在 F28335 上,外设使用了 96 个可能的中断中的 58 个。 96 个中断被分组为 8 个块,每组被连接到 12 个 CPU 中断线中的 1 个(INT1 到 INT12),如下图所示。
上面是PIE外设中断表响应的优先级为
- INT1>INT2>……INT12
- INTx.1>INTx.2>……>INTx.8
这96个中断中的每一个都由其自己的向量支持,该向量存储在一个专用 RAM 块中,可由用户覆盖, 处理中断时 CPU 会自动获取向量(同时所有中断的固定地址TI的官方程序中已经通过命名的方式为我们定义好了,直接调用即可)。 获取向量并保存关键 CPU 寄存器需要 8 个 CPU 时钟周期。因此 CPU 可以快速响应中断事件。 中断的优先级由硬件和软件控制。 每个单独的中断都可以在 PIE 块内启用/禁用。
3. PIE模块的响应机制
如前文所述传入CPU总中断12组之一的均可分为8个子中断,由PIE模块进行响应哪一个中断,其中:
IFR(12:1):CPU中断标志寄存器
,若可屏蔽中断挂起(等待CPU允许),相应
中断标志位置1。
IER(12:1):CPU中断使能寄存器
,若使能某个中断,将相应位置1。
PIEACKx : PIE Interrupt Acknowledge Register
, 对应12组可屏蔽中断,如果相应的PIEACKx位清零,PIE向CPU申请中断;如果PIEACKx置1,PIE将等待到相应的PIEACKx清零才向CPU申请中断。PIE通过对PIEACKx的位控制来控制每1组中只有1个中断能被响应,一旦响应后,就需要将PIEACKX相应为清零,以让它能够响应该组中后边过来的中断。
PIEIERx(8:1):PIE中断使能寄存器
,置1使能(与IER类似)。
PIEIFRx(8:1):PIE中断标志寄存器
,当相应的中断触发后,对应中断标志位置1。
三 中断开发流程及配置简介
下图是TI可屏蔽中断的操作流程,中断的现场保护机制的细节描述可以查阅TI官方文档和计算机操作系统进行学习了解。
4 中断配置实例简介
因为所有的中断都有自己固定的地址,TI公司通过命名的方式与中断的响应的地址对应好了,我们可以直接使用名称,或者定义自己便于阅读的名称(因为我们要初始化中断向量表)。
4.1 中断配置实例简介
我们平常使用的中断基本由PIE中断模块管理,本次对定时器0(Time 0)的中断配置进行简介(采用研旭的开发板例程说明(写的非常详细,流程上是按照PIE模块的响应机制进行配置的,对照上面的中断简介和代码注释可以很清楚的了解中断的配置流程))
#include "DSP2833x_Device.h" // DSP2833x 头文件
#include "DSP2833x_Examples.h" // DSP2833x 例子相关头文件
//28335有88个GPIO,分为A、B、C三组,一组是32个GPIO,A组0~31,B组32~63,C组是64~87。对每一位进行操作。
#define LED1 GpioDataRegs.GPADAT.bit.GPIO0 //宏定义GPA组的GPIO0为LED1
#define LED2 GpioDataRegs.GPADAT.bit.GPIO1 //宏定义GPA组的GPIO1为LED2
#define LED3 GpioDataRegs.GPADAT.bit.GPIO2 //宏定义GPA组的GPIO2为LED3
#define LED4 GpioDataRegs.GPADAT.bit.GPIO3 //宏定义GPA组的GPIO3为LED4
#define LED5 GpioDataRegs.GPADAT.bit.GPIO4 //宏定义GPA组的GPIO4为LED5
interrupt void ISRTimer0(void); //声明定时器TIME0中断()
void configtestled(void); //声明GPIO配置
void main(void)
{
// 步骤 1. 初始化系统控制:
// 设置PLL, WatchDog, 使能外设时钟
// 下面这个函数可以从DSP2833x_SysCtrl.c文件中找到..
InitSysCtrl();
//首先失能CPU级的中断,
DINT;
// 初始化PIE中断向量表,并使其指向中断服务子程序(ISR)
// 这些中断服务子程序被放在了DSP280x_DefaultIsr.c源文件中
// 这个函数放在了DSP2833x_PieVect.c源文件里面.
InitPieCtrl();
// 禁止CPU中断和清除所有CPU中断标志
IER = 0x0000;
IFR = 0x0000;
// PIE 向量表指针指向中断服务程(ISR)完成其初始化.
// 即使在程序里不需要使用中断功能,也要对 PIE 向量表进行初始化.
// 这样做是为了避免PIE引起的错误.
InitPieVectTable();
//EALLOW,EDIS是成对使用的,有些寄存器是受到保护的,不能任意写,
//EALLOW相当于去掉保护,对写保护的寄存器进行操作后 EDIS 是重新把这个寄存器保护起来的意思。
EALLOW;
PieVectTable.TINT0 = &ISRTimer0; //将定时器中断添加都中断向量表里
EDIS;
InitCpuTimers(); // 定时器初始化
//通过以下面程序就可以让定时器 0 每隔一段时间产生一次中断,这段时间的
//计算公式为: △T= Freq * Period /150000000(s);(其中 150000000 是
//CPU 的时钟频率,即 150MHz 的 时钟频率)针对此实验,Frep 为 150,Period 为 1000000,那么△T=1s。
ConfigCpuTimer(&CpuTimer0, 150, 500000);
StartCpuTimer0(); //开启定时器
IER |= M_INT1; //使能第一组中断,因为定时器0中断为PIE向量组的第一组
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; //使能总中断
PieCtrlRegs.PIEIER1.bit.INTx7 = 1; //使能第一组中断里的第七个中断--定时器中断
EINT; // 总中断 INTM 使能
ERTM; // 使能总实时中断
// 本例使用下面的GPIO配置
configtestled();
LED1=1; //初始化LED电平
DELAY_US(10); //延时
LED2=1; //初始化LED电平
DELAY_US(10); //延时
LED3=1; //初始化LED电平
DELAY_US(10); //延时
LED4=1; //初始化LED电平
DELAY_US(10); //延时
LED5=1; //初始化LED电平
DELAY_US(10); //延时
for(; ;); //For循环
}
interrupt void ISRTimer0(void)
{
// Acknowledge this interrupt to receive more interrupts from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; //0x0001赋给12组中断ACKnowledge寄存器,对其全部清除,不接受其他中断
CpuTimer0Regs.TCR.bit.TIF=1; // 定时到了指定时间,标志位置位,清除标志
CpuTimer0Regs.TCR.bit.TRB=1; // 重载Timer0的定时数据
LED1=~LED1; //取反
LED2=~LED2; //取反
LED3=~LED3; //取反
LED4=~LED4; //取反
LED5=~LED5; //取反
}
void configtestled(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; // GPIO复用为GPIO功能
GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; // GPIO设置为输出
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0; // GPIO复用为GPIO功能
GpioCtrlRegs.GPADIR.bit.GPIO1 = 1; // GPIO设置为输出
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0; // GPIO复用为GPIO功能
GpioCtrlRegs.GPADIR.bit.GPIO2 = 1; // GPIO设置为输出
GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0; // GPIO复用为GPIO功能
GpioCtrlRegs.GPADIR.bit.GPIO3 = 1; // GPIO设置为输出
GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 0; // GPIO复用为GPIO功能
GpioCtrlRegs.GPADIR.bit.GPIO4 = 1; // GPIO设置为输出
EDIS;
}
总结
本文通过查阅TI等相关资料,结合自己实际的学习及实验过程将中断过程做一个简单的记录和整理,加深记忆的同时也分享给需要的伙伴,不当之处也欢迎批评指正。