|
上回聊了单片机的一些基本概念,见:
http://www.crystalradio.cn/bbs/thread-155177-1-1.html
这回聊聊单片机到底是如何干活的?也就是这个小玩意是如何工作的。
1、从哪里开始?
任何事情总有一个开头,单片机也不例外,怎么样的开头呢?想想一个小孩醒来第一件事作什么?一般情况是先找妈妈,然后妈妈告诉他要作什么事,如何去作(考拉喜欢用小孩来比单片机,因为单片机很象心智未开的小宝宝,什么都得你替他安排,教他去作)。如果我们把妈妈理解为小孩的程序(告诉他要作的每件事的每一个步骤),那么小孩子就必须先找到妈妈所在的地方。
单片机其实也一样,它只要一醒来(加上电源),首先也要到一个固定的地方找程序,看看有没有指令要执行。这个地方当然是位于单片机程序存储器内的某个地方,不同的单片机不一样,多数是程序存储器寻址空间的最开头(如0000H,这是16进制,概念和为啥要加个H后面再说),有的在其他地方(象PIC16C5x)。这个地址就是单片机运行程序开始的地方,也就是程序的入口地址,有些书上也叫复位矢量或复位向量。
知道了单片机是从哪里开始的,那么我们也就清楚了一件事:如果要让单片机正确的运行,就必须把所编程序的第一条指令放在程序入口地址(复位矢量)处。
2、如何自动工作?
有了开头下来单片机该干活了,怎么干呢?假如一个小孩子作事情每作一步都停下来等你的指示,你会不会有些烦?就象俗话说的碗里的芋头筷子拨一下动一下。我们当然希望能一次告诉他所有要作的事情,然后他自己按步骤去完成。能不能实现自动化呢?当然可以,但需要一些辅助手段。
当单片机在程序入口处找到了程序的第一条指令执行后,如果要实现自动运行而不是等你的命令,它就必须知道下一条指令在什么地方。同理,如果要保证整个程序的自动执行,单片机必须在取得一条指令并执行后知道下一条指令放在什么地方。怎么实现呢?最直接的办法当然是在当前指令里附上下一条指令的存放地址(早期的计算机就有这么干的),但这样一来指令会变得很长,费空间不说执行速度也慢。于是后来人们想了另外一个办法,在计算机内设置了一个程序计数器(Program Counter,缩写为PC),在PC里存入下一条要执行的指令的地址。单片机里也有一个PC,它每到PC里记录的地址处取一条指令,PC就自动加1指向下一条指令的地址,从而实现了程序的自动执行。但上面的这个设计只适应于程序的指令是按顺序指行的情况,如果因为某种需要不能按顺序执行需要跳转到程序的另一段怎么办呢?也简单,只要在需要跳转的地方由特殊的指令修改PC的值,变为要跳转执行的程序段的第一条指令存放地址就行了。
PC就象整个单片机运行的指挥官,指挥着单片机的自动运行。明白了这个前面讲的复位后的程序入口地址也就更好理解了,只要单片机在上电复位时给PC设置为程序入口的地址(复位矢量),单片机就自动到那里去找指令了。此外理解了PC的概念也就明白了单片机程序寻址空间的由来。PC的长度决定了可以存放地址的大小,所以由PC的字长就决定了程序寻址空间的大小。象标准51的PC是16位的,故51的程序寻址空间就是64K了。计算方法如下:16位2进制最大计数值是10进制的65535,加上0(因为是从0而不是从1开始计数的)是65536个,而计算机里的1K=1024(2的10次方),65536除以1024等于64,也就是64K了。
3、怎样步调一致?
从前面这些描述,你一定也已经明白单片机内部是一个挺复杂的结构,有很多东西在协同工作来完成各种功能。这就有了一个问题,这个不同的部件如何协同工作而不发生错误呢?比如当前一条指令还没取(地址还没用)但PC已经提前加1指向了下一条指令岂不乱套!也就是说这些部件有一个协同工作步调一致的问题。
想想舞台上的小乐队是如何同步的呢?一般是听鼓手的鼓点。而舞池里的众人如何一起跳舞呢?当然是听乐曲的节奏。也就是说生活中我们往往需要一个节奏来供大家协同,单片机其实也一样,这个节奏就是单片机的时钟。单片机内部的各个部件在时钟的统一节奏下按部就班的工作,保证了互相的配合与协同。同时时钟也决定了单片机工作的速度,时钟越快速度也就越快。
单片机的时钟可以由外部提供,也可以由内部电路提供。外部提供时由一个专门的时钟脉冲电路产生时钟信号注入单片机。内部电路提供时有几种情况,最常见的是振荡电路内部已经集成,但晶振和微调电容需要外接。常用的晶振有4M/6M/8M等,51常用6M和12M,这和其内部的时序设计有关(后面再细说)。还有一些非整数晶振也常用,比如11.0592,为什么要用这种晶振呢?这是为了串行通讯的需要,这些频率分频后能够精确的产生串行通讯所需要的波特率(这个概念后面聊到串行异步通讯时再说)。一些比较新的单片机(如AVR M8)可以由内部集成的电路(一般是一个RC振荡电路)产生时钟信号,因此设置好后不用外接晶振也能工作。
4、正确的开始很重要
前面已经说了加电后单片机内部是怎么运作的。但熟悉模拟电路的都知道当电源启动后到电压上升达到稳定是有一个时间的,虽然时间很短但在这个期间还是会有一些波动以及电压达不到预定值等问题。从前面单片机用的时钟晶振就可以知道单片机运行的速度是很快的,虽然电源达到稳定的时间短,但这段时间已经足够单片机作很多事情了。假如电压不稳定而单片机已经开始干活,就可能因为电源的各种问题给单片机的工作带来干扰,甚至产生运行错误。
如何避免呢?最简单的办法当然是等电源电压稳定了再干活,因此单片机就需要一个上电复位电路。单片机一般都有一个复位引脚,叫作RESET/RST或其他名字,当这个引脚接上预定的高电平或低电平(这个词后面再解释)时,单片机就复位,回到刚加电的状态,进行内部初始化,并重新到复位矢量处去从头执行程序。因此只要在系统加电时让复位引脚保持在复位电平一段时间,等到电源稳定再撤销,就可以实现正确的上电复位。简单的上电复位电路可以用一个电容和一个电阻构成,上电时由于电容充电让复位引脚保持在复位电平,充满电后自动撤销进入正常运转。例如51是高电平复位,就可以让RST(51的复位引脚)通过电容(常用10uF或22uF)接VCC(电源正极),同时通过一只电阻(常用1K欧或10K欧)接到GND(电源负极,也即地线),上电时电容充电使RST保持高电平处于复位状态,充满电后由于接地的电阻使RST处于低电平进入正常运行,电容的容量和电阻的大小决定了上电复位的时间。只要电容和电阻构成复位电路的充电时间大于电源电压稳定所需要的时间,就可以保证单片机的正确复位。
除了这种简单的电路还有一些专用的单片机复位集成电路,可以更可靠的为单片机提供上电复位服务。此外一些比较新的单片机如AVR M8和PIC等内部集成了上电复位电路,可以使单片机上电后延时一段时间再开始工作,因此这些单片机只要设置正确不用外部复位电路也能正常工作。
5、哪些是必须的?
从前面聊的这些我们已经知道单片机要干活除了电源还是需要一些外部条件的。首先需要一个时钟,比如51要外接一个晶振和俩微调电容(常用30PF);其次需要一个上电复位电路以保证可靠的复位。有了这些单片机就已经准备好可以接受程序工作了,因此以上这些就可以称为单片机的最小系统,基本是由单片机本身,时钟电路,上电复位电路三者构成。后面附了一张参考图,是网上找的。注意图上多接了一根线,EA脚(右边中间部位)也接了VCC电压,为什么要接这根线后面再说,这里不必深究。
注意最小系统不是一个固定的概念,不同的单片机可能最小系统构成不同,同样的单片机可能设置方式不同最小系统构成也不同。简单到极致时钟和上电复位全部用内部集成的,一个芯片就已经是最小系统了。所以最小系统应该理解为可以保证可靠的上电复位以及正常运行的最小系统构成。
另外注意这里说的最小系统和一些市售最小系统板的区别。这里的最小系统是一个理论上的概念,而市售的最小系统是一个实验中的概念。这些最小系统板除了前面说的理论上的单片机最小系统外,一般还集成了供电系统、串行通讯系统、程序下载系统、以及总线驱动系统等(根据设计和需要会有一些取舍)。这些可以为你的实验提供可靠的保证,是一个实验应用中比较完备的单片机最小核心系统。
好了,单片机的基本运作模式已经把最基本的说差不多了,下面举一个实例具体说说单片机怎么干活。就举一个最简单的例子吧,单片机如何让一颗LED闪烁。星星之火可以燎原,相信考拉,只要你能让单片机点亮一只LED,就一定能够让它干更多更复杂的事情!
如何让一只LED闪烁呢?答案很简单,只要打开、关闭,再打开、再关闭不断重复就是了。别把很多问题想得太复杂,其实有时就和怎样把大象放进冰箱里一样简单,哈哈。虽然答案很简单,但如果直接让单片机这么干你是肯定看不到想要的结果的,原因就是单片机运行的太快了,运行一条指令的时间是以微秒计的。如果只是简单的打开和关上,你肯定会看到LED仍然是一直亮着,最多由于高速的打开和关闭亮度变暗了一点。
如何才能看到闪烁呢?也很简单,只要让打开和关闭的时间都长一点就是了。也就是在打开和关闭LED的命令间插入一段延时就行了,比如半秒(也就是500毫秒,写为500ms)。这样我们就可以得到一个闪烁的工作步骤:
第一步:打开LED;
第二步:延时500ms;
第三步:关闭LED;
第四步:延时500ms;
…………
只要不断重复下去就可以看到LED闪烁了。但这也带来了一个问题,就是程序好象是无限延续的,这可不成,程序存储器可不是无限的呀。我们可以稍稍改动一下变成如下的样子:
第一步:打开LED;
第二步:延时500ms;
第三步:关闭LED;
第四步:延时500ms;
第五步:返回第一步;
这样我们就能在有限的程序长度内完成无限时长的事情了,这就是循环。计算机是最擅长循环的,它既不会觉得累也不是觉得烦,很多问题的解决都需要循环执行一段程序来完成,后面还会大量遇到。这段程序还有一个问题,就是延时500ms重复出现了,很浪费,因此我们可以把这段程序作为子程序(也就是一个标准模块)来调用,具体调用的机制和方法后面再说,这里只要知道个意思就行,最后就成了这个样子:
第一步:打开LED;
第二步:调用延时500ms子程序;
第三步:关闭LED;
第四步:调用延时500ms子程序;
第五步:返回第一步;
延时500ms子程序:…………
上面这个结构已经是一个可以实用的程序逻辑结构了,但这个东西单片机是不认识的,下面给出一个实现上述功能的51汇编例程,注意俺没有经过实际运行测试,这也只是一个汇编程序段而不是一个完整的51汇编程序,只用来表述逻辑结构。假设LED接在51的P1.0引脚(P1口的第1个引脚,是51芯片的左边从上向下数第1个引脚)上,低电平LED亮。例程如下:
begin:
clr P1.0 ;设置P1.0为低电平,点亮LED
acall delay500ms ;调500毫秒延时子程序
setb P1.0 ;设置P1.0为高电平,熄灭LED
acall delay500ms ;调500毫秒延时子程序
ajmp begin ;重头再来
;===============================
delay500ms: ;6M下延时500ms子程序,实际程序多延时48微秒
mov temp0,#05h ;temp=5
delay500ms_1:
mov temp1,#64h ;temp1=100
delay500ms_2:
mov temp2,#0f8h ;temp2=248,外层循环DJNZ补上后循环体刚好1ms
djnz temp2,$
djnz temp1,delay500ms_2
djnz temp0,delay500ms_1
ret ;返回调用处继续执行
;===============================
end
稍说明几句,因为51上电复位后I/O口是都是高电平,而前面已经说明LED是低电平点亮,所以上电后LED是不亮的。而clr P1.0这句是把这个引脚设置为低电平,这样LED就亮了,setb P1.0则是把这个引脚设置为高电平,LED也就灭了。其他指令不必深究,后面再细说,大致明白单片机是这么干活的就行了。
今天就先说到这里了,下次聊聊用什么来指挥单片机干活,且听下回分解。
http://www.crystalradio.cn/bbs/viewthread.php?tid=156114
[ 本帖最后由 cosine 于 2010-12-11 14:03 编辑 ] |
-
51单片机最小系统
|