清华大学计算机硬件技术基础实验报告.docx
《清华大学计算机硬件技术基础实验报告.docx》由会员分享,可在线阅读,更多相关《清华大学计算机硬件技术基础实验报告.docx(39页珍藏版)》请在冰点文库上搜索。
清华大学计算机硬件技术基础实验报告
实验名称:
实验6:
中断技术
姓名:
袁鹏学号:
2013011780
实验班号:
33机器号:
42
一.实验目的
1.了解中断原理,包括对中断源、中断向量、中断类型号、中断程序以及中断响应过程的
理解;
2.掌握单片机C语言中断程序设计方法
二.实验任务
1.中断响应过程的理解
代码:
#include"io430.h"
#include"in430.h"
voiddelay()//延时函数
{unsignedintj;
for(j=0;j<0xffff;j++);
}
voidBlink()//LED闪
{P2OUT&=~BIT3;
delay();
P2OUT|=BIT3;
delay();
}
voidBuzz()//蜂鸣响
{unsignedinti;
for(i=0;i<3;i++)
{P2OUT&=~BIT4;
delay();
P2OUT|=BIT4;
delay();
};
}
voidmain(void)
{WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
//设置引脚P2.4、P2.3输出,P2.3连接LED,P2.4连接蜂鸣器
P2SEL&=~(BIT3+BIT4);
P2SEL2&=~(BIT3+BIT4);
P2OUT|=(BIT3+BIT4);
P2DIR|=(BIT3+BIT4);
//设置端口P1.1允许中断
P1SEL&=BIT1;
P1SEL2&=BIT1;
P1OUT|=BIT1;;
P1REN|=BIT1;
P1DIR&=~BIT1;
P1IES|=BIT1;
P1IFG&=~BIT1;
P1IE|=BIT1;
_EINT();//总中断允许
for(;;)//主循环
{Blink();};
}
#pragmavector=PORT1_VECTOR
__interruptvoidport_ISR()
{Buzz();
P1IFG&=~BIT1;
}
该程序的功能是让P2.3控制的LED灯不断闪烁,当P1.1控制的开关发出中断申请时,控制P2.4控制的蜂鸣器响三声,然后继续让LED灯闪烁。
1)从程序如何判断用的是哪个中断源?
其中断类型号是多少?
将实验板上某一按键与
该中断源对应的引脚相连,运行程序,操作按键,观察现象。
程序是通过判断中断标志位来确定是哪个中断源,P1.1的中断类型号是2。
运程序时P2.3控制的LED4灯不断闪烁,当P1.1控制的开关发出中断申请时,控制P2.4控制的蜂鸣器响三声,然后继续让LED4灯闪烁。
2)main函数中无调用函数Buzz的语句,函数Buzz如何能被执行?
何时会被执行?
据
此描述中断响应过程。
函数Buzz是在函数名为port_ISR的中断程序中,因此当P1.1发出中断申请时,函数port_ISR就会被执行,执行完毕后再返回main函数中继续执行main函数。
3)如果port_int函数中不清分中断标志P1IFG的后果是什么?
如果不清分中断标志P1IFG的话就会一直相应中断,然后port_ISR函数就会一直被执行,蜂鸣器不断的响。
4)如果L6_int.c中的PORT1_VECTOR改为PORT2_VECTOR,其他不变,程序执行
的后果是什么?
为什么?
(可在主程序入口处加一断点,运行程序,看现象,分析原因)
将PORT1_VECTOR改为PORT2_VECTOR后当按下K2键给P1.1发出中断申请后蜂鸣器不会鸣叫,因为没有正确的设置中断向量,未能将中断程序的入口地址放入FFE0+偏址的中断向量表中,因此程序不能正确的进行中断响应。
思考:
当在主程序入口处加一断点时可以发现,由于已经设置了中断的端口,因此当有中断信号发出时,程序仍然会去执行中断子程,但由于中断向量没有正确设置,PC指针会跑飞,然后机器会自动复位,重新执行程序。
5)如果中断源采用的是P1.5,按键用K7,请设计连线,修改L6_int.c程序完成以中断
方式响应K7的操作。
只需要将P1.1允许中断改为P1.5允许中断即可,同时将P1.5用跳线块与K7相连,具体代码如下:
#include"io430.h"
#include"in430.h"
voiddelay()//延时函数
{unsignedintj;
for(j=0;j<0xffff;j++);
}
voidBlink()//LED闪
{P2OUT&=~BIT3;
delay();
P2OUT|=BIT3;
delay();
}
voidBuzz()//蜂鸣响
{unsignedinti;
for(i=0;i<3;i++)
{P2OUT&=~BIT4;
delay();
P2OUT|=BIT4;
delay();
};
}
voidmain(void)
{WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
//设置引脚P2.4、P2.3输出,P2.3连接LED,P2.4连接蜂鸣器
P2SEL&=~(BIT3+BIT4);
P2SEL2&=~(BIT3+BIT4);
P2OUT|=(BIT3+BIT4);
P2DIR|=(BIT3+BIT4);
//设置端口P1.5允许中断
P1SEL&=BIT5;
P1SEL2&=BIT5;
P1OUT|=BIT5;;
P1REN|=BIT5;
P1DIR&=~BIT5;
P1IES|=BIT5;
P1IFG&=~BIT5;
P1IE|=BIT5;
_EINT();//总中断允许
for(;;)//主循环
{Blink();};
}
#pragmavector=PORT1_VECTOR
__interruptvoidport_ISR()
{Buzz();
P1IFG&=~BIT5;
}
6)(选做)去掉L6_int.c程序最后的那条无限循环语句,看看有什么现象?
可以去掉吗?
去掉程序最后的无限循环语句后LED4灯不在闪烁,但当P1.1发出中断申请后蜂鸣器还是会响三下,因此如果仅仅实现中断功能,则可以去掉无限循环语句。
2.中断程序编程练习
将P1.4、P1.5与K5、K6相连,作为中断源,将P1.7、P2.0、P2.6与BUZZ、LED1、LED7相连,每当K5键按下,使蜂鸣器鸣叫,每当K6键按下,控制二极管闪烁,实现功能。
具体代码如下:
#include"io430.h"
#include"in430.h"
voiddelay()//延时函数
{unsignedintj;
for(j=0;j<0xffff;j++);
}
voidBlink()//LED闪
{P2OUT&=~BIT6;
delay();
P2OUT|=BIT6;
delay();
}
voidBlink2()//LED闪
{
unsignedinti;
for(i=0;i<3;i++)
{
P2OUT&=~BIT0;
delay();
P2OUT|=BIT0;
delay();
}
}
voidBuzz()//蜂鸣响
{
P1OUT&=~BIT7;
delay();
P1OUT|=BIT7;
delay();
}
voidmain(void)
{WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
_DINT();//关闭总中断允许
P1IE&=~(BIT4+BIT5);//关闭分中断允许
//设置引脚P2.0、P2.6、P1.7输出,P2.0连接LED1,P2.6连接LED7,P1.7连接蜂鸣器
P2SEL&=~(BIT0+BIT6);
P2SEL2&=~(BIT0+BIT6);
P1SEL&=~BIT7;
P2SEL2&=~BIT7;
P2OUT|=(BIT0+BIT6);
P2DIR|=(BIT0+BIT6);
P1OUT|=BIT7;
P1DIR|=BIT7;
//设置端口P1.4、P1.5允许中断
P1SEL&=~(BIT4+BIT5);
P1SEL2&=~(BIT4+BIT5);
P1OUT|=(BIT4+BIT5);;
P1REN|=(BIT4+BIT5);
P1DIR&=~(BIT4+BIT5);
P1IES|=(BIT4+BIT5);
P1IFG&=~(BIT4+BIT5);
P1IE|=(BIT4+BIT5);
_EINT();//总中断允许
for(;;)//主循环
{Blink();};
}
#pragmavector=PORT1_VECTOR
__interruptvoidport_ISR()
{if((P1IFG&BIT4)!
=0)
{
Buzz();
P1IFG&=~BIT4;
}
if((P1IFG&BIT5)!
=0)
{
Blink2();
P1IFG&=~BIT5;
}
}
思考:
如果用长导线将按键K5、K6分别连接在P2.2和P2.5上,如何修改程序以实现
任务2功能?
若用长导线将按键K5、K6分别连接在P2.2和P2.5上,则只需将P2.2与P2.5设置为允许中断即可,具体代码如下:
#include"io430.h"
#include"in430.h"
voiddelay()//延时函数
{unsignedintj;
for(j=0;j<0xffff;j++);
}
voidBlink()//LED闪
{P2OUT&=~BIT6;
delay();
P2OUT|=BIT6;
delay();
}
voidBlink2()//LED闪
{
unsignedinti;
for(i=0;i<3;i++)
{
P2OUT&=~BIT0;
delay();
P2OUT|=BIT0;
delay();
}
}
voidBuzz()//蜂鸣响
{
P1OUT&=~BIT7;
delay();
P1OUT|=BIT7;
delay();
}
voidmain(void)
{WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
_DINT();//关闭总中断允许
P2IE&=~(BIT2+BIT5);//关闭分中断允许
//设置引脚P2.0、P2.6、P1.7输出,P2.0连接LED1,P2.6连接LED7,P1.7连接蜂鸣器
P2SEL&=~(BIT0+BIT6);
P2SEL2&=~(BIT0+BIT6);
P1SEL&=~BIT7;
P2SEL2&=~BIT7;
P2OUT|=(BIT0+BIT6);
P2DIR|=(BIT0+BIT6);
P1OUT|=BIT7;
P1DIR|=BIT7;
//设置端口P2.2、P2.5允许中断
P2SEL&=~(BIT2+BIT5);
P2SEL2&=~(BIT2+BIT5);
P2OUT|=(BIT2+BIT5);;
P2REN|=(BIT2+BIT5);
P2DIR&=~(BIT2+BIT5);
P2IES|=(BIT2+BIT5);
P2IFG&=~(BIT2+BIT5);
P2IE|=(BIT2+BIT5);
_EINT();//总中断允许
for(;;)//主循环
{Blink();};
}
#pragmavector=PORT2_VECTOR
__interruptvoidport_ISR()
{if((P2IFG&BIT2)!
=0)
{
Buzz();
P2IFG&=~BIT2;
}
if((P2IFG&BIT5)!
=0)
{
Blink2();
P2IFG&=~BIT5;
}
}
思考:
K5键连接的P1.4与K6键连接的P1.6均属于同一级优先级,因此当执行P1.4发出的中断子程时若按下K6再次发出中断申请,则程序会先处理完P1.4控制的中断程序,然后在执行完后执行P1.5控制的子程。
若想要实现实时反馈,则可以将K6连接的端口改为P2.X,由于P2端口的中断优先级高于P1,因此程序会优先执行P2控制的中断程序。
3.采用事件标志处理中断
阅读程序L6_intA.c和L6_intB.c(见后页),描述其实现功能。
比较L6_intA.c和L6_intB.c二者在编程实现上有何不同。
程序A和程序B实现的功能相同:
用P1.0作为中断源,当P1.0接收到中断信号时,控制蜂鸣器响一声。
不同的是程序A把控制蜂鸣器鸣叫的过程放在中断程序中,而程序B仅仅在中断程序中设置了一个事件标志,而把控制蜂鸣器鸣叫放在了while循环中,这样每当事件标志被响应时,蜂鸣器就会鸣一声。
因此程序A的中断子程执行时间长于程序B。
用L6_intB.c的方法,改写任务2的编程。
具体代码如下:
#include"io430.h"
#include"in430.h"
intflag=0;
voiddelay()//延时函数
{unsignedintj;
for(j=0;j<0xffff;j++);
}
voidBlink()//LED闪
{P2OUT&=~BIT6;
delay();
P2OUT|=BIT6;
delay();
}
voidBlink2()//LED闪
{
unsignedinti;
for(i=0;i<3;i++)
{
P2OUT&=~BIT0;
delay();
P2OUT|=BIT0;
delay();
}
}
voidBuzz()//蜂鸣响
{
P1OUT&=~BIT7;
delay();
P1OUT|=BIT7;
delay();
}
voidmain(void)
{WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
_DINT();//关闭总中断允许
P1IE&=~(BIT4+BIT5);//关闭分中断允许
//设置引脚P2.0、P2.6、P1.7输出,P2.0连接LED1,P2.6连接LED7,P1.7连接蜂鸣器
P2SEL&=~(BIT0+BIT6);
P2SEL2&=~(BIT0+BIT6);
P1SEL&=~BIT7;
P2SEL2&=~BIT7;
P2OUT|=(BIT0+BIT6);
P2DIR|=(BIT0+BIT6);
P1OUT|=BIT7;
P1DIR|=BIT7;
//设置端口P1.4、P1.5允许中断
P1SEL&=~(BIT4+BIT5);
P1SEL2&=~(BIT4+BIT5);
P1OUT|=(BIT4+BIT5);;
P1REN|=(BIT4+BIT5);
P1DIR&=~(BIT4+BIT5);
P1IES|=(BIT4+BIT5);
P1IFG&=~(BIT4+BIT5);
P1IE|=(BIT4+BIT5);
_EINT();//总中断允许
for(;;)//主循环
{Blink();
if(flag==1)
{
Buzz();
flag=0;
}
elseif(flag==2)
{
Blink2();
flag=0;
}
}
}
#pragmavector=PORT1_VECTOR
__interruptvoidport_ISR()
{if((P1IFG&BIT4)!
=0)
{
flag=1;
P1IFG&=~BIT4;
}
if((P1IFG&BIT5)!
=0)
{
flag=2;
P1IFG&=~BIT5;
}
}
4.(选做)按键抖动处理
为了去除这些毛刺带来的影响,进行按键消抖,需要在响应了第一次下降沿后,加入一定的延时,躲过其它电压毛刺的产生时间。
具体代码如下:
#include"io430.h"
#include"in430.h"
unsignedintnumber=0;//记录响应按键次数
voiddelay()//延时函数
{unsignedintj;
for(j=0;j<0xffff;j++);
}
intmain(void)
{WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
__disable_interrupt();//_DINT();禁止总中断
P2SEL=0;//置P2为基本I/O功能
P2SEL2=0;//
P2OUT=0xFF;//置P2输出的初值
P2DIR=0xFF;//置P2为输出方向
P1SEL&=BIT2;
P1SEL2&=BIT2;
P1OUT|=BIT2;;
P1REN|=BIT2;
P1DIR&=~BIT2;
P1IES|=BIT2;
P1IFG&=~BIT2;
P1IE|=BIT2;
__enable_interrupt();//_EINT();总中断运行
while
(1){};
}
#pragmavector=PORT1_VECTOR
__interruptvoidport_int(void)
{unsignedinti;
for(i=0;i<3;i++)
{
delay();
}
if((P1IFG&BIT2)!
=0)
{number++;
P2OUT=~number;
}
P1IFG&=~BIT2;
}
实验名称:
实验7:
基本时钟和低功耗模式
姓名:
袁鹏学号:
2013011780
实验班号:
33机器号:
42
一.实验目的
1.了解MSP430Gxxx基本时钟模块的工作原理,掌握其控制方法;
2.掌握利用时钟信号和中断技术实现定时功能的方法;
3.掌握低功耗模式控制方法
二.实验任务
1.数字示波器的使用
(1).用示波器测得信号源的周期T=20us、频率f=1.000KHZ、峰峰值V=3.12V。
(2).测得实验板上Vcc信号正常,Vccmax=3.76V,Vccmin=3.52V,Vccavg=3.66V。
2.测试上电复位系统的ACLK、和SMCLK时钟频率
输出的ACLK频率为F(ACLK)=32.79KHZ,SMCLK的频率为F(SMCLK)=1.031MHZ。
代码如下:
#include"io430.h"
intmain(void)
{
//Stopwatchdogtimertopreventtimeoutreset
WDTCTL=WDTPW+WDTHOLD;
P1SEL|=BIT0;//P1.0输出ACLK
P1SEL2&=~BIT0;
P1DIR|=BIT0;
P1SEL|=BIT4;//P1.4输出SMCLK
P1SEL2&=~BIT4;
P1DIR|=BIT4;
while
(1);
}
思考:
上电复位后,CPU工作的时钟信号MCLK频率值是多少?
上电复位后,通过查看基本时钟模块相关寄存器,可知MCLK的时钟源为DCO,SMCLK的时钟源也为DCO,因此通过测量上面复位后的SMCLK频率可知MCLK的频率,由上述可知F(MCLK)=1.031.MHZ。
3.掌握基本时钟模块的编程控制
参看附录A实验板原理图,用跳线将JP8中的插针信号接到晶振32.768Khz侧,使晶振
与单片机的P2.6和P2.7相连。
编程控制基本时钟模块,设置ACLK分别为下面时钟频
率,并通过P1.0输出ACLK,用示波器观察:
(1).ACLK=4096Hz;(时钟源外部晶振,32768Hz/8)
观察的F(ACLK)=4.098KHZ。
具体代码如下:
#include"io430.h"
intmain(void)
{
//Stopwatchdogtimertopreventtimeoutreset
WDTCTL=WDTPW+WDTHOLD;
P1SEL|=BIT0;//设置P1.0输出ACLK
P1SEL2&=~BIT0;
P1DIR|=BIT0;
P2SEL|=BIT6;//设置P2.6、P2.7连接外部晶振引脚
P2SEL2&=~BIT6;
P2DIR&=~BIT6;//P2.6XIN输入
P2SEL|=BIT7;
P2SEL2&=~BIT7;
P2DIR|=BIT7;//P2.7XOU输出
BCSCTL1|=DIVA_3;//设置ACLK为8分频
while
(1);
}
(2).ACLK=3KHz;(时钟源VLOCLK,12KHz/4)
观察的F(ACLK)=3.165KHZ。
具体代码如下:
#include"io430.h"
intmain(void)
{
//Stopwatchdogtimertopreventtimeoutreset
WDTCTL=WDTPW+WDTHOLD;
P1SEL|=BIT0;//设置P1.0输出ACLK
P1SEL2&=~BIT0;
P1DIR|=BIT0;
BCSCTL1|=DIVA_2;//设置ACLK时钟源为VLOCLK,并为4分频
BCSCTL3|=LFXT1S_2;
while
(1);
}
思考:
可否编程在引脚P2.0上输出ACLK?
为什么?
不可以,因为根据说明指导书MSP430G2553的辅助时钟ACLK