51系列单片机

最近在基于51单片机编程的过程中出现了个很奇怪的问题 “程序执行中在寄存器EA=1,ET0=1,TR0=1条件下,单TF0=1时并没有执行中断”。在有过单片机中断编程经历者都知道当EA=1,ET0=1的条件下,满足TF0=1时,如果在此期间没有更高优先级的中断执行的情况下定时器中断0必定会产生中断响应。而在我所编写的程序中仅使用了定时器中断0,一个中断也就谈不上存在优先级问题。

经过我对自己程序的检查并对各教材中断程序对比发现我的程序中的一个问题:由于中断的不可控性决定其跳出中断返回主程序的不确定,而由于程序需要中断跳出后能跳到指定的地址。为了解决这个问题我在中断结束的地方直接用了无条件跳转指令“LJMP ADR16”其中ADR16是我想在中断结束后程序所运行的地址,而没有经过指令“RE”。

问题找到了这就意味着我的程序和其他程序不同的地方就是没有执行“RE”而直接跳出。

为了解决问题所在我查阅了很多单片机方面的资料,教材。几乎所有的教材对指令“RETI”的作用千篇一律都是:“中断程序完成后,一定要执行一条RETI指令,执行这条指令后,CPU将会把堆栈中保存着的地址取出,送回PC,那么程序就会从主程序的中断处继续往下执行了。”如果“RETI”的作用仅仅在于“把堆栈中保存着的地址取出送回PC”;那么我用指令“POP DPH”和“POP DPL”两条指令取代其做用不就可以达到同样的推出地址的效果么?这样可以解决由于只有进堆栈指令(硬件自动生成)没有出堆栈所导致的堆栈溢出错误,但是并不能解决文章开始所提到的“进不了中断”问题。这让我更加相信书上所介绍的关于指令“RETI”作用并不完全。

经过查阅各种资料文献,我发现了个以往在介绍单片机硬件,以及寄存器上教材,老师,没有提及的“‘优先级生效’触发器“的概念。资料指出“根据8051的结构特点,其中断系统中含有两个不可寻址的“优先级生效”触发器。一个用于指出CPU是否正在执行高优先级的中断服务程序,这个触发器为1时,系统将屏蔽所有的中断请求;另一个则指出CPU是否正在执行低优先级中断服务程序,该触发器为1时,将阻止除高优先级以外的一切中断请求。由此可见,若要响应同级甚至是低级中断请求,必须使得该“优先级生效”触发器清零。但该触发器又是不可寻址的,所以无法用软件直接清零。”问题是不是在这里呢?而“优先级生效”触发器清零过程是怎样执行的呢?是在硬件自动执行的那么是在什么时候执行的呢?带着问题我去解决问题。假设我可以将程序满足跳出中断后跳到自己原来指定地址“ADR16”又满足执行指令“RETI”。经过反复思考我用“DEC SP”;“DEC SP”;“MOV DPTR,#ADR16”;“PUSH DPL”;“PUSH DPL”“PUSH DPH”四条指令代替,问题得到了解决。

总结:

中断指令“RETI”做为中断跳出指令除了将堆栈中保存着的地址取出,送回PC;使程序从主程序的中断处继续往下执行。的作用外还有将“优先级生效”触发器清零。自己做的程序也是出现了这个错误,由于对“优先级生效”触发器清零,导致第二次进不了中断(相当于同优先级申请)。

后记:

在解决这个问题时候我所用的知识是课本上的,而又不完全是课本上的。在这个过程中我用已学的知识解决了自己的问题,并进一步推出中断过程的一些新的知识,我认为新知识的学习有很大程度的要靠自己在已学过知识的基础上通过运用,总结,推导等过程获得新知识。着也是当代大学生运用知识,获取新知识的一种能力。

转自: 电子发烧友

围观 412

(一) 在我们讲解P0端口之前我们首先梳理一下各个端口有什么不同之处:
P0口有三个功能:
1、外部扩展存储器时,当做数据(Data)总线(如图1中的D0~D7为数据总线接口)
2、外部扩展存储器时,当作地址(Address)总线(如图1中的A0~A7为地址总线接口)
3、不扩展时,可做一般的I/O使用,但内部无上拉电阻,作为输入或输出时应在外部接上拉电阻(后面将详细介绍)。

P1口只做I/O口使用:其内部有上拉电阻。

P2口有两个功能:
1、扩展外部存储器时,当作地址总线使用(如图1中的A8~A15为地址总线接口)
2、做一般I/O口使用,其内部有上拉电阻;

P3口有两个功能:
除了作为I/O使用外(其内部有上拉电阻),还有一些特殊功能,由特殊寄存器来设置,具体功能请参考我们后面的引脚说明。

在介绍这四个I/O口时提到了一个“上拉电阻”那么上拉电阻又是一个什么东东呢?他起什么作用呢?都说了是电阻那当然就是一个电阻啦,当作为输入时,上拉电阻将其电位拉高,若输入为低电平则可提供电流源;所以如果P0口作为输入时,处在高阻抗状态,只有外接一个上拉电阻才能有效。

单片机P0口以及上拉电阻详解

图2(注:该图只是P0口的一位,也就是说P0口有8个相同的这样的结构)

单片机P0口以及上拉电阻详解

图3

(二) 由图2可以看出每个P0口都有这些元件:
一个锁存器,两个三态输入缓冲器和一个输出驱动电路组成

在访问外部存储器时,P0是一个真正的双向口,当P0输出地址/数据信息时,CPU内部法控制电平“1”来打开上面的与门,又使模拟开关MUX把地址/数据信息经过反相器和T1接通(我们称上面的场效应晶体管FET为T1,下面的场效应管FET为T2);

输出的地址/数据信息既通过与门去驱动T1,又通过反相器去驱动T2,是两个FET构成推拉输出电路;

1.当P0口作为外部扩展存储器的数据地址总线时:
· 若地址数据信息为“0”,那么这个信号就使得T1截止,使T2导通(经过反反相器作用使得T2接收到的信号为“1”,根据场效应晶体管的特性,T2导通),若T2导通,那么T2的上下两个N极就导通,而发射极(下面的N极)接地信号则为“0”,这样P0口就相当于接收到了“0”信号;

· 若地址数据信息输入“1”,则该信号使T2截止,使T1导通,在T1导通情况下,T1的上下N极导通,使得VCC与P0相同,从而输出高电平,即“1”信号;

· 若从P0口输入信号,信号从引脚通过输入缓冲器进入内部总线;

2.当P0口作为一般I/O口使用时:
· CPU内部发布控制信号“0”,封锁与门,使得T1截止,同时使模拟开关MUX把锁存器的非Q端与T2端的栅极接通;

· 在P0口作为输出时,由于非Q端和T2的倒相作用,那么内部总线上的信息与到达P0口上的信息是同相的,只要写脉冲加到锁存器的CL端,内部总线上的信息就会P0的引脚上;

· 但是由于此时T2为漏极开路输出,所以要外接上拉电阻。

· 当P0作为输入时,由于该信号既加到T2又加到下面的三态缓冲器。现在我们假设我们刚刚输出的信号为“0”,也就是输入锁存器的数据为“0”,经过非Q达到T2使T2导通,这样P0引脚上的信号就被T2钳在“0”电平上,这样就使输入的“1”无法读入。那么我们就必须在输入信号前,应该先向锁存器Q端写“1”,非Q就为“0”,使T2截止,这就是所谓的“准双向口”的解释。但是在访问片外存储器时,CPU会自动向锁存器Q写入“1”,所以对用户而言P0口作为数据/地址总线时,是一个真正的双向口。

(三) 下面我们说一下为什么要上拉电阻

单片机P0口以及上拉电阻详解

图4

由于P0口内部没有上拉电阻,是开漏的,不管它的驱动能力多大,相当于它是没有电源的,需要外部的电路提供,绝大多数情况下P0口是必需加上拉电阻的。作为一般的I/O口时,当P0口用来驱动PNP(如上图4所示)管子的时候,就不需要上拉电阻,因为此时的低电平有效;当P0口用来驱动NPN管子的时候,就需要上拉电阻的,因为此时只有当P0为1时候,才能够使后端导通。

其实说白了上拉就是将不确定的信号通过一个电阻钳位在高电平!电阻同时起限流作用!

上拉电阻就是从电源高电平引出的电阻接到输出端

第一种,如果电平用OC(集电极开路,TTL)或OD(漏极开路,CMOS)输出,那么不用上拉电阻是不能工作的, 这个很容易理解,管子没有电源就不能输出高电平了。 (这个就可以解释我们这里的原因)

第二种,如果输出电流比较大,输出的电平就会降低(这是电路中已经有了一个上拉电阻的情况下,但是电阻太大,压降太高),就可以用上拉电阻提供电流分量, 把电平“拉高”。(就是并一个电阻在IC内部的上拉电阻上, 让它的压降小一点)。其实这些都是按需要,工作在线性范围的上拉电阻不能太小,当然也会用这个方式来实现门电路电平的匹配。

51系列单片机的P0口作为通用I/O口使用时,内部输出电路为OD(漏极开路,CMOS),必须外接上拉电阻才能有高电平输出;而P1、P2、P3口内部输出电路中有上拉电阻故不需要接上拉电阻(这里的不需要接上拉电阻是相对而言的,若遇到第二种情况,就需要适当加一个上拉电阻,来减小压降)。

来源: 至秦单片机公众号

围观 586
订阅 RSS - 51系列单片机