只要把汇编指令都写出来了,你就可以到指令表中找到每一条指令所对应的机器码,然后你只要在机器码后面加上操作数即可,比如,把一个30H单元送入A累加器;指令是这样的:MOV A , 30H .那么你可以在指令表中查到执行这条指的机器码是1110 0101,但是由于这条指令后面的那个30H单元的数是根据你的要求在不断的变的,机器没规定你只能用30H单元,所以这个30的操作数必须由你填,它们和在一块儿,这条指令的机器码是:1110 0101 0011 0000用十六进制来表示:E530,很明显前两位E5是机器指定的,而后两位30是你自己加进去的。共是十六位,占用两个字节……。
你说的LED灯闪烁,不知是指的流水灯还是一只发光二极管在不停地闪烁?但不管是哪一种,有一点很重要。你在编写此程序时必须要考虑延时,因为51单片机的晶体振荡器最低频率可能是6M(具体数值我已记不清了)。也就是说单片机的每一个机器周期所占用的时间仅2微秒,如果你不考虑延时的话,那么你设计的那盏灯,它闪烁的结果是;亮2微秒,熄2微秒,也就是说每一秒钟要亮暗50万次,肉眼看这盏灯根本就不会有熄灭的时候,只是比不闪的灯暗了一半。我们生活中用的白炽灯,每秒钟亮暗100次,你能感觉出灯泡有熄灭的时候吗?更何况那是50万次啊!
比如设计流水灯的程序,不妨可以这样考虑它的算法。计数寄存器的高八位加上低八位,合起来也只有十六位,它能数的数最大也就是65535,就算单片机用的是最低的6M的晶体振荡器,一个机器周期是12个机器节拍,所以,每一个机器周期占用2微秒时间,从0数到65535,仅用了131070微秒就数完了,约130毫秒,如果就按这个延时去改变灯的亮暗时间,那么这盏灯每秒钟要亮暗3、4次,肉眼虽然能够看到灯有熄灭的时间了。但是眼睛看这样的灯总不会那么舒服,所以至少应让它延时到1秒钟亮暗一次。为了计算方便,就让计数器数100毫秒的时间吧!等计数器数到100毫秒后,就让它再数一次,然后再数一次……,等它数满5次后,这就是500毫秒(半秒钟),然后,我们再去改变灯的亮暗状态。
这个程序可以这样来编:
MOV A ,#0FEH ;最低位设为0
MOV P1, A ;点亮最低位灯
MOV TCON,#10H ;T1为方式1,定时
BEGIN: MOV R7 ,#05H ;设循环5次
STAR: MOV TH1 #3CH ;计数器数100毫秒
MOV TL1 #AFH
SETB TR1 ;开始计数
ROU: JBC TF1 SE ;100毫秒到否?
SJMP ROU ;等待到100毫秒
SE: CLR TR1 ;关闭计数器
DJNZ R7 STAR ;5次循环到否? RL A ;把0向左移一位
MOV P1 ,A ;改下一只灯亮
SJMP BEGIN
51的单片机
ORG 0000H
MAIN:MOV R2,#2
L1:MOV R3,#200
L2:MOV R4,#200
L3:NOP
NOP
DJNZ R4,L3
DJNZ R3,L2
DJNZ R2,L1
CPL P1.7
JMP MAIN
END
Medwin编写C51汇编
八只LED灯做流水灯实验
单片机在上电初始后,其各端口输出为高电平。如果我们现在想让接在P1.0口的LED1亮,那么我们只要把P1.0口的电平变为低电平就可以了。想让LED1灭,LED0亮,只需将P1.0升高,P1.1变低,LED1就熄灭LED2随后既点亮!依始类推如下所示8只LED变会一亮一暗的做流水灯了.
P1.0低、P1.0高、P1.1低、P1.1高、P1.2低、P1.2高、P1.3低、P1.3高、P1.4低、P1.4高、P1.5低、P1.5高、P1.6低、P1.6高、P1.7低、P1.7高、返回到开始、程序结束。
我们不能说P1.1你变低,它就变低了。因为单片机听不懂我们的汉语的,只能接受二进制的“1、0......”代码。我们又怎样来用二进制语议论使单片机按我们的意思去工作呢?为了让单片机工作,只能将程序写为二进制代码交给其执行;早期单片机开发人员就是使用人工编写的二进制代码交给单片机去工作的。今天,我们不必用烦人的二进制去编写程序,完全可以将我们容易理解的“程序语言”通过“翻译”软件“翻译”成单片机所需的二进制代码,然后交给单片机去执行。这里的“程序语言”目前主要有汇编和C两种;在这里我们所说的“翻译”软件,同行们都叫它为“编译器”,将“程序语言”通过编译器产生单片机的二进制代码的过程叫编译。前面说到,要想使LED1变亮,只需将对应的单片机引脚电平变为低电平就可以了。现在让我们将上面提到的8只LED流水灯实验写为汇编语言程序。
“汉语”语言 汇编语言
开始: star:
P1.0低 clr p1.0
P1.0高 setb p1.0
P1.1低 clr p1.1
P1.1高 setb p1.1
P1.2低 clr p1.2
P1.2高 setb p1.2
P1.3低 clr p1.3
P1.3高 setb p1.3
P1.4低 clr p1.4
P1.4高 setb p1.4
P1.5低 clr p1.5
P1.5高 setb p1.5
P1.6低 clr p1.6
P1.6高 setb p1.6
P1.7低 clr p1.7
P1.7高 setb p1.7
返回到开始 ljmp star
结束 end
这里用到了四条汇编指令:clr、 setb、 ljmp 、end;
clr:是将其后面指定的位清为0;
setb:是将其后面指定的位置成1;
ljmp:是无条件跳转指令,意思是:跳转到指定的标号处继续运行。
end:是一条告诉编译器:程序到此结束的伪指令。伪指令只告诉编译器此程序到此有何 要求或条件,它不参与和影响程序的执行。这里需要说明的是,按汇编语法要求,所编制的程序(下称源程序)之格式和书写要求必须依下列原则:
1、源程序必须为纯文本格式文件,如用Windows“附件”中的“记事本”编写的文本文件;2、源程序的扩展名应是 *.ASM; 3、一行只能写一条语句,以回车作为本句的结束,每一语句行长度应少于80个字符(即40个汉字)。 4、每行的格式应为:标号: 命令 参数 ;注释
即一行由四部份组成,各部份的顺序不能搞错,依实际要求可以缺省其中的一部份或几部份,甚至全部省去,即空白行。需要使用标号时标号后面必须有“:”(冒号),而命令语句和参数之间必须用空格分开,如果命令有多个参数,则参数与参数之间必须用“,”(逗号)分开,需要注释时注释前必须用“;”(分号),“;”后面的语句可以写任何字符,包括汉字用于解释前面的汇编语句,它将不参与汇编,不生成代码。由于汇编程序对我们还不直观,所以在编写源程序时,应当养成多写注释的习惯,这样有助于今后源程序的阅读和维护。
标号是标志程序中某一行的符号名,编译后标号的数值就是标号所在行代码的地址。在宏汇编ASM51中标号的长度不受限制,但标号中不能包含‘:’或其它的一些特殊符号,也不能用汉字,可以用数字作标号,但必须用字母开头。当标号作参数用(如标号作转移地址),在命令后面出现时,必须舍去‘:’(如上面程序中的 LJMP STAR中的 STAR 是不能再有:)。
每行只能有一个标号,一个标号只能用在一处,如果有两行用了同一个标号,则汇编时就会出错。由于标号的长度没有限制,可以用有意义的英文或汉语拼音来说明行,使源程序读起来更方便。
源程序中的字母不区分大小写,也就是说 star 和 STAR 是一样的,请不要用大小写方式去区分不同的标号
:
流水灯实验详解二
上一节的实验最后没有得到“流水”显示的效果,主要是单片机执行每条指令的时间很短,我们肉眼无法看到LED的熄灭与点亮。单片机内部能按部就班的自动工作,正是在系统时钟的作用下,内部各逻辑硬件产生各种所需脉冲信号而实现的。这个时钟信号(既晶体振荡信号)的周期称“振荡周期”。我们这个实验中晶体使用的是12MHZ. 在单片机中,要处理最短周期的一条指令需要由12个振荡周期(既晶振振荡周期)组成的,这个叫“机器周期”。 8051核的单片机,大多数指令只用一个机器周期(既单周期),也有双周期和四周期的指令。本实验中用到的SETB P.x和CLR P.x均属于单周期指令,也就是说,执行一句 SETB P.x 用时仅1uS(微秒),CLR P.x 也是1uS;难怪我们前面的程序不能看到流水效果。 现在,将程序改动一下,在每点亮一个LED后,让程序干点别的事,也就是让它等一会再将该LED熄灭,继续执行下面的程序:
DDW: ;程序开始
CLR P1.0 ;LED1亮
ACALL DELAY ;调用延时子程序
SETB P1.0 ;LED1灭
CLR P1.1 ;换灯,同上
ACALL DELAY
SETB P1.1
CLR P1.2
ACALL DELAY
SETB P1.2
CLR P1.3
ACALL DELAY
SETB P1.3
CLR P1.4
ACALL DELAY
SETB P1.4
CLR P1.5
ACALL DELAY
SETB P1.5
CLR P1.6
ACALL DELAY
SETB P1.6
CLR P1.7
ACALL DELAY
SETB P1.7
LJMP DDW ;返回到开始循环
DELAY: ;延时子程序
MOV R1,#50
AD10:
MOV R2,#100
AD11:
MOV R3,#100
DJNZ R3,$
DJNZ R2,AD11
DJNZ R1,AD10
RET ;延时子程序结束,返回到调用处的下一句
END
请将上面的程序保存为 1LED.asm,进行编译,并烧写到AT89S51中,之后将89S51安装到套件的实验部份插座上实验,这回显示的就是“流水灯”的效果了!?回过头,让我们看看延时子程序是怎样工作的:单片机内部有不少寄存器,这些寄存器在单片机通电时,你可以给他写入数据(是单片机按你程序要求写的数据,而不是编程器写的),当第二次给他写入新数据时,前次的数据就被新数据覆盖;当然也可以从寄存器中读取数据。当单片机没有电源供给时,寄存器内部的数据也随即消失;这些寄存器人们叫他RAM,而用编程器将我们编写的程序烧写到单片机中的存储器叫ROM;现在,我们应该清楚:RAM是让程序去使用的,ROM是我们编写的程序存放的地方! 前面说过,单片机内部有不少RAM,本实验用的AT89C51有多少寄存器?我们现在不必关心,现在只须知道单片机内部有名叫R0~R7 的这8个寄存器。这8个寄存器每个都由8个单独的位寄存器组成,最大存放数据为二进制的 1111 1111,十六进制 = FF,十进制 = 255。在使用时注意不要大于其有效范围。上面延时程序中,先用到 MOV R1,#50 ,MOV是移动的意思,该句是将50这个十进制数放到R1中;50是立即数,按汇编语言要求前面要加“#”号,汇编语言还规定,十六进制数后面要加“?H”,十六进制数的高位是字母时在字母前面还要加“0”,例如:#0F8H;二进制数后面加“B”,例如:#11110000B。十进制不加,例如:#100。延时程序的第二、三句为: MOV R2,#100 ;MOV R3,#100 ;这两句意思同前。第四句中DJNZ R3,$ 的意思是将 R3 里面的数减 1 后如果 R3 不等于 0 则跳到后面指定的程序位置,这里的“$”既要跳转的程序位置,“$”代表当前语句处,也就是说,R3不等于 0,程序返回再次执行本句。如果R3 减 1 后等于0,程序结束本句,继续执行下面的语句。延时程序的最后一句是RET ,意思是退出本子程序,返回到调用本子程序处的下一句。根据上面的解释,一进入延时子程序首先为R1, R2, R3 寄存器装入我们需要的数据,然后先对R3 进行减数,每次减 1 ,R3 减完后减R2 ,减R2 时就费事啦,因为R2 每减 1 后不为 0 需要跳转到AD11 标号处执行下面的语句,此时R3 再次装入数据100,并且还要再次对R3 进行减数......,R2 减完后减R1,减R1的过程你研究研究看看。 每执行 DJNZ ?Rn,rel (Rn 指 R0~R7,rel 指转移地址)指令一次,需要2个机器周期,单片机需耗时2uS(指本实验),若忽略装数等语句,延时子程序从开始到结束,单片机共耗时100*100*50*2nS,既1000000uS=1秒!若加上装数等语句的耗时,延时时间大于1秒。 到此,我们做的流水灯已成功,原理大致也明白啦,若你自认为这一课你完全明白了,那请你将“流水灯”的流向改变一下,也可以改为两边向内流,内部向外流......,我想你一定能用前面学到的方法实现这些功能。可能有些高手说,前面的编程方法是最最笨的!,不错!但玩单片机初期不必讲究语言的简练,只要能完成预先要求就好,这是初学者要知道的。那么还有更好的编程思路吗?有!请继续学习下节课
做流水灯实验详解三
在上节课中让 LED 流水是去逐个控制P1端口的每个位来实现的,那么我们在程序一开始就给P1口送一个数,这个数本身就让P1.0先低,其他位为高,然后让这个数据向高位移动不就实现“流水”效果啦?的确如此!可惜,8051没有让P1数据移动的指令,但有对累加器ACC中数据左移或右移的指令,ACC是8051单片机内部算术逻辑单元中的一个“寄存器”(这里叫他寄存器是不正确的,但你可以先这样理解,ACC在指令中常写为A),他在数据传输和数据处理过程中作用十分重要,ACC为8位。他可与片内所有单字节寄存器交换数据,实际上P1和其他端口在单片机中也是一个寄存器。这样我们可以将需移动的数据先放到ACC中,让其移动,然后将ACC移动后的数据再转送到P1口,这样同样可以实现“流水”效果。
程序如下:DDW: ;开始
MOV ACC,#0FEH ;ACC中先装入LED1熄灭的数据(即二进制的 1111 1110)
MOV P1,ACC ;将ACC的数据送P1口
MOV R0,#7 ;因上句送到?p1口的数据就熄灭了一位,所以将数据再移动7次就完成一个8位流水过程
LOOP: ;数据移动循环
Rl A ;将ACC中的数据左移一位
MOV P1,A ;把ACC移动过的数据送p1口显示
ACALL DELAY ;调用延时
DJNZ R0,LOOP ;没有移动够7次继续移动
LJMP DDW ;移动完7次后跳到开始重来,以达到循环流动效果
DELAY: ;延时子程序,就是上节课中的延时子程序
MOV R1,#50
ADl0:
MOV R2,#100
ADl1:
MOV R3,#100
DJNZ R3,$
DJNZ R2,AD11
DJNZ R1,AD10
RET ;延时子程序结束,返回到调用处的下一句
END ;本汇编程序到此结束
接下来,将上述程序编译,并烧写到前面我们的实验芯片中,流水效果与第二节课的一样。 其实8051单片机有111条指令,这111条指令好比以前我们使用数字传呼机时的“短语代码”一样,可以用几个“短语代码”去表示一句完整、通顺的语句段落。有的指令常用,有的指令不常用,只要遵守语法规则,你可以用这些指令“组合”成你想象到的任何程序。当然,有时一条指令可以替代很多条指令,这样会使程序简捷,费码减少,在编写较大程序时可以让程序存储器放得下你需要的代码。这也是单片机高手所追求的。当然,在程序存储器空间不成问题时,你不这样做但也可以达到预期的功能,这也不算错。 单片机内部还有很多“部件”我们只是用到什么说什么,很不系统。但是我也不想系统的介绍这些,因系统介绍单片机结构和指令的书很多,何况写的远比我好,因此,希望你在看本讲座的过程中,还要结合正规的教材学习其更多的指令和“部件”。
这是我在别的地方找过来的,希望对你有所帮助。
我用的是WAVE6000编译的。
其他回答 按时间排序 按投票数排序
0
wsdx888 2009-9-3 10:25:17 124.128.36.* 举报 单片机的内部结构
单片机是把微型计算机的主要组成部分CPU、存储器、输入/输出接口等集成在一块超大规模集成电路芯片上。
它是由CPU系统、程序存储器、数据存储器、各种I/O端口、基本功能单元(定时器/计数器等)组成。
1.CPU系统
CPU系统包括有CPU、时钟系统、复位、总线(BUS,即信号的公共通道)控制逻辑。
(1)CPU
单片机中的CPU与微型计算机中的CPU有所不同,它的特点是,面向控制、面向嵌入系统、面向单芯片化。
(2)时钟系统
时钟系统用于产生单片机工作所需的时钟信号。它必须满足CPU及单片机内各单元电路对时钟的要求。时钟振荡器的工作频率一般在1.2~12MHz。
(3)复位电路
复位电路应满足上电复位、信号控制复位的要求。
(4)总线控制逻辑
总线控制逻辑应满足CPU对内部总线和外部总线的控制要求。
2.程序存储器
程序存储器是一种只读存储器ROM(Read Only Memory),用它来固化单片机的应用程序和一些表格常数。单片机生产厂家按单片机内部程序存储器的不同结构,形成单片机的不同结构类型,计有:
(1)Mask ROM型 (2)EPROM型 (3)ROM less型 (4)OTP ROM (5)Flash ROM(MTP ROM)型
前三种程序存储器的单片机是早期的产品,目前EPROM、ROM Less型已较少使用。
3.数据存储器RAM
RAM是一种可读写的存储器,也叫随机存储器。单片机内部的RAM除了作为工作寄存器、位标志和堆栈区以外的单元都可以作为数据缓冲器使用,存放输入的数据或运算的结果。
由于单片机主要是面向测控系统,所以单片机内部的数据存储器容量较小,通常不多于256字节,而且都使用静态随机存储器SRAM(Static Random Access Memory)。
4.各种I/O端口
I/O端口是计算机的输入、输出接口(T是输入,O是输出之意)。单片机中的I/O端口都是芯片的辅入/输出引脚。这些I/O端口,可分为以下几种类型:
(1)总线输入/输出端口
(2)用户I/O端口。由用户用于外部电路的输入/输出控制。
(3)单片机内部功能的输入/输出端口。例如,定时器/计数器的计数辅入、外部中断源辅入等。
为减少单片机引脚数量,一般I/O口都有复式功能。例如不使用外部总线时,总线端口可出让给用户做辅入/辅出端口用。
从I/O口的结构上还可以分为并行I/O口,即多位数据一起输出或输入,这种形式传送数据速度快但使用的引脚多。另—种I/O口称为串行I/O口,即传送数据是顺序输出或输入,这种形式可大大减少I/O口的引脚数,但传送数据较慢。
5.基本功能单元
基本功能单元是为满足单片机测控功能而设置的一些电路,是用来完善和扩大计算机功能的一些基本电路,如定时器/计数器,中断系统等。定时器/计数器在实际应用中作用非常大,如精确的定时,或者对外部事件进行计数等。
手机可以存储,U盘可以存储,用手机的内存卡加上一个读卡器也可以存储东西,注意手机可不要存储些有毒的东西...
手机