实验七、中断技术实验八、基本时钟和定时器实验报告实验七、中断技术一、实验目的1.了解中断原理,包括对中断源、中断向量、中断类型号、中断程序以及中断相应过程的理解;2.掌握单片机C语言中断程序设计方法。二、实验任务1.中断相应过程的理解(1)在中断子程序的定义之前,有一条预编译指令,观察其中的中断向量即可知道中断源。如本程序中的预编译指令是“#pragmavector=PORT1_VECTOR”可知中断源是P1.0~P1.7的八个引脚(准确说应该是P1.3)。在知道中断源的情况下,通过查表可以知道中断其对应的中断类型号是3。从程序中看出中断标志位用的是Bit3,所以将P1.3与按键连接。实验现象:当操作时,LED灯一直闪烁,当按下K4(与P1.3相连)时,灯停止闪烁,蜂鸣器响三声之后灯继续闪烁。(2)port_ISR被在满足条件的时候被硬件执行,不受软件操控,所以程序中并没有调用这个函数的语句但是仍可以被执行。中断响应过程:由于在该程序中用到的是可屏蔽中断,中断相应需要满足三个条件:中断总控位、中断分控位、中断源发出请求(即中断标志位置位)。在程序中已经将中断总控位和分控位置于允许状态所以只需要中断标志位置位即可,所以当在按键的下降沿时(由P1.3作为中断源),中断标志位被置位,即P1IFG&BIT3被置位,则中断子程被硬件自动运行,也就是函数port_ISR被执行。(3)当在运行完port_ISR时,如果中断标志位没有被清零则当跳出中断子程之后,由于依然满足中断相应的条件,所以中断会被继续执行,即中断将被一直运行下去。(4)在将PORT1_VECTOR改为PORT2_VECTOR之后在单片机上运行,发现按键不再能够使蜂鸣器响起,但是按键时原来闪烁的LED灯会暂停非常短暂的时间。这说明在按键时虽然程序暂时中断,但是并没有去执行中断子程里面的东西。在main函数入口处加入一断点时,按键时原来闪烁的LED灯会停止闪烁,并且程序会停止在断点处。这是由于将中断向量改为PORT2_VECTOR之后,在按下键的时候产生中断请求,但是由于PORT1的中断向量没有被预编译,所以不能够正确执行,所以中断子程不能够被执行。程序运行复位,所以程序会从最开始运行,所以在main函数的入口处加上断点时,运行程序,程序会停在断点处。(5)将原程序总中断的相关设置修改为以下:P2SEL&=~BIT5;P2SEL2&=~BIT5;P2OUT|=BIT5;P2REN|=BIT5;P2DIR&=~BIT5;P2IES|=BIT5;P2IFG&=~BIT5;P2IE|=BIT5;另外#pragmavector=PORT1_VECTOR需要修改为:#pragmavector=PORT2_VECTOR;中断子程中的清零指令修改为:P2IFG&=~BIT5;在硬件连接上需要将P2.5连接至KEY6。即可实现程序的修改。2.中断程序编程练习(1)程序设计思路当程序中没有收到中断请求时,L5灯循环闪烁,该功能可以由main函数中的循环实现,即设置某引脚为输出引脚,并控制L5,则实现L5的循环闪烁则很容易实现。要求中中断源有两个,P1.2和P1.7均可以触发中断。由于P1.2和P1.7两个引脚共享一个中断类型号,所以两个引脚的关于中断的设置相同,但是在中断子程中需要对两个中断进行判断,使得两个中断对应执行不同的指令。(2)硬件连接图(3)C语言程序#includeio430.h#includein430.hvoiddelay()//延时子函数{unsignedintj;for(j=0;j0xffff;j++);}voidblink1()//LED5闪烁控制子函数{P2OUT&=~BIT4;delay();P2OUT|=BIT4;delay();}voidblink2()//LED2闪烁控制子函数{for(inti=0;i2;i++){P2OUT&=~BIT1;delay();P2OUT|=BIT1;delay();};}voidBuzz()//蜂鸣器控制子函数{P2OUT&=~BIT2;delay();P2OUT|=BIT2;}intmain(void){//StopwatchdogtimertopreventtimeoutresetWDTCTL=WDTPW+WDTHOLD;//****输出端口设置***//P2SEL&=~(BIT4+BIT1+BIT2);P2SEL2&=~(BIT4+BIT1+BIT2);P2DIR|=(BIT4+BIT1+BIT2);P2OUT|=(BIT4+BIT1+BIT2);//****中断相关设置****//P1SEL&=~(BIT2+BIT7);P1SEL2&=~(BIT2+BIT7);//设置GPIO类型P1DIR&=~(BIT2+BIT7);//设置两个引脚为输入引脚P1REN|=(BIT2+BIT7);//上拉/下拉电阻允许P1OUT|=(BIT7+BIT2);//上拉电阻P1IES|=(BIT2+BIT7);//下降沿触发P1IFG&=~(BIT2+BIT7);//清零中断标志位P1IE|=(BIT2+BIT7);//中断分控允许_EINT();//中断总控允许for(;;){blink1();};//LED5循环闪烁}#pragmavector=PORT1_VECTOR__interruptvoidport_1()//中断子程{if((P1IFG&BIT2)!=0)//如果是P1.2产生的中断,执行下面的内容{Buzz();P1IFG&=~BIT2;}if((P1IFG&BIT7)!=0)//如果是P1.7产生的中断{blink2();P1IFG&=~BIT7;}}(3)思考题1)如果将按键K2,K7分别接在P2.1和P2.6上时,此时的中断向量应该变为了P2.0~P2.7八个端口。首先需要将上面程序main函数中的中断相关的设置改为下面://****中断相关设置****//P2SEL&=~(BIT1+BIT6);P2SEL2&=~(BIT1+BIT6);//设置GPIO类型P2DIR&=~(BIT1+BIT6);//设置两个引脚为输入引脚P2REN|=(BIT1+BIT6);//上拉/下拉电阻允许P2OUT|=(BIT6+BIT1);//上拉电阻P2IES|=(BIT1+BIT6);//下降沿触发P2IFG&=~(BIT1+BIT6);//清零中断标志位P2IE|=(BIT1+BIT6);//中断分控允许另外由于在上面的程序中用P2.1来控制LED2的闪烁,所以需要将控制LED2的闪烁的引脚改为P2.3。中断子程也应该进行相关的修改,如下所示:#pragmavector=PORT2_VECTOR__interruptvoidport_2()//中断子程{if((P2IFG&BIT1)!=0)//如果是P1.2产生的中断,执行下面的内容{Buzz();P2IFG&=~BIT1;}if((P2IFG&BIT6)!=0)//如果是P1.7产生的中断{blink2();P2IFG&=~BIT6;}}2)如果按键K2,K7分别接在P1.0和P2.4上,此时中断会用到P1.0~P1.7和P2.0~P2.1两个中断源。在进行程序修改时,也是应该对中断相关端口的设置和中断子程进行相关的修改。修改如下所示:对于中断相关端口的设置://****中断相关设置****//P1SEL&=~BIT0;P1SEL2&=~BIT0;//设置GPIO类型P1DIR&=~BIT0;//设置两个引脚为输入引脚P1REN|=BIT0;//上拉/下拉电阻允许P1OUT|=BIT0;//上拉电阻P1IES|=BIT0;//下降沿触发P1IFG&=~BIT0;//清零中断标志位P1IE|=BIT0;//中断分控允许P2SEL&=~BIT4;P2SEL2&=~BIT4;//设置GPIO类型P2DIR&=~BIT4;//设置两个引脚为输入引脚P2REN|=BIT4;//上拉/下拉电阻允许P2OUT|=BIT4;//上拉电阻P2IES|=BIT4;//下降沿触发P2IFG&=~BIT4;//清零中断标志位P2IE|=BIT4;//中断分控允许中断子程的修改如下:#pragmavector=PORT1_VECTOR__interruptvoidport_1()//中断子程1{Buzz();P1IFG&=~BIT0;}#pragmavector=PORT2_VECTOR__interruptvoidport_2()//中断子程2{blink2();P2IFG&=~BIT4;}另外由于原程序中用P2.4来控制LED5的闪烁,所以与这里中断中用到的引脚冲突,所以可以利用P2.5来控制LED5,即将原P2.4对应程序改为P2.5即可。3.采用事件标志处理中断(1)功能描述:在将P1.4和某一按键相连,P1.6与蜂鸣器相连的情况下,两个程序实现的功能是相同的,都是在没有按键的情况下程序不执行任何指令,在按下键时产生中断,蜂鸣器发出一声警报声。(2)两者在编程实现上的不同:程序L7_intA对于蜂鸣器控制的指令在中断子程中,即在按键时,执行中断子程,使蜂鸣器发出一声警报,然后跳出中断子程继续执行空的循环。而在程序L7_intB中,多了一个标志变量flag,在不执行中断子程中flag一直为0,虽然在main函数循环中存在对蜂鸣器引脚操作的指令,但是由于flag为0,所以不执行。当按键时,执行中断子程,在中断子程中只是将flag变量置位,然后跳出中断子程,由于此时flag为1,所以蜂鸣器会发出一声警报之后,flag又被置零。所以两个程序实现的功能是相同的,但是L7_intB中中断子程的执行时间较L7_intA短很多。(3)对任务二的程序进行改编,如下所示:#includeio430.h#includein430.hvoiddelay(){unsignedintj;for(j=0;j0xffff;j++);}voidblink1(){P2OUT&=~BIT4;delay();P2OUT|=BIT4;delay();}voidblink2(){for(inti=0;i2;i++){P2OUT&=~BIT1;delay();P2OUT|=BIT1;delay();};}voidBuzz(){P2OUT&=~BIT2;delay();P2OUT|=BIT2;}intflag1=0;intflag2=0;intmain(void){//StopwatchdogtimertopreventtimeoutresetWDTCTL=WDTPW+WDTHOLD;P2SEL&=~(BIT4+BIT1+BIT2);P2SEL2&=~(BIT4+BIT1+BIT2);P2DIR|=(BIT4+BIT1+BIT2);P2OUT|=(BIT4+BIT1+BIT2);P1SEL&=~(BIT2+BIT7);P1SEL2&=~(BIT2+BIT7);P1DIR&=~(BIT2+BIT7);P1REN|=(BIT2+BIT7);P1OUT|=(BIT7+BIT2);P1IES|=(BIT2+BIT7);P1IFG&=~(BIT2+BIT7);P1IE|=(BIT2+BIT7);_EINT();for(;;){if(flag1==0&&flag2==0){blink1();}if(flag1!=0){Buzz();flag1=0;}if(flag2!=0){blink2();flag2=0;}};}#pragmavector=PORT1_VECTOR__interruptvoidport_1(){if((P1IFG&BIT2)!=0){flag1=1;P1IFG&=~BIT2;}if((P1IFG&BIT7)!=0){flag2=1;P1IFG&=~BIT7;}}4.(提高)按键抖动处理(1)延时函数应该加在按键中断程序的最后,因为若延时加在中断程序的开始,则在执行中断时对有效指令的执行也会产生相同的延时。将延时放