前言:
单片机的中断是由单片机片内的中断系统来实现的。当中断请求源(简称中断源)发出中断请求时,如果中断请求被允许的话,单片机暂时中止当前正在执行的主程序,转到中断服务程序处理中断服务请求,处理完中断服务请求后,再回到原来被中止的程序之处(断点),继续执行被中断的主程序。
下表中的以下三种异常被称为中断:
1、FE级不可屏蔽中断(FENMI)
一个FENMI中断被确认,即使另一个FE级中断- FEINT-已经被确认生成的。
-即使CPU系统寄存器PSW,也会确认FENMI中断,Np = 1。
-从FENMI中断返回是不可能的,恢复也是不可能的。
2、FE级可屏蔽中断(FEINT)
—如果CPU系统注册PSW,则可以确认FEINT。Np = 0。如果是PSW则被屏蔽,NP = 1。
-从佯攻中断返回是可能的,恢复也是可能的。
3、EI级屏蔽中断(EIINT)
如果FE级中断(FENMI或FEINT)没有被确认,则可以确认EIINT中断生成。
中断概述
中断的优先级:
中断控制寄存器可以根据请求设置可屏蔽中断的16个优先级。
外部中断检测方法(TNMI/INTPm):
检测外部中断的方法(TNMI/INTPm)可以从五种类型中选择:
上升边,下降边,两边都是,低水平,高水平。
直接分支方法或表引用方法可通过寄存器设置进行选择。
1.1、FE级不可屏蔽中断
(1)优先级
请参见上表异常源列表。
(2)返回PC
不可能从FE不可屏蔽中断中返回或恢复。
(3)返回指令
无。
1.2、FE级可屏蔽中断
(1)优先级
请参见上表异常源列表。
(2)返回PC
FERET指令从中断处理例程返回的返回PC就是来自的PC
当程序暂停时(当前PC)。
(3)返回指令
FERET.
1.3、EI级可屏蔽中断
(1)中断命名规则
中断请求信号名的组成,它们被分配的中断控制寄存器和这些寄存器中的位遵循特殊规则。
在下面的特定中断请求的名称表示为<name>。
中断请求名称:INT<name>
前缀“INT”被附加到<name>。
中断请求控制寄存器:IC<name>
前缀“IC”被附加到<name>。
16位寄存器IC<name>也可以以字节单位访问:
—IC<name>寄存器的低字节(bits [7:0]): IC<name>L
后缀“L”被附加到寄存器名称IC<name>。
IC<name>寄存器的高字节(bits [15:8]): IC<name>H
后缀“H”被附加到寄存器名称IC<name>。
中断控制寄存器位名:CT<name>, RF<name>, MK<name>, TB<name>,P3<name>, P2<name>, P1<name>, P0<name>位前缀“CT”,“RF”,“MK”,“TB”,“P3”,“P2”,“P1”,或“P0”被附加到中断后面 <name>。
例子:
命名来自TAUD0通道(<name> = TAUD0I2)的通道2的中断请求INTTAUD0I2相关的中断控制寄存器是Ictaud0i2、ictaud0i2l、ictaud0i2h这个寄存器中的位是Cttaud0i2、rftaud0i2、mktaud0i2、tbtaud0i2、p3taud0i2、p2taud0i2、P1TAUD0I2, P0TAUD0I2。
1.4、中断源寄存器
1.4.1、FE级别不可屏蔽中断源
1.4.1.1、WDTNMIF -- FE级别信息中断寄存器
Bit position |
Bit Name |
Function |
2 |
WDTA1NMIF |
WDTA1NMI标志 0:没有WDTA1NMI 1:发生WDTA1NMI |
1 |
WDTA0NMIF |
WDTA0NMI标志 0:没有WDTA0NMI 1:发生WDTA0NMI |
0 |
TNMIF |
NMI引脚输入信号标志 0:没有发生TNMI 1:发生TNMI |
1.4.1.2、WDTNMIFC -- FE级别清除信息中断寄存器
Bit position |
Bit Name |
Function |
2 |
WDTA1NMIFC |
WDTA1NMI清除标志 0:无 1:清除 |
1 |
WDTA0NMIFC |
WDTA0NMI清除标志 0:无 1:清除 |
0 |
TNMIFC |
NMI引脚输入信号清除标志 0:无 1:清除 |
1.5、中断控制器控制寄存器
1.5.1、ICxxx -- EI级别中断控制寄存器
Bit position |
Bit Name |
Function |
|
15 |
CTxxx |
该位表示中断检测的类型,此位为只读。 0:边缘检测 1:电平检测 当写入8位或16位单位时,请在重置后写入值。 |
|
12 |
RFxxx |
这是一个中断请求标志。 RFxxx位可从程序中写入。设置RFxxx位为1生成一个EI级可屏蔽中断n (EIINTn),像中断请求被确认。 0:没有中断请求。 1:表示中断请求。 |
|
输入接口 |
功能 |
||
边缘检测(CTxxx = 0) |
这个位在中断时自动清除 请求被CPU内核确认。可以设置并被软件清除。 |
||
电平检测(CTxxx = 1) |
软件无法设置或清除此位。它可以只有被读。当中断请求被清除时,它不会被清除被CPU内核确认。 |
||
7 |
MKxxx |
0:启用中断处理 1:禁用中断处理 |
|
6 |
TBxxx |
该位用于选择中断向量方式。 0:直接跳转到从优先级确定的地址 1:参考表格 |
|
3 - 0 |
P3xxx to P0xxx |
这些位指定中断优先级为16个级别中的一个,0是最高的 15是最低的。 当多个EI级中断请求同时发出时,中断从这些位中具有最高优先级设置的源中选择和传送到CPU核心,首先进行维修。当P3xxx到P0xxx位指定同时发生的中断请求具有相同的优先级通道号较低的源具有优先级。 |
1.5.2、IMRm -- EI级别中断掩码寄存器
Bit position |
Bit Name |
Function |
31 - 0 |
IMRmEIMK (m×32+31) to IMRmEIMK (m×32+0) |
0:启用中断服务 1:禁用中断服务 |
1.5.3、FNC -- FE级别NMI状态寄存器
Bit position |
Bit Name |
Function |
12 |
FNRF |
中断请求标志 0:无中断请求 1:有中断请求 |
1.5.4、FIC -- FE级别可屏蔽中断状态寄存器
Bit position |
Bit Name |
Function |
12 |
FIRF |
中断请求标志 0:无中断请求 1:有中断请求 |
1.6、EI级别可屏蔽中断选择寄存器
1.6.1、SELB_INTC1 -- INTC1中断选择寄存器
Bit position |
Bit Name |
Function |
12 |
SELB_INTC1_12 |
中断通道选择 0: INTADCA0I2(通道20)INTCSIH0IJC(通道32) 1: INTCSIH0IJC_1 (通道20)INTADCA0I2_2(通道32) |
11 |
SELB_INTC1_11 |
中断通道选择 0: INTTAUD0I14 (通道15)INTCSIH3IJC(通道161) 1: INTCSIH3IJC_1 (通道15)INTTAUD0I14_2(通道161) |
10 |
SELB_INTC1_10 |
中断通道选择 0: INTTAUD0I12 (通道14)INTCSIH3IRE(通道160) 1: INTCSIH3IRE_1 (通道14)INTTAUD0I12_2(通道160) |
9 |
SELB_INTC1_9 |
中断通道选择 0: INTTAUD0I10 (通道13)INTCSIH3IR(通道159) 1: INTCSIH3IR_1 (通道13)INTTAUD0I10_2(通道159) |
8 |
SELB_INTC1_8 |
中断通道选择 0: INTTAUD0I2 (通道9)INTCSIH3IC(通道158) 1: INTCSIH3IC_1 (通道 9)INTTAUD0I2_2(通道158) |
7 |
SELB_INTC1_7 |
中断通道选择 0: INTTAUD0I8(通道12)INTCSIH2IJC(通道135) 1: INTCSIH2IJC_1 (通道12)INTTAUD0I8_2(通道135) |
6 |
SELB_INTC1_6 |
中断通道选择 0: INTTAUD0I6 (通道11)INTCSIH2IRE(通道134) 1: INTCSIH2IRE_1 (通道11)INTTAUD0I6_2(通道134) |
5 |
SELB_INTC1_5 |
中断通道选择 0: INTTAUD0I4(通道10)INTCSIH2IR(通道133) 1: INTCSIH2IR_1 (通道10)INTTAUD0I4_2(通道133) |
4 |
SELB_INTC1_4 |
中断通道选择 0: INTTAUD0I0 (通道8)INTCSIH2IC(通道132) 1: INTCSIH2IC_1 (通道8)INTTAUD0I0_2(通道132) |
3 |
SELB_INTC1_3 |
中断通道选择 0: INTCSIG0IR (通道28)INTCSIH1IJC(通道119) 1: INTCSIH1IJC_1 (通道28)INTCSIG0IR_2(通道119) |
2 |
SELB_INTC1_2 |
中断通道选择 0: INTCSIG0IR (通道27)INTCSIH1IJC(通道118) 1: INTCSIH1IJC_1 (通道27)INTCSIG0IR_2(通道118) |
1 |
SELB_INTC1_1 |
中断通道选择 0: INTTAP0IVLY0 (通道17)INTCSIH1IR(通道117) 1: INTCSIH1IR_1 (通道17)INTTAP0IVLY0 _2(通道117) |
0 |
SELB_INTC1_0 |
中断通道选择 0: INTTAP0IPEK0 (通道16)INTCSIH1IC(116通道) 1: INTCSIH1IC_1(通道16)INTTAP0IPEK0 _2(116通道) |
1.6.2、SELB_INTC2 -- INTC2中断选择寄存器
Bit position |
Bit Name |
Function |
10 |
SELB_INTC2_10 |
中断通道157的选择 0: INTTAUB0I15 1: INTPWGA31 |
9 |
SELB_INTC2_9 |
中断通道155的选择 0: INTTAUB0I13 1: INTPWGA30 |
8 |
SELB_INTC2_8 |
中断通道153的选择 0: INTTAUB0I11 1: INTPWGA26 |
7 |
SELB_INTC2_7 |
中断通道151选择 0: INTTAUB0I9 1: INTPWGA19 |
6 |
SELB_INTC2_6 |
中断通道149选择 0: INTTAUB0I7 1: INTPWGA18 |
5 |
SELB_INTC2_5 |
中断通道147选择 0: INTTAUB0I5 1: INTPWGA17 |
4 |
SELB_INTC2_4 |
中断通道145选择 0: INTTAUB0I3 1: INTPWGA16 |
3 |
SELB_INTC2_3 |
中断通道88的选择 0: INTENCA0I1 1: INTPWGA7 |
2 |
SELB_INTC2_2 |
中断通道87选择 0: INTENCA0I0 1: INTPWGA6 |
1 |
SELB_INTC2_1 |
中断通道86的选择 0: INTENCA0IUD 1: INTPWGA5 |
0 |
SELB_INTC2_0 |
中断通道85选择 0: INTENCA0IOV 1: INTPWGA4 |
1.7、中断返回
要从中断处理中返回,执行对应的返回指令(EIRET或FERET)每个相关的中断级别。
当环境保存在堆栈或类似的对象中时,必须在执行之前恢复上环境返回指令。
EIRET指令用于从EI级可屏蔽中断处理和FERET返回指令用于从FE级可屏蔽中断处理返回。 当执行EIRET或FERET指令时,CPU执行以下处理和然后将其控制传递给返回的PC地址:
(1)从EI级异常服务例程返回时,PC和PSW值为ON返回值从EIPC和EIPSW寄存器加载。
当从服务例程返回FE级别异常时,PC和PSW值为从返回值FEPC和FEPSW寄存器加载。
(2)将控制传递到被加载的返回PC和PSW所指示的地址。
(3)当EP = 0, INTCFG。ISPC = 0,表示CPU更新ISPR寄存器。
1.8、中断操作
可以为EIINT的每个各自的中断通道指定中断屏蔽。中断屏蔽为执行以下寄存器设置。
ICxxx。MKxxx位也可以通过相应的IMRmEIMKn位来读写IMRm寄存器。中断掩码状态反映在ICxxx寄存器和IMRm中寄存器。
例程:
1、TAUB定时器中断
/******************************************************************************
* Function Name : void R_TAUB_Init( void )
* Description : This function initialize TAUB (ch.0).
* Argument : none
* Return Value : none
******************************************************************************/
void R_TAUB_Init( void )
{
/* Set the interrupt flags */
MKTAUB0I0 = 1U;
RFTAUB0I0 = 0U;
#ifdef USE_TABLE_REFERENCE_METHOD
TBTAUB0I0 = 1U;
#else
TBTAUB0I0 = 0U;
#endif
TAUB0.TPS = 0x3333U; /* PCLK(40MHz) / 8 -> 5MHz */
TAUB0.CDR0 = 5000U - 1U; /* INTTAUBnIm cycle = count clock cycle * (TAUBnCDRm + 1) */
TAUB0.CMOR0 = 0x0000U;
TAUB0.CMUR0 = 0x00U;
TAUB0.TOM &= 0xFFFEU;
TAUB0.TOC &= 0xFFFEU;
TAUB0.TOL &= 0xFFFEU;
TAUB0.TDE &= 0xFFFEU;
TAUB0.TDL &= 0xFFFEU;
TAUB0.TOE &= 0xFFFEU;
TAUB0.RDE &= 0xFFFEU;
TAUB0.RDS &= 0xFFFEU;
TAUB0.RDM &= 0xFFFEU;
TAUB0.RDC &= 0xFFFEU;
MKTAUB0I0 = 0U; /* Enable INTTAUB0I0 interrupt */
}
1.CAN中断
/******************************************************************************
** Function: CAN_interrupt_enable
** Description: This function enables the error table interrupt for CAN
** Parameter : None
** Return: None
******************************************************************************/
void CAN_interrupt_enable(void)
{
/* Set interrupt flags. */
INTC1MKRCANGERR0 = 1U;
INTC1RFRCANGERR0 = 0U;
INTC1TBRCANGERR0 = 0U;
INTC1MKRCAN0ERR = 0U;
INTC1RFRCAN0ERR = 0U;
INTC1TBRCAN0ERR = 1U;
INTC1MKRCAN0TRX = 1U;
INTC1RFRCAN0TRX = 0U;
INTC1TBRCAN0TRX = 0U;
RSCAN0GCTR &= ~R_CAN_GMDC_MASK; /* GMDC[1:0] = 00B */
while ((RSCAN0GSTS & R_CAN_GRSTSTS_ON) != 0UL)
{
__asm( "nop");
}
RSCAN0C0CTR &= ~R_CAN_CHMDC_MASK; /* CHMDC[1:0] = 00B */
while ((RSCAN0C0STS & R_CAN_CRSTSTS_ON) != 0UL)
{
__asm( "nop");
}
RSCAN0C1CTR &= ~R_CAN_CHMDC_MASK; /* CHMDC[1:0] = 00B */
while ((RSCAN0C1STS & R_CAN_CRSTSTS_ON) != 0UL)
{
__asm( "nop");
}
RSCAN0C2CTR &= ~R_CAN_CHMDC_MASK; /* CHMDC[1:0] = 00B */
while ((RSCAN0C2STS & R_CAN_CRSTSTS_ON) != 0UL)
{
__asm( "nop");
}
RSCAN0RFCC0 = 0x0000F703;
RSCAN0RFCC1 = 0x0000F703;
RSCAN0RFCC2 = 0x0000F703;
INTC1P0RCAN0REC = 0;
INTC1P1RCAN0REC = 0;
INTC1P2RCAN0REC = 0;
INTC2P0RCAN1REC = 1;
INTC2P1RCAN1REC = 1;
INTC2P2RCAN1REC = 1;
INTC2P0RCAN2REC = 1;
INTC2P1RCAN2REC = 1;
INTC2P2RCAN2REC = 1;
INTC1MKRCANGRECC0 = 0U;
INTC1RFRCANGRECC0 = 0U;
INTC1TBRCANGRECC0 = 1U;
}
3、ADC中断
/******************************************************************************
** Function: ADC_interrupt_enable
** Description: This function enables the error table interrupt for ADCA0
** Parameter : None
** Return: None
******************************************************************************/
void ADC_interrupt_enable(void)
{
INTC1MKADCA0I0 = 1U;
INTC1TBADCA0I0 = 1U;
INTC1RFADCA0I0 = 0U;
/* ErrorInterrupt for ADCA0 enabled */
INTC2TBADCA0ERR = 1u; /* Error table interrupt is enabled by setting the table bit to 1 */
INTC2MKADCA0ERR = 0u; /* Error interrupt is unmasked by setting the mask bit to 0 */
INTC2RFADCA0ERR = 0U;
}