单片机经典教程 - 图文(6)

2019-07-13 16:05

1.工作方式0

13 位的定时/计数器工作方式。因此,最多可以计到2 的13 次方,也就是8192 次。 2.工作方式1

16 位的定时/计数器工作方式。因此,最多可以计到2 的16 次方,也就是65536 次。 2 3.工作方式2 和3

工作方式2 和工作方式3 都是8 位的定时/计数器工作方式,因此最多可以计到2 的8 次方,也说是256 次。

预置值计算:用最大计数量减去需要的计数次数即可。例如:流水线上一个包装是24 盒,要求每到24 盒就产生一个动作,用单片机的工作方式0 来控制,应当预置多大的值呢?对了,就是8192-24=8168。 以上是计数器的原理,明白了这个道理,定时器也一样。

单片机经典教程18 单片机的中断系统

单片机中断系统的目的是为了让CPU 对内部或外部的突发事件及时地作出响应,并执行相应的程序,在单片机的开发中,它同样有着十分重要的作用,那么单片机的中断是怎么回事?它是如何来工作的呢?这一课就来讨论这个问题,在讲解之前让我们先来介绍一下中断的原理:

一、中断的基本原理

什么是中断?中断的过程是什么?要搞清楚这个问题,我们同样先从生活中的一个例子开始:你正在家中看书,突然电话铃响了,你放下书,去接电话,和来电话的人交谈,通完电话,回来继续看你的书,这就是生活中的“中断”现象—就是正常的工作过程被外部的事件打断了。仔细研究一下生活中的中断,对我们学习单片机中断会很有帮助:

第一,中断源。什么可引起中断,生活中很多事件都可以引起中断,比如:有人按了门铃、电话铃响了、你的闹钟响了、你烧的水开了??等等诸如此类的事件,我们把可以引起中断的事件称之为中断源。单片机中也有一些可以引起中断的事件(比如:掉电、运算溢出、报警等等),89C51 单片机中共有5 个中断源:两个外部中断,两个定时/计数器中断(溢出),一个串行口中断。

第二,中断的嵌套与优先级处理。设想一下,我们正在看书,电话铃响了,同时又有人按了门铃,你该先做那样呢?如果你正在等一个很重要的电话,一般是不会去理会门铃的;而反之,如果你正在等一个很重要的客人,则可能就不会去理会电话了;如果两者都不是(既不等电话,也不等人上门),你可能会按你通常的习惯去处理。总之这里存在一个优先级的问题,单片机中也是如此,也有优先级的问题。优先级的问题不仅仅发生在两个中断同时产生的情况,也发生在一个中断已产生,又有另一个中断产生的情况。比如你正在接电话,又有人按门铃的情况,或者你正开门与人交谈,又有电话响了的情况。考虑一下,我们一般会怎么办?

第三,中断的响应与处理。当有事件产生,进入中断之前我们必须先记住现在的书看到第几页了,或拿一个书签放在当前页的位置,然后去处理不同的事情(因为处理完了,我们还要回来继续看书),电话铃响我们要到放电话的地方去,门铃响了我们要到门那边去,也就是说不同的中断,我们要在不同的地点处理,而这个地点通常还是固定的。单片机中采用的也是这种方法,五个中断源,每个中断产生后都到一个固定的地址去找处理这个中断的程序,当然在去之前首先要保存下面将执行的指令的地址,以便处理完中断后回到原来的地方继续往下执行程序。具体地说,单片机中断响应可以分为以下几个步骤:1、停止主程序运行。当前指令执行完后立即终止现行程序的运行。2、保护断点。把程序计数器PC 的当前值压入堆栈,保存终止的地址(即断点地址),以便从中断服务程序返回时能继续执行该程序,3、寻找中断入口。根据5 个不同的中断源所产生的中断,查找5 个不同的入口地址。4、执行中断处理程序。这就不讲了;5、

中断返回。执行完中断处理程序后,就从中断处返回到主程序,继续往下执行。以上工作是由计算机自动完成的,与编程者无关,在这5 个入口地址处存放有中断处理的程序(这是程序编写时放在那儿的,如果没把中断处理程序放在那儿可就错了,因为中断程序无法被执行到)。有点复杂是吗?没关系,继续往下看。二、实现中断的好处

单片机为什么要有中断系统,使用中断有什么好处呢?日常生活中,我们除了看书,肯定还要做很多其他的事情,比如听电话,接待客人,烧水吃饭等等,单片机实行中断也有很多的好处,具体来说:1。实行分时操作,提高CPU 的效率。只有当服务对象向CPU 发出中断申请时,才去为它服务,这样我们就可以利用中断功能同时为多个对象服务,从而大大提高了CPU 的工作效率。2。实现实时处理。利用中断技术,各个服务对象可以根据需要随时向CPU 发出中断申请,及时发现和处理中断请求并为之服务,以满足实时控制的要求。3。进行故障处理。对难以预料的情况或故障,比如掉电,事故等,可以向CPU 发出请求中断,有CPU 作出相应的处理。那么单片机是如何实现中断处理的呢?要了解这个问题,就让我们先来看看单片机中断系统的内部结构。 三.单片机中断系统的结构:

前面已经提到,89C51 单片机有5 个中断源,那么它们的硬件结构是怎么样的呢?请看下面的图,这就是89C51 单片机的中断系统内部结构图,下面让我们一一来进行分析: 1.中断源: (1)外部中断:

即外中断0 和外中断1,经由外部引脚引入,在单片机的硬件上有两个引脚(12 和13),名称为INT0 和INT1 (第二引脚功能P3.2、P3.3)。在单片机的内部有一个特殊功能寄存器TCON,其中有四位是与外中断有关的。还记得TCON 是什么吗?对了,是定时器控制寄存器,请看下面的表:

A.IT0:中断0(INT0)的触发方式控制位。

可由软件进行置位和复位,IT0=0,中断0 为低电平触发方式;IT0=1,中断0 为负跳变触发方式。这两种方式的差异讲起来有点复杂,这里就不介绍了,作为初学者,只要知道就可以了。至于具体如何使用,我们到后面做实验时再讲解。

B.IE0:中断0( INT0)的中断请求标志位。

当有外部的中断请求时,该位就会置“1”;在CPU 响应中断后,该位就自动清“0”。(注意?:这是由硬件自动完成的)。 IT1、IE1 的用途和IT0、IE0 是类似的。看上面的表: (2)内部中断

即定时器0(T0)和定时器1(T1)中断,与外中断一样,它也是由TCON 中的四位控制的。 A. TF0:定时器T0 的溢出中断标记。

当T0 计数产生溢出时,由硬件置位TF0;当CPU 响应中断后,再由硬件将TF0 自动清“0”。 TF1 :与TF0 类似,这里就不讲了。 (3)串行口中断

单片机教程(MCS-51 系列)

负责串行口的发送、接收中断,具体内容我们到下册学习串行接口时再详细讲解。下面我们再来讲另一个与中断有关的寄存器。 2、中断允许寄存器IE(A8H)

中断的允许或禁止是由片内可进行位(什么是位,大家可别到现在还说不知道哦)寻址的8 位中断允许寄存器IE 来控制的,单片机中断系统中有两种不同类型的中断:一种称为非屏蔽中断;另一种称为屏蔽中断。对于非屏蔽中断,用户不能用软件方法加以禁止,一旦有中断申请,CPU 将根据自然优先级予以响应。这里主要讲屏蔽中断,对于屏蔽中断,我们可以通过软件的方法来予以控制(允许中断我们把它称为中断开放,不允许中断我们把它称之为中断屏蔽),如何操作,说穿了其实很简单,就是通过对IE 的相应位的置“1”或请“0”来允许或禁止某个中断,请看下面的表格:

(1)EA:总中断允许开关。它是个总开关,凡是要设置中端都得先通过它。EA=1,开放所有的

中断;EA=0,则所有中断都被禁止。(2)ES:串行口中断控制位。ES=1,允许中断;ES=0,禁止中断。(3)ET1:定时/计数器1 中断控制位。ET1=1,允许中断;ET1=0,禁止中断。(4)EX1:外中断1 中断控制位。EX1=1,允许中断;EX1=0,禁止中断。(5)ET0:定时器0 中断控制位。ET0=1,允许中断;ET0=0,禁止中断。(6)EX0:外中断0 中断控制位。EX0=1,允许中断;EX0=0,禁止中断。

例如:我们现在要设置INT1 允许,T1 允许,其它不允许,则IE 应该是10001100 (即8CH),也可以直接用位操作指令SETB EA;SETB ET1;SETB EX1 来实现它。看一下下面的表:

这里有一点请大家注意?:当复位CPU 时,IE 将被全部清“0”。

了解了中断的设置,让我们再来看另一个问题:前面我们提到过,中断有优先级和嵌套的问题,那么中断的优先级和嵌套是如何来控制的呢?接着往下看:

3.中断源优先级寄存器IP(D8H)

单片机执行中断的过程和生活中的中断有些类似,它也有一个自然优先级与人工优先级的问题,那么单片机是如何来设置它们的呢?这就要用到中断优先级寄存器IP,它也是一个可位寻址的8 位寄存器。现在让我们先来看五个中断源的自然优先级是如何设置的: 五个中断源的自然优先级由高到低的排列顺序为外中断0→定时器0→外中断1→定时器1→串口中断。如果我们不对其进行设置,单片机就按照此顺序不断的循环检查各个中断标志(就像我们生活中按照习惯处理事物一样),但有时我们需要人工设置高、低优先级,也就 是说由编程者来设定哪些中断是高优先级、哪些中断是低优先级(当然由于只有两级,所以必然只有一些中断处于优先级别,而其他的中断则处于同一级别,处于同一级别的中断顺序就由自然优先级来确定,这一点请大家务必搞清楚了)。

既然可以设定人工优先级,那么它又是如何来设置的呢?其实很简单,我们只要把IP 寄存器的对应位置“1”就可以了,看下面的表: 开机时,每个中断都处于低优先级,我们可以用指令来对优先级进行设置。例如:现在有如下要求,将T0、INT1 设为高优先级,其它为低优先级,求IP 的值。

IP 的首3 位没用,可任意取值,设为000 ,后面根据要求写:00000110 ,即IP=06H,看下面的表。

这里有个问题:如果5 个中断请求同时发生时又会出现什么情况呢?比如在上例中,五个中断同时发生,求中断响应的次序。按照我们学到的内容,响应次序应该为:定时器0→外中断1→外中断0 68

→实时器1→串行中断。是不是符合我们刚才说的除了人工设置的高优先级外,其余的均按照自然优先级来处理。其实这很好理解,如果我在家等待一个很重要的电话,同时又有人来敲门或者烧的水开了,当我放下电话后,还是会按照一般的习惯去处理其他的事情(比如先开门让客人进来,再去处理烧开的水)。 4.串行口控制寄存器SCON(98H)

用于串行口中断及控制,我们留到下册中再详细解释。下面讨论一下另一个问题: 四.中断响应的条件和过程 1、中断响应的原理

讲到这里,我们依然对于单片机响应中断的过程感到神秘,我们人响应外界的事件,是因为我们有多种“传感器”――眼、耳等可以接受不同的信息,那么单片机是如何做到这点的呢?其实说穿了,一点也不稀奇,单片机工作时,在每个机器周期中都去查询一下各个中断标记,看它们是否是“1”,如果是“1”,就说明有中断请求了。所以所谓中断,其实也就是查询,只不过是每个周期都查一下而已。这要换成人来说,就相当于你在看书的时候,每一秒钟都抬起头来看一看,看是不是有人按门铃了,是否有电话来了,烧的水是否开了??很蠢,是吗?本来嘛,计算机它根本就没人聪明。了解了响应中断的原理,就不难理解中断响应的条件了。 2、中断响应的条件

当有下列三种情况之一发生时,CPU 将封锁对中断的响应,而是到下一个机器周期时再继续查询:

(1)CPU 正在处理一个同级或更高级别的中断请求时。 (2)当前的指令没有执行完时。

我们知道,单片机有单周期指令、双周期指令、三周期指令和两个四周期指令,如果当前执行指令是单字节指令也许没关系,如果是双字节或四字节的指令,那就要等整条指令都执行完了,才能响应中断(因为中断查询是在每个机器周期都可能查到的)。 (3)当前正执行的指令是返回指令(RETI)或访问IP、IE 寄存器的指令,则CPU 将至少再执行一条指令才能响应中断。

这些都是与中断有关的寄存器,如果正访问IP、IE 则可能会出现开、关中断或改变中断的优先级;而中断返回指令则说明本次中断还没有处理完,所以就要等本指令处理结束,再执行一条指令才可以响应中断。 3、中断响应的过程:

CPU 响应中断时,首先把当前指令的下一条指令(就是中断返回后将要执行的指令)的地址(也叫

断点地址)送入堆栈,然后根据中断标记,硬件执行长跳转指令,转到相应的中断源入口处,执行中断服务程序,当遇到RETI(中断返回指令),返回到断点处继续执行程序,这些工作都是由硬件自动来完成的。那么中断入口的地址是如何来确定的呢?在51 系列单片机中,五个中断源都有它们各自的中断入口地址,请看下面: (1)外中断0(INT0):0003H (2)定时器0(T0):000BH (3)外中断1(INT1):0013H (4)定时器1(T1):001BH (5)串口中断:0023H

讲到这里,大家应该明白,为什么我们前面的有些程序一开始是这样写的: ORG 0000H ; LJMP START ; ORG 0030H ; START:***** ; ***** ; ***** ; END。

其实这样写的目的,就是为了让出中断源所占用的向量地址,当然,在程序中如果没有用到中断时,直接从地址0000H 开始写理论上不是不可以,但在实际工作中最好不要这样做。这里还有一个问题,大家是否注意到,每个中断向量地址只间隔了8 个字节,如0003H-000BH,在如此少的空间中如果完成不了中断程序,又该这么办呢?其实很简单,您只要在中断处安排一条LJMP 指令,不就可以把中断服务程序跳转到任何地方去了吗?所以一个完整的主程序看起来应该是这样的: ORG 0000H ; LJMP START ; ORG 0003H ;

LJMP AINT0 ;转外中断0 服务程序 ORG 000BH ;

RETI ;没有用定时器0 中断,在此放一条RETI,万一“不小心”产生了中断,也不会有太大的后果。 START:***** ;主程序 ***** ; ***** ;

AINT0:***** ;中断服务程序 ***** ;

RETI ;从中断服务程序返回 END。

中断程序处理完成后,一定要执行一条RETI 指令,执行这条指令后,CPU 将会把堆栈中保存着的地址取出,送回程序计数器PC,那么程序就会根据PC 中的值从主程序的中断处继续往下执行了。从CPU 终止当前程序,且转向另一程序这点看,中断的过程很象子程序,其实它们之间还是有区别的:中断发生的时间是随机的,而子程序调用则是按程序进行的,所以它们的返回命令也是不一样的。RET 是用在返回子程序中的,而RETI 则用在返回中断处理程序中的,这一点千万不能搞错了。另外还有一点需要大家注意?的是:在这里CPU 所做的自动保护工作是很有限的,它只保护了一个地址(就是中断返回后将要执行的指令的地址,即PC 的值),而其它的所有东西都不保护,所以如果你在主程序中用到了如ACC、PSW 等寄存器,而在中断程序中又要用到它们,还要保证回到主程序后这里面的数据还是没执行中断之前的数据,就得自己把它们保护起来。这是一项非常重要的工作,否则程序执行的结果就不是您想象的要求了!(具体如何做,我们将在下一课的实验中详细解释)。

单片机经典教程19 单片机的定时与中断实验

前面的两节课程我们介绍了单片机定时/计数器和中断的原理及结构,这节课我们就来做几个实验验证一下前面所学的内容。实验一、利用定时器实现灯的闪烁

在开始学单片机时我们所做的第一个实验就是LED 灯的闪烁,不过那是用延时程序做的,现在回想起来,这样做不是很恰当,为什么呢?因为我们的主程序做了灯的闪烁,就不能再干其它的事情了,难道单片机只能这样工作吗?当然不是,我们可以用定时器来完成灯的闪烁功能。 程序如下: ORG 0000H ; AJMP START ; ORG 30H ;

START:MOV P1,#0FFH ;关所有的灯

MOV TMOD,#00000001B ; 定时/计数器0 工作于方式1 MOV TH0,#15H ;

MOV TL0,#0A0H ;立即数(15AH+0A0H=5536) SETB TR0 ; 定时/计数器0 开始运行

LOOP:JBC TF0,NEXT ;如果TF0 等于1,则清TF0 并转NEXT 处 此处可以加入其他的任何指令 AJMP LOOP ;否则跳转到LOOP 处运行 NEXT:CPL P1.0 ; MOV TH0,#15H ;

MOV TL0,#9FH ;重置定时/计数器的初值 AJMP LOOP ; END。

把程序下载到实验板,看到了什么?灯开始闪烁了,这可是用定时器做的,不再是主程序的循环了。简单分析一下程序,为什么用JBC 呢?TF0 是定时/计数器0 的溢出标记位,当定时器产生溢出后,该位由“0”变“1”,所以查询该位就可知道定时时间是否已到,该位为“1”后,要用软件将标记位清“0”,以便下一次定时时间到了将该位由“0”变为“1”,所以用了JBC 指令,该指令前面已经学过--判“1”转移的同时,将该位清“0”。

以上程序可以实现灯的闪烁了,可是主程序除了让灯闪烁外,还是不能做其他的事啊!不对,我们可以在LOOP:JBC TF0,NEXT 和AJMP LOOP 指令之间插入一些指令来做其他的事情,只要保证执行这些指令的执行时间少于定时时间就可以了。

提个问题,我们在用软件延时程序的时候不是也可以用DJNZ 替代一些指令吗?是的,但是那就要求你精确计算所用指令的时间,然后再减去相应的DJNZ 循环次数,很不方便,而现在只要求所用指令的时间少于定时时间就行,显然要求低了。当然,这样的方法还不是最好,所以我们常用下面的方法来实现: 实验二、利用中断方式实现灯的延时

ORG 30H ;START:MOV P1,#0FFH ;关所有灯MOV TMOD,#00000001B ; 定时/计数器0 工作于方式1 MOV TH0,#15H ; MOV TL0,#0A0H ;立即数5536 SETB EA ;开总中断允许SETB ET0 ;开定时/计数器0 允许SETB TR0 ;定时/计数器0 开始运行LOOP:AJMP LOOP ;真正工作时,这里可写任意程序TIME0:PUSH ACC ;将ACC 推入堆栈保护PUSH PSW ;将PSW 推入堆栈保护CPL P1.0 ;取反P1.0 MOV TH0,#15H ; MOV TL0,#0A0H ;重置定时常数POP PSW ;POP ACC ;RETI ;END。

上面的例子中,定时时间一到,TF0 由“0”变“1”,就会引发中断,CPU 将自动转至000B 处寻找程序并执行,由于留给定时器中断的地址空间只有8 个字节,显然不足以写下所有的中断处理程序,所以在ORG 000BH 后安排了一条长跳转指令,转到实际处理中断的程序处,这样,中断程序可以写在任意地方,也可以写任意长度了。单片机进入定时中断后,首先要保存当前的一些状态,在这里程序只演示了保存ACC 和PSW,实际工作中应该根据需要将可能会改变的单元的值都推入堆栈进行保护(本程序中实际不需保护任何值,这里只作个演示)。 上面的两个程序运行后,我们发现灯的闪烁非常快,根本分辨不出来,只是视觉上感到灯有些晃动而已,为什么呢?我们可以计算一下,定时器中预置的数是5536 ,所以每计60000(65536-5536 )个脉冲就是定时时间到,这60000 个脉冲的时间是多少呢?我们的晶振是12 兆的,所以就是60000 微秒,即60 毫秒,因此速度是非常快的。如果我想实现一个1 秒的定时器,该怎么办呢?在该晶振频率下,最长的定时也就是65.536 个毫秒啊!请看第三个实验: 实验三、延长定时时间的方法 程序如下:

ORG 0000H ; AJMP START ;ORG 000BH ;定时器

0 的中断向量地址

AJMP TIME0 ;跳转到真正的定时器程序处

ORG 30H ;START:MOV P1,#0FFH ; 关所有的灯MOV 30H,#00H ;软件计数器预清0 MOV TMOD,#00000001B; 定时/计数器0 工作于方式1 MOV TH0,#3CH ;MOV TL0,#0B0H ;立即数(3CH+0BH=15536)SETB EA ;开总中断允许SETB ET0 ;开定时/计数器0 允许SETB TR0 ;定时/计数器0 开始运行

LOOP:AJMP LOOP ;真正工作时,这里可写任意程序TIME0:PUSH ACC ;将ACC 推入堆栈保护PUSH PSW ;将PSW 推入堆栈保护INC 30H ;MOV A,30H ;CJNE A,#20,TIME1 ;30H 单元中的值到了20 了吗? CPL P1.0 ;到了,取反P1.0 MOV 30H,#0 ;清软件计数器

TIME1:MOV TH0,#15H ;给T0 重新赋值MOV TL0,#9FH ;重置定时常数POP PSW ;POP ACC ;RETI ;END。

先自己分析一下程序,看看是怎么实现的?这里采用了软件计数器的概念,思路是这样的,先用T0 做一个50 毫秒的定时器,定时时间到了之后并不是立即取反P1.0,而是将软件计数器中的值加1,如果软件计数器计到了20,就取反一次P1.0,并清掉软件计数器中的值;否则直接返回。这样,就变成了20 次定时中断才取反一次P1.0,因此定时时间就延长了成了20*50mS ,即1000 毫秒了。这个思路在实际的工程应用中是非常有用的,比如有时候我们需要若干个定时器,可89C51 中总共才有2 个,怎么办呢?其实,只要这几个定时器在时间上有一定的公约数,我们就可以用软件定时器加以实现。例如要实现P1.0 口所接灯按1S/次,而P1.1 口所接灯按2S/次闪烁,怎么实现呢?我们可以用两个计数器,一个在它计到20 时,取反一次P1.0,并清“0”,如上面所示;而另一个则计到40 取反一次P1.1,然后清“0”,不就行了吗?看下面的实验: 实验四、软件定时器的实现方法 程序如下:

ORG 0000H ; AJMP START ; ORG 000BH ;定时器

0 的中断向量地址

AJMP TIME0 ;跳转到真正的定时器程序处

ORG 0030H ; START:MOV P1,#0FFH ; 关所有的灯MOV 30H,#00H ;软件计数器预清0 MOV TMOD,#00000001B ; 定时/计数器0 工作于方式1 MOV TH0,#3CH ;MOV TL0,#0B0H ;立即数15536 SETB EA ;开总中断允许SETB ET0 ;开定时/计数器0 允许SETB TR0 ;定时/计数器0 开始运行LOOP:AJMP LOOP ;真正工作时,这里可写任意程序TIME0: PUSH ACC ;将ACC 推入堆栈保护PUSH PSW ;将PSW 推入堆栈保护INC 30H ;INC 31H ;两个计数器都加1

MOV A,30H ; CJNE A,#20,TNEXT ;30H 单元中的值到了20 了吗CPL P1.0 ;到了,取反P1.0

这就是软件定时器的用法,试试看,用软件定时器做一个交通信号灯的实验,要求红灯亮2 分钟,黄灯亮1 分钟,绿灯亮3 分钟,然后红灯再亮2 分钟,黄灯再亮1 分钟,绿灯再亮3 分钟,不断的循环??。通过上面的几个实验,大家对定时器的使用方法是不是有了一个初步认识,接下来让我们共同来做一个更为有趣的实验:用单片机做一个乐曲编奏器。实验五、可编程乐曲演奏器

单片机用作乐曲编奏器的原理是,通过控制定时器的定时时间来产生不同频率的方波,驱动喇叭发出不同音阶的声音,再利用延迟来控制发音时间的长短,就能控制音调中的节拍。编程时,把乐谱中的音符和相应的节拍变换为定时常数和延迟常数,把数据表格存放在存储器中,由查表程序得到相应的定时常数和延迟常数,分别用定时器控制产生方波的频率和发出该频率方波的持续时间,当延迟时间到了之后,再查下一个音符的定时常数和延迟常数。依次进行下去,就可自动演奏出悦耳动听的乐曲来。 程序如下:

ORG 001BH ;定时器T1 的中断入口 MOV TH1,R1 ;重装定时初值 MOV TL1,R0 ;

CPL P3.7 ;P1.0 输出方波 RETI ;中断返回 ORG 100H ;主程序

START:MOV TMOD,#10H ; 定时器T1 工作方式1 MOV IE,#88H ;允许T1 中断 MOV DPTR,#TAB ;表格首地址 LOOP:CLR A ; MOVC A,@A+DPTR ;查表

MOV R1,A ;定时器高8 为存R1 INC DPTR ; CLR A ;

MOVC A,@A+DPTR ;查表

MOV R0,A ;定时器低8 为存R0 ORL A,R1 ;

JZ NEXT0 ;全0 为休止符 MOV A,R0 ; ANL A,R1 ;

CJNE A,#0FFH,NEXT ;全1 表示乐曲结束SJMP START ;从头开始,循环演奏NEXT:MOV TH1,R1 ;装入定时值MOV TL1,R0 ; SETB TR1 ;启动定时器SJMP NEXT1 ; NEXT0:CLR TR1 ;关闭定时器,停止发音NEXT1:CLR A ; INC DPTR ; MOVC A,@A+DPTR ;查延迟常数MOV R2,A ; LOOP1:LCALL D200 ;调用延时200mS 子程序

上述程序是歌曲“新年好”的一段简谱:1=C 1 1 1 5 │ 3 3 3 1 │ 1 3 5 5 │ 4 3 2 —│,如何来实现的呢?。单片机的晶振为12M,则乐曲、频率及定时常数三者之间的对应关系如下表所示:

我们用定时器T1 工作方式1 来产生歌谱中各音符对应频率的方波,由P3.7 输出驱动蜂鸣器,节拍的控制通过调用延时子程序D200 (延


单片机经典教程 - 图文(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:某工程监理大纲

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: