一、系统复位及初始化
1、加电复位 POR 和 加电清零PUC
(1)、加电复位 POR 产生条件
·为器件加电
·RST# / NMI 引脚配置为复位模式(WDTNMI = 0)(默认配置)时,引脚上产生低电平信号 。
·当PORON = 1时(SVSCTL寄存器) ,一个SVS低电平条件。
注意 :产生POR复位后尽量评估看门狗计时器、振荡器故障 和 闪存标志,以确定复位源。
(2)、加电清零 PUC 产生条件
·POR信号;当POR产生时,一定会产生 PUC。
·只在 安全装置模式中时的安全装置定时器过期。(即看门狗定时时间到及写入错误的安全键值)
·一个闪存存储器安全密钥违反。(正确应写入 0xA5)
·从0H 到 01FFH外设地址 (SFR区域 + 8/16位外设模块区域)范围内的一个CPU取指令。
2、欠压复位 BOR
欠压复位电路用于监测低电源电压,通过在通电或断电时触发 POR信号来复位器件。
如图, 当Vcc超过Vcc_start电平时POR信号变为有效状态。在Vcc 超过V(B_IT+)阈值并且经过延时T(BOR)之前,该信号一直保持有效状态。对于缓慢上升的Vcc,T(BOR)会自适应的变得更长。迟滞Vhys(B_IT-)确保电源电压必须降至V(B_IT-)以下才能通过欠压复位电路生成另一个POR信号。 BOR复位只能在不低于 POR电路最低电平Vmin的电源故障提供复位。
二、中断
中断有三个类型 :
· 系统复位
· (不)可屏蔽 NMI
· 可屏蔽中断
1、(不)可屏蔽中断 NMI
NMI中断不会被 通用中断使能位 GIE (状态寄存器SR中) 屏蔽,而是由单独的中断使能位NMIIE 、ACCVIE 、OFIE启用。当一个 NMI中断被接收时 ,所有NMI中断使能位都自动复位。程序从存储在 (不)可屏蔽中断向量 0FFFCh 中的地址开始执行。 用户软件必须设置所需的NMI中断使能位才能重新启用中断。
NMI中断的三个来源:
(1)、RST#/NMI 引脚配置为NMI模式(WDTNMI = 1)时,引脚上的边沿信号(由 WDTNMIES位设置触发的边沿 0 -- 上升沿 1 -- 下降沿)。
加电时,RST#/NMI引脚配置为 复位模式。 当设置为复位模式时,只要引脚保持低电平,CPU就保持在复位状态,输入变为高电平后,CPU在复位向量中存储的字地址 0FFFEh处开始执行程序,并且设置 RSTIFG标志。
配置为NMI功能时,在设置NMIIE位时,WDTNMIES位选择的信号沿会生成NMI中断。NMIIFG标志也会被置位。
(2)、振荡器发生故障。
晶体振荡器出现错误情况时,OFIFG被置位,通过设置 OFIE 启用对应NMI中断。然后通过NMI中断服务例程测试OFIFG标志,以确定NMI故障源
注意 :PUC信号可以触发振荡器故障,因为PUC将LFXT1切换到LF模式,从而关闭HF模式。PUC信号也会关闭XT2振荡器。
(3)、一个到闪存存储器的方位违反。
当出现闪存访问违法时,ACCVIFG标志被置位(位于闪存控制器FCTL3寄存器中)。通过设置ACCVIE位,可以启用对应的NMI中断。然后通过NMI中断服务例程测试ACCVIFG标志,以确定NMI是否由闪存访问违法引起
NMI中断时一个多源中断。NMI中断会自动复位 NMIIE 、OFIE 、ACCVIE中断使能位。用户NMI服务程序中根据应用程序需复位中断标志并重新启用中断使能位。 为防止出现嵌套NMI中断,不应在NMI中断服务例程中设置 ACCVIE 、NMIIE 和 OFIE使能位。
2、可屏蔽中断
可屏蔽中断时具有 中断功能的外设引起(包括间隔计时器模式下的看门狗计时器溢出)。
注意:在执行中断服务程序期间 ,GIE默认被 禁止,即不允许中断嵌套发生。当在中断服务程序中 设置 GIE = 1时,启用中断嵌套。启用后,任何中断都可打断该中断服务程序,无论中断优先级如何。
中断向量和上电起始地址位于 地址范围 0FFFFh -- 0FFC0h 内。用户使用相应中断服务例程的16位地址对向量进行编程 。 一个虚拟的中断服务例程只可包含RETI指令 。
3、中断嵌套过程
(1)A中断服务程序 未开中断 ,发生中断B
在 中断服务程序A 未开中断的情况下,不会立即响应B中断,需等待A执行完成返回后(GIE自动恢复),才进入B中断服务程序。
(2)、A中断服务程序 开中断 ,发生中断B和中断C
以上两种情况,会造成高优先级的中断处理延时,要解决这种情况,就需要允许中断的嵌套,即在所有中断入口处都加一句开中断的语句:_EINT(); ,恢复总的中断允许。中断嵌套被允许后,所有中断能够立即被执行,保证了时间的实时性要求。
注意:避免中断的不断嵌套造成堆栈溢出因而产生的复位现象
4、中断向量表
中断优先级固定,不可更改。
#ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define RESERVED0_VECTOR ".int00" /* 0xFFC0 Reserved Int. Vector 0 */ #else --------- 前 13个 均为 保留 #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define DAC12_VECTOR ".int14" /* 0xFFDC DAC12 */ #else #define DAC12_VECTOR (14 * 1u) /* 0xFFDC DAC12 */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define DMA_VECTOR ".int15" /* 0xFFDE DMA */ #else #define DMA_VECTOR (15 * 1u) /* 0xFFDE DMA */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define USCIAB1TX_VECTOR ".int16" /* 0xFFE0 USCI A1/B1 Transmit */ #else #define USCIAB1TX_VECTOR (16 * 1u) /* 0xFFE0 USCI A1/B1 Transmit */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define USCIAB1RX_VECTOR ".int17" /* 0xFFE2 USCI A1/B1 Receive */ #else #define USCIAB1RX_VECTOR (17 * 1u) /* 0xFFE2 USCI A1/B1 Receive */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define PORT1_VECTOR ".int18" /* 0xFFE4 Port 1 */ #else #define PORT1_VECTOR (18 * 1u) /* 0xFFE4 Port 1 */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define PORT2_VECTOR ".int19" /* 0xFFE6 Port 2 */ #else #define PORT2_VECTOR (19 * 1u) /* 0xFFE6 Port 2 */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define RESERVED20_VECTOR ".int20" /* 0xFFE8 Reserved Int. Vector 20 */ #else #define RESERVED20_VECTOR (20 * 1u) /* 0xFFE8 Reserved Int. Vector 20 */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define ADC12_VECTOR ".int21" /* 0xFFEA ADC */ #else #define ADC12_VECTOR (21 * 1u) /* 0xFFEA ADC */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define USCIAB0TX_VECTOR ".int22" /* 0xFFEC USCI A0/B0 Transmit */ #else #define USCIAB0TX_VECTOR (22 * 1u) /* 0xFFEC USCI A0/B0 Transmit */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define USCIAB0RX_VECTOR ".int23" /* 0xFFEE USCI A0/B0 Receive */ #else #define USCIAB0RX_VECTOR (23 * 1u) /* 0xFFEE USCI A0/B0 Receive */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define TIMERA1_VECTOR ".int24" /* 0xFFF0 Timer A CC1-2, TA */ #else #define TIMERA1_VECTOR (24 * 1u) /* 0xFFF0 Timer A CC1-2, TA */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define TIMERA0_VECTOR ".int25" /* 0xFFF2 Timer A CC0 */ #else #define TIMERA0_VECTOR (25 * 1u) /* 0xFFF2 Timer A CC0 */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define WDT_VECTOR ".int26" /* 0xFFF4 Watchdog Timer */ #else #define WDT_VECTOR (26 * 1u) /* 0xFFF4 Watchdog Timer */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define COMPARATORA_VECTOR ".int27" /* 0xFFF6 Comparator A */ #else #define COMPARATORA_VECTOR (27 * 1u) /* 0xFFF6 Comparator A */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define TIMERB1_VECTOR ".int28" /* 0xFFF8 Timer B CC1-6, TB */ #else #define TIMERB1_VECTOR (28 * 1u) /* 0xFFF8 Timer B CC1-6, TB */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define TIMERB0_VECTOR ".int29" /* 0xFFFA Timer B CC0 */ #else #define TIMERB0_VECTOR (29 * 1u) /* 0xFFFA Timer B CC0 */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define NMI_VECTOR ".int30" /* 0xFFFC Non-maskable */ #else #define NMI_VECTOR (30 * 1u) /* 0xFFFC Non-maskable */ #endif #ifdef __ASM_HEADER__ /* Begin #defines for assembler */ #define RESET_VECTOR ".reset" /* 0xFFFE Reset [Highest Priority] */ #else #define RESET_VECTOR (31 * 1u) /* 0xFFFE Reset [Highest Priority] */ #endif三、例程
1、 RST#/NMI 引脚触发 NMI中断
#include <msp430.h> /* * 上电初始化默认状态:RST#/NMI引脚 默认配置为 复位功能 * 本实例 :将RST#/NMI引脚 配置为 NMI功能 ,下降沿触发 * * RST#/NMI 引脚功能配置 及 中断边沿配置 在 看门狗控制寄存器WDTCTL中 * NMI中断使能 及 中断标志位 在 IE1 和 IFG1 寄存器中 * (另 闪存访问违例 及 振荡器故障 也可产生NMI中断 , * 如有需要使能对应中断位 ACCVIE 、OFIE 。在NMI中断服务程序中,判断 对应标志位) */ int main(void) { WDTCTL = WDTPW + WDTHOLD + WDTNMI + WDTNMIES; //WDTCTL = 0x5AE0; P1DIR |= 0x01; P1OUT &= ~0x01; IE1 |= NMIIE; __bis_SR_register(LPM0_bits); //CPU、MCLK被禁用。 } #pragma vector = NMI_VECTOR __interrupt void NMI_ISR(void) { volatile unsigned int i ,j; for(j=10;j>0;j--) { P1OUT ^= 0x01; for(i=20000;i>0;i--); } P1OUT &= ~0x01; //清除NMI中断 IFG1 &= ~NMIIFG; }