带你玩转MSP-ESP430G2(基础篇)----(十四)中断系统

玩转MSP-ESP430G2(基础篇)

(十三)中断系统

中断是暂停CPU正在运行的程序,转去执行相应的中断服务程序,完毕后返回被中断的程序继续运行的现象和技术。

中断源(中断分类)

中断首先要有中断源发出中断请求,并征得系统允许(屏蔽、优先权)后才会发生。转去执行中断服务程序前需要保护中断现场,执行完终端服务程序后恢复中断现场。

中断分为软件中断(内中断)和硬件中断(外中断)
而硬件中断又分为 非屏蔽中断和可屏蔽中断

中断种类

按中断源的响应是否受控

  • 系统复位 POR、PUC、BOR、SVS
  • 非屏蔽中断 NMI、晶振失败、FLASH失败、DMA
  • 可屏蔽中断 TA、BT、COMP、UART

非屏蔽中断的控制机制

在这里插入图片描述
**可屏蔽中断的控制机制(分控位、总控位)

在这里插入图片描述
按中断源来自MCU外部引脚还是内部

  • 由外部引脚(RST/NMI)产生的中断,为外中断
  • 由MCU内部模块产生的中断,为内中断

中断源、标志和矢量
在这里插入图片描述
**状态寄存器SR(Status Register)

15-9876543210
保留VSCG1SCG0OSCOFFCPUOFFGIENZC

GIE:可屏蔽中断屏蔽位(General Interrupt Enable Bit)
置位1:允许所有可屏蔽中断
置位2:禁止所有可屏蔽中断

开/关总中断控制位指令
(Disable/enable general interrupt bit)

指令格式执行操作VZNC
_DINT();0→GIE****
_EINT();1→GIE
实现中断嵌套需要注意以下几点
  1. 430默认的是关闭中断嵌套的,一定要中断嵌套的话,就必须在中断服务程序中打开总中断msp430的指令中,_DINT()和_EINT()分别指关和开总中断。
  2. 当进入中断服务程序时,只要不在中断服务程序中再次开中断,则总中断是关闭的,此时来中断不管是比当前中断的优先级高还是低都不执行;
  3. 若在中断服务程序A中开了总中断,则可以响应后来的中断B(不管B的优先级比A高还是低),B执行完再继续执行A。
    注意:进入中断服务程序B后总中断同样也会关闭,如 果B中断程序执行时需响应中断C,则此时也要开总中断,若不需响应中断,则不用开中断,B执行完后跳出中断程序进入A程序时,总中断会自动打开;
  4. 若在中断服务程序中开了总中断,后来的中断同时有多个,则会按优先级来执行,即中断优先级只有在多个中断同时到来时才起做用!中断服务不执行抢先原则。
  5. 对于单源中断,只要响应中断,系统硬件自动清中断标志位,对于TA/TB定时器的比较/捕获中断,只要访问TAIV/TBIV标志位倍被自动清除;
  6. 对于多源中断要手动清标志位,比如P1/P2口中断,要手工清除相应的标志,如果在这种中断用"EINT();"开中断,而在打开中断前没有清标志,就会有相同的中断不断嵌入,而导致堆栈溢出引起复位,所以在这类中断中必须先清标志再打开中断开关.
// Interrupt Vectors (offset from 0xFFE0)
#define PORT1_VECTOR 	(2*2u)/*0xFFE4 Port 1 */
#define PORT2_VECTOR 	(3*2u) /*0xFFE6 Port 2 */
#define ADC10 VECTOR	 (5*2u) /*0xFFEA ADC10 */
#define USCIAB0TX VECTOR (6*2u) /*0xFFEC USCI A0/B0 Transmit
*/
#define USCIABORX VECTOR  (7*2u) /*0xFFEE USCI A0/B0 Receive
*/
#define TIMERO A1_VECTOR	 (8*2u) /*0xFFF0 Timer0)A CC1, TA0 */
#define TIMERO A0 VECTOR 	(9*2u) /*0xFFF2 Timer0 A CCO */
#define WDT VECTOR 	(10 *2u) /*0xFFF4 Watchdog Timer */
#define COMPARATORA_VECTOR 	(11 *2u)/* 0xFFF6 Comparator A */
#define TIMER1_A1_VECTOR 	(12*2u) /*0xFFF8 Timer1_A CC1-4, TA1
*/
#define TIMER1 A0 VECTOR 	(13 *2u) /*0xFFFA Timer1_A CCO */
#define NMI_VECTOR 	(14*2u) /*0xFFFC Non-maskable */
#define RESET VECTOR 	(15*2u)/*0xFFFE Reset [Highest Priority]
*/

作为中断申请的端口P1和P2引脚,应设置下列相应寄存器:

  1. 设置功能选择寄存器PxSEL.y对应位为0(基本1/0功能)
  2. 设置方向选择寄存器PxDIR.y对应位为0(输入)
  3. 设置PxlES.y选择中断源有效信号类型是上升还是下降沿
  4. 设置PxIE.y打开分中断允许位
  5. 设置GIE=1打开总中断允许位

中断程序中:

  1. 由于端口的8个引脚共用一个中断向量,当有多个引脚做中断源时,需利用PxIFG判断产生中断的中断源引脚
  2. 在中断子程中应清除PxIFG相应的中断标志位

中断编程步骤:
编程前应了解可屏蔽硬中断的响应过程,了解有关的寄存器和引脚与中断响应过程的关系
a. 主程序做好相关设置:中断源发出中断申请时CPU能够响应的准备工作
b. 中断程序:处理与中断源有关的关键任务
c. 设置中断向量:根据中断源在中断向量表的相应位置,设置中断向量

C语言中的中断程序结构
_interrupt void intName(void)
{

}
  1. 定义了一个函数名为intName的中断程序
  2. 结构上与普通函数的区别
    使用了关键字_interrupt
    使得反汇编中断程序时返回的语句时RETI而不是RET
C语言程序设置中断的方法

在中断程序前使用#pragma vector=偏址语句
将中断程序的入口地址放入到FFE0+偏址中断向量表中

#pragam vector=N*2 //使用中断类型号计算偏址
_interrupt void intName(void)
{

}
#pragma vector=PORT1_VECTOR//使用符号表示的中断偏址
_interrupt void intName(void)
{

}
C语言:开关总中断控制位函数

(disable/enable general interrupt bit)

函数名称功能包含在
_disable_interrupt()0→GIEintrinsics.h
_enable_interrupt()1→GIEintrinsics.h
用C语言编写中断程序的方法1
  • 包含intrinsics.h文件中
  • 使用_disable_interrupt()和_enable_interrupt()
#include"in430.h"
#include "intrinsics.h"
int main( void )
{
//Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
	_disable_interrupt(); 	//关总中断控制(非必要)
	… //主程序初始化准备工作
	…
	_enable_interrupt();	//开总中断控制
while(1){ }; //主程序循环
}
#pragma vector=数字或符号表示的偏址//中断向量设置
_interrupt void port_int(void) //中断子程
{
	....
}
....
#include "instrinsics.h"
....
/*Deprecated,please use "_disable_interrupt"instead.*/
#define	_DINT()	_disable_interrupt()

/*Deprecated,please use "_disable_interrupt"instead.*/
#define _EINT() _disable_interrupt()

/*Deprecated,please use "_disable_interrupt"instead.*/
#define _NOP() _disable_interrupt()
....
用C语言编写中断程序方法2

包含in430.h文件
使用DINT()和EINT()

#include"in430.h"
int main( void )
{
	//Stop watchdog timer to prevent time out reset
	WDTCTL = WDTPW + WDTHOLD;
	_DINT( );	 //关总中断控制(非必要)
			//主程序初始化准备工作
	….…
	_EINT( ); 	//开总中断控制
while(1){ }; 	//主程序循环
}
	#pragma vector=数字或符号表示的偏址//中断向量设置
	interrupt void port_int(void) //中断子程
{
....
}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值