首页 理论教育中断概念与多语言编程

中断概念与多语言编程

【摘要】:所谓中断,就是计算机为提高运行效率而采用的一种方式。当一个变量一旦发生要求的改变时,计算机立即自动触发中断,转向一段服务程序,执行完成后,自动返回主程序的原断点继续运行。④ES为串行口中断允许位。当几个通道同时发生中断时,计算机只能选择一个通道进行响应,即具有高优先级的通道才能被响应。⑥连续单击“跟踪”,由于a+1,a≠5,所以返回主函数继续等待下一次中断。

所谓中断,就是计算机为提高运行效率而采用的一种方式。例如对一个变量,当它发生状态改变时,就要立即进行处理。为此就必须时刻查询这个变量的状态。例如,例4-37中,对定时器T/C0的溢出标志位TF0必须不间断地查询它的状态。但这样做就要浪费计算机大量的运行时间,很显然这是我们不希望的。而采用中断方式,就可以有效地克服这种缺点。当一个变量一旦发生要求的改变时,计算机立即自动触发中断,转向一段服务程序,执行完成后,自动返回主程序的原断点继续运行。这就不必要时刻查询这个变量的状态,在不发生改变时,可以放心让机器做其他工作。这样就解放了计算机的大量能力,提高了运行效率。

1.有关中断的设置

(1)选择中断源

8051系列单片机的中断机制,共设置有5种中断源,见表4-7。

表4-7 5种中断源

978-7-111-47138-7-Chapter04-126.jpg

(2)设置寄存器

与中断执行有关的SFR有两个,即中断允许寄存器IE和中断优先级寄存器IP。

1)中断允许寄存器IE。

978-7-111-47138-7-Chapter04-127.jpg

复位后,IE=0x00,禁止一切中断。各位状态的设置如下:

①EA为总允许位。若EA=0,禁止一切中断;EA=1,允许中断。

②×表示无效,是保留位。

③ET2为定时器2中断允许位。若ET2=0,此位禁止;ET2=1,此位允许有效(EA=1时)。

④ES为串行口中断允许位。若ES=0,此位禁止;ES=1,此位允许有效(EA=1时)。

⑤ET1为定时器1中断允许位。若ET1=0,此位禁止;ET1=1,此位允许有效(EA=1时)。

⑥EX1为外部中断1允许位。若EX1=0,此位禁止;EX1=1,此位允许有效(EA=1时)。

⑦ET0为定时器0中断允许位。若ET0=0,此位禁止;ET0=1,此位允许有效(EA=1时)。

⑧EX0为外部中断0允许位。若EX0=0,此位禁止;EX0=1,此位允许有效(EA=1时)。

2)中断优先级寄存器IP。

978-7-111-47138-7-Chapter04-128.jpg

复位后,IP=00H,无优先级,各位状态的设置(该位置“1”,表示优先级为高,清“0”表示优先级为低)如下:

①×表示无效,是保留位。

②PT2为定时器2优先级设置位。PT2=1,优先级为高。

③PS为串行口中断优先级设置位。PS=1,优先级为高。

④PT1为定时器1中断优先级设置位。PT1=1,优先级为高。

⑤PX1为外部中断1优先级设置位。PX1=1,优先级为高。

⑥PT0为定时器0中断优先级设置位。PT0=1,优先级为高。

⑦PX0为外部中断0优先级设置位。PX0=1,优先级为高。

所谓优先级设置,即设置计算机对中断响应的选择权。当几个通道同时发生中断时,计算机只能选择一个通道进行响应,即具有高优先级的通道才能被响应。

当多个高优先级中断发生或无优先级设定时,要按照下面自然优先级响应中断:

978-7-111-47138-7-Chapter04-129.jpg

(3)中断服务函数定义

在C语言中,若应用中断功能,必须先定义中断服务函数。其一般形式如下:

978-7-111-47138-7-Chapter04-130.jpg

其中,n是中断号,m是选定的工作寄存器组编号,0~3代表4个工作寄存器。

中断服务函数编程中的规则如下

1)中断函数中,不能有任何参数声明。

2)中断函数不能设返回值。应设为void型。

3)中断函数不能直接调用。

如果在中断函数中调用了其他函数,则被调用函数所用的寄存器组必须与中断函数所用寄存器组相同。

2.【例4-41】 利用定时器T/C0控制灯D0闪烁,定时时间为1s,采用中断方式

(1)确定定时器T/C0各SFR

1)确定TMOD值。选用T/C0为定时器,工作方式选mode 1,即16位定时器,TMOD=0000 0001B=0x01。

2)计算定时常数。项目要求定时时间为1s,选T/C0定时时间为T/C0=0.1s,靠软件重复10次,总定时时间T=10×0.1s=1s。

定时常数T0=65536-(100×103/2)

=65536-50000

将T0分解为高8位TH0和低8位TL0,为

TH0=15536/256=60=0x3C

TL0=15536-(256×60)=176=0xB0

3)确定TCON值。TR0在程序中设置,其他位为0,TCON=0x00。

4)确定IE值。EA=1,允许总中断。ET0=1允许T/C0中断。其他位为0,IE=1000 0010=0x82。

5)确定IP值。因只有一个中断,可以不设置优先级,仍保持复位状态IP=0x00。

(2)编辑C语言源程序

978-7-111-47138-7-Chapter04-131.jpg

(3)编译

(4)执行

1)软仿真。

①进入调试,米黄色标志箭头停在第11语句处。

②调出P1状态窗口。

③调出Timer 0窗口。

④调出变量窗口。

⑤连续单击“跟踪”,在语句18等待中断处,令TF0=1,即在Timer 0窗口的TF0处打“√”。单击“跟踪”,程序即跳转到中断服务子函数。

⑥连续单击“跟踪”,由于a+1,a≠5,所以返回主函数继续等待下一次中断。

⑦中断5次,由于a=5,D0取反,a=0。等待下一个5次中断。

通过调试,证明程序达到要求。

2)下载到实验机。执行程序,灯D0闪烁,间隔时间为0.5s。

(5)程序点评

本例采用用T/C0中断方式控制灯闪烁。变量a应为全局变量。不管在主函数或在中断函数中均有效。在变量a信息栏内,因为它不是局部变量,所以单击F2键,才可以观察a的变化。

3.【例4-42】 乐曲编程《生日快乐歌》

(1)乐曲编程简介

对于一个音符,有两个属性:一是音高,即音符对应的音名(频率);二是时值,即占有的节拍数。对于声音的频率,按定时器T0的工作方式1(16位计数)在P2.7口产生方波,驱动蜂鸣器发声。对于节拍,按延时函数产生,不同的节拍数由不同延时倍率保证。用定时器产生方波,比较准确。对于节拍,准确度要求不高,用延时函数产生是合适的。

要对一首乐曲(主要是歌曲)进行编程,就是将歌曲简谱的每个音符按顺序编辑成两组代码,一组是音符的音高代码,一组是音符的时值代码。节拍按每拍0.5s计算。完成后与程序一齐存入片内存储器。执行程序,即可听到歌曲的演奏声。

也可以将乐曲代码单独存入外部扩展存储器,例如24C02或24C64。开机后立即将乐曲的所有音符代码读入片内RAM,然后执行发音程序。如果片内RAM足够大,也可以开机后直接存入RAM,然后执行。

编程前,第一步将乐曲的简谱写出。第二步将每个音符的音高根据音高表列出编码。第三步按乐曲节拍列出编码。

(2)编辑C语言源程序

1)流程图,如图4-12所示。

978-7-111-47138-7-Chapter04-132.jpg

图4-12 流程图

2)C语言程序如下:

978-7-111-47138-7-Chapter04-133.jpg(www.chuimin.cn)

978-7-111-47138-7-Chapter04-134.jpg

978-7-111-47138-7-Chapter04-135.jpg

(3)编译

(4)执行

1)软仿真。

①进入“调试”,调出P2口状态。调出Timer 0。

②连续单击“单步”,执行语句。由于第一个音符≠00,≠15,≠14,直接执行到取TH0/TL0,开Timer 0,取节拍值。在此期间,由T/C0按中断服务函数发音。当节拍延时结束,立即关T/C0,停止发音。完成一个音符,进入下一个音符的提取。如此循环,直到0x14,循环结束。

③若结束符为0x15,则表示继续从头循环发音。若为0x00,则为空拍,不发音,执行空拍后,取下一音符。

2)下载到目标机。执行后,蜂鸣器发出《生日快乐歌》曲调。

(5)程序点评

本例练习乐曲编程。音符的发声由定时器中断产生。中断的定时时间取决于TH0/TL0的数值。即相当于音符的音高。发声的延时时间由节拍决定。本例只列出了两个曲目。有兴趣的读者只需改变tab_1内容(音高),tab_5内容(节拍)即可以练习其他乐曲。

《生日快乐歌》的曲谱及音高节拍编码表分别如图4-13和图4-14所示。

978-7-111-47138-7-Chapter04-136.jpg

图4-13 《生日快乐歌》曲谱

4.【例4-43】 电子琴练习,

利用目标机的5只键演奏C调“1,2,3,4,5”

(1)编辑C语言源程序

分析电子琴的程序,主要是两部分:5只键的扫描和T/C0中断服务程序。上电即进入键扫描状态,若无键按下,则继续扫描等待。一旦发现有键按下,即进入T/C0初始化。开中断,从对应的键号开始取TH0/TL0,并由中断服务程序发声。当查询到键若未抬起,则继续中断发声。若查询到键已抬起,则返回继续键扫描,等待下次按键。

978-7-111-47138-7-Chapter04-137.jpg

图4-14 音高/节拍编码表

具体程序如下:

978-7-111-47138-7-Chapter04-138.jpg

978-7-111-47138-7-Chapter04-139.jpg

978-7-111-47138-7-Chapter04-140.jpg

(2)编译

(3)执行

1)软仿真。

①进入“调试”,调出P2口状态。调出Timer 0。

②连续单击”跟踪”,执行语句,由于P2无键按下,key()子函数的返回值c=0x05,进入循环查键。TR=0,T/C0关闭,系统等待。

③若置P2.0=0,连续单击“单步”,执行语句,由于有键按下,key()子函数的返回值c=0x00,相当于按下+1键,i=0x00。

④进入键号取值。TH0=0xFC,TL0=0x46,对应于“do”音。

⑤连续单击“单步”,由于开中断,导致Timer 0中断发音。

⑥到达key_ up(),等待键抬起。当键抬起后,TR0=0,关闭Timer 0发音。进入下一轮查键。

通过调试,证明程序可以满足设计要求。

2)下载到目标机执行程序,依次按下+1、-1、H、AD、WR键,发音1、2、3、4、5(do、re、mi、fa、sol)音。

(4)程序点评

本例在实验机建立一个5键电子琴,可以验证电子琴的编程原理。

5.【例4-44】 频率计

若用T/C0做定时器,用T/C1做计数器,当有脉冲输入时,在一定时间内将计数结果保存并显示,就是频率计。下面我们用T/C0作为定时器,用T/C1做计数器,P3.5(T1)作为外触发输入计数脉冲,并用数码管显示结果。

(1)编程

978-7-111-47138-7-Chapter04-141.jpg

978-7-111-47138-7-Chapter04-142.jpg

(2)编译

(3)执行

1)软仿真。

①进入软仿真调试状态。米黄色图标指向main()主函数第1条语句。

②连续单击“单步”向下执行,到if(TF0)停止等待。因为T0未溢出。这时,TH0=0x3C,TL0=0xB0,TH0=0x00,TL0=0x00。调出P3口。

③手动单击P3.5(T1),发下降沿脉冲,即置0,置1,共50次。在T/C1的TL0栏内即显示输入的次数0x32=50,即表示输入50次计数值。

④置TC0的TF0=1,定时器T/C0溢出。程序向下执行,a=TL1=0x32。

⑤单击“单步”,执行send(form[a%10]),因为a=50,a%10=0,传送的实参byte=0xC0。即0的字形码。

⑥单击“单步”,执行send(form[a/10]),因为a=50,a/10=5,传送的实参byte=0x92。即5的字形码。

⑦单击“单步”,向下执行。重置TH0/TL0,开TR0,TR1进入下次测试。

从调试的结果,证明程序正确。

2)下载到目标实验机。若进行硬件部分执行,除主机运行上面程序外,还必须用另一单片机组成一个已知频率的发生器,将计数脉冲输入到主机,然后观察显示结果,应与已知频率相同。

(4)程序点评

本例要求了解定时器既可以做定时器,也可以做计数器。当在一定时间内,计入外部输入的计数脉冲值,就是频率计。此例对理解定时和计数的原理是很合适的。

6.【例4-45】 外部中断练习在外部中断0978-7-111-47138-7-Chapter04-143.jpg的输入端P3.2加一个下降沿脉冲,触发外部中断0,控制一个二进制位xbit的状态。xbit的初始状态为0。

(1)外部中断简介

8051单片机本身设有两个外部中断输入端,分别为978-7-111-47138-7-Chapter04-144.jpg978-7-111-47138-7-Chapter04-145.jpg。外部中断0978-7-111-47138-7-Chapter04-146.jpg的中断服务程序入口的地址为0x0003,外部中断1(978-7-111-47138-7-Chapter04-147.jpg)的中断服务程序入口的地址为0x0013。在C语言中中断服务函数可以用下列格式进行声明:

978-7-111-47138-7-Chapter04-148.jpg

其中,extern表示外部,extern_ int0(void)表示外部中断服务函数的名称,(void)表示此函数无返回值,interrupt 0表示中断编号为0,using 0表示函数放于寄存器0区。为了避免与其他数据相互影响,也可以用using 1,表示函数放于寄存器1区。

外部中断的激活方式(不管是978-7-111-47138-7-Chapter04-149.jpg978-7-111-47138-7-Chapter04-150.jpgINT1)有两种:一种是电平激活,另一种是脉冲边沿激活。这两种方式可以靠TCON寄存器的外部中断类型控制位IT0和IT1来控制。当为1时,是后沿触发中断。当为0时,是低电平触发中断。

为了可靠地触发中断,对于后沿触发至少高电平要保持1个机器周期,而下降沿也要至少保持1个机器周期。对于6MHz晶振,高电平保持至少2μs,低电平也至少保持2μs。

(2)编辑C语言源程序

978-7-111-47138-7-Chapter04-151.jpg

978-7-111-47138-7-Chapter04-152.jpg

(3)编译

(4)执行

1)软仿真。

①调出P1和P3口状态。

②连续单击“跟踪”,当未产生外部中断0时,xbit=0,P1口不产生变化。

③当置P3.2=0,产生一个下降沿中断,程序转入中断服务函数,xbit=1,中断返回后,导致P1+1产生变化。

若继续产生下降沿中断,则xbit=0,P1口停止变化。如此反复。可以检验外部中断0的效果。

2)下载到实验机。进行如下操作:

若总中断被打开,外部中断0被打开,TCON的IT0=1,若未产生外部中断0,则xbit=0,程序继续循环,P1口不产生变化。

当第1次在P3.2产生一个下降沿时,立即触发外部中断0,并执行中断服务函数,导致xbit=1。P1口的状态产生+1变化。直到再次产生中断,xbit=0为止。

当又产生中断时,xbit=1,P1口的状态再次产生+1变化。直到再次产生中断,xbit=0为止。

这样,就验证了外部中断0的机制。

(5)程序点评

本例验证外部中断机制。用位变量xbit作为引导。当INT0产生下降沿外部中断时,导致xbit取反。当xbit=1,P1+1,即表示外部中断的效果。