标题: 4课:第一个单片机小程序 [打印本页]

作者: admin    时间: 2013-5-21 02:47
标题: 4课:第一个单片机小程序
 上一次我们的程序实在是没什么用,要灯亮还要重写一下片子,下面我们要让灯持续地闪烁,这就有一定的实用价值了,比如能把它当成汽车上的一个信号灯用了。怎样才能让灯持续地闪烁呢?实际上就是要灯亮一段时间,再灭一段时间,也就是说要P10持续地输出高和低电平。怎样实现这个要求呢?请考虑用下面的指令是否可行:SETB P1.0
CLR P1.0 ……
这是不行的,有两个问题,第一,计算机执行指令的时间很快,执行完SETB P1.0后,灯是灭了,但在极短时间(微秒级)后,计算机又执行了CLR P1.0指令,灯又亮了,所以根本分辨不出灯曾灭过。第二,在执行完CLR P10后,不会再去执行SETB P1.0指令,所以以后再也没有机会让灭了。
  为了解决这两个问题,我们能做如下设想,第一,在执行完SETB P1.0后,延时一段时间(几秒或零点几秒)再执行第二条指令,就能分辨出灯曾灭过了。第二在执行完第二条指令后,让计算机再去执行第一条指令,持续地在原地兜圈,我们称之为"循环",这样就能完成任务了。
以下先给出程序(后面括号中的数字是为了便于讲解而写的,实际不用输入):

;主程序:
LOOP: SETB P1.0    ;(1)熄灭灯
LCALL DELAY       ;(2)延时一段时间
CLR P1.0           ;(3)点亮灯
LCALL DELAY        ;(4)延时一段时间
AJMP LOOP          ;(5)跳转到第一句LOOP处
;以下子程序
DELAY: MOV R7,#250 ;(6)
D1: MOV R6,#250    ;(7)
D2: DJNZ R6,D2     ;(8)
       DJNZ R7,D1  ;(9)
       RET         ;(10)
END                ;(11)

本例keil工程文件点击这里下载

按上面的设想分析一下前面的五条指令。
  第一条是让灯灭,第二条应当是延时,第三条是让灯亮,第四条和第二条一模一样,也是延时,第五条应当是转去执行第一条指令。第二和第四条实现的原理稍后谈,先看第五条,AJMP是一条指令,意思是转移,往什么地方转移呢?后面跟的是LOOP,看一下,什么地方还有LOOP,对了,在第一条指令的前面有一个LOOP,所以很直观地,我们能认识到,它要转到第一条指令处。这个第一条指令前面的LOOP被称之为标号,它的用途就是给这一行起一个名字,便于使用。是否一定要给它起名叫LOOP呢?当然不是,起什么名字,完全由编程序的人决定,能称它为A,X等等,当然,这个时候,第五条指令AJMP后面的名字也得跟着改了。
  第二条和第四条指令的用途是延时,它是怎样实现的呢?指令的形式是LCALL,这条指令称为调用子程序指令,看一下指令后面跟的是什么,DELAY,找一下DELAY,在第六条指令的前面,显然,这也是一个标号。这条指令的作用是这样的:当执行LCALL指令时,程序就转到LCALL后面的标号所标定的程序处执行,如果在执行指令的过程中遇到RET指令,则程序就返回到LCALL指令的下面的一条指令继续执行,从第六行开始的指令中,能看到确实有RET指令。在执行第二条指令后,将转去执行第6条指令,而在执行完6,7,8,9条指令后将遇到第10条令:RET,执行该条指令后,程序将回来执行第三条指令,即将P10清零,使灯亮,然后又是第四条指令,执行第四条指令就是转去执行第6,7,8,9,10条指令,然后回来执行第5条指令,第5条指令就是让程序回到第1条开始执行,如此周而复始,灯就在持续地亮、灭了。
  在标号DELAY标志的这一行到RET这一行中的所有程序,这是一段延时程序,大概延时零点几秒,至于具体的时间,以后我们再学习如何计算。 程序的最后一行是END,这不是一条指令,它只是告诉我们程序到此结束,它被称为"伪指令"。
   单片机内部结构分析:为了知道延时程序是如何工作的,我们必需首先了解延时程序中出现的一些符号,就从R1开始,R1被称之为工作寄存器。什么是工作寄存器呢?让我们从现实生活中来找找答案。如果出一道数学题:123+567,让你回答结果是多少,你会马上答出是690,再看下面一道题:123+567+562,要让你要上回答,就不这么不难了吧?我们会怎样做呢?如果有张纸,就不难了,我们先算出123+567=690,把690写在纸上,然后再算690+562得到结果是1252。这其中1252是我们想要的结果,而690并非我们所要的结果,但是为了得到最终结果,我们又不得不先算出690,并记下来,这其实是一个中间结果,计算机中做运算和这个类似,为了要得到最终结果,一般要做很多步的中间结果,这些中间结果要有个地方放才行,把它们放哪呢?放在前面提到过的ROM中能吗?显然不行,因为计算机要将结果写进去,而ROM是不能写的,所以在单片机中另有一个区域称为RAM区(RAM是随机存取存储器的英文缩写),它能将数据写进去。 特别地,在MCS-51单片机中,将RAM中分出一块区域,称为工作寄存器区,上面程序用到的R6,R7就是在这个区里面,这我们会在第7课有详细的介绍。其实如果我们用C语言来写程序的话用根本不用了解工作寄存器这个概念了因为C编译器会自动处理.看上面的程序如果用c来写就是

#include <at89x52.h>
void DELAY()   //延时函数
{ unsigned char i,j;
    for(i=0;i<250;i++)
    {
        for(j=0;j<200;j++);
    }
}
void main() //程序从这里开始执行
{
while(1) //这句的作用就是反复的执行下面这个{}中包含的4句
    {
     P1_0=1;  //(1)熄灭灯
     DELAY(); //(2)延时一段时间
     P1_0=0;  //(3)点亮灯
     DELAY(); //(4)延时一段时间
    }
}
   在汇编例子中程序是从第一条语句开始执行的,而c不同在c语言里程序是从main() 这里开始执行的,关于(1)(2)(3)(4) 这几句的解释和上面的汇编一样,不再敖述。循环部分这里是用了一个while(1) 语句下面打了一个大括号,这样大括号中的这4条语句就会按(1)->(2)->(3)->(4) ->(1)->(2)->(3)->(4) ->(1)->(2)->(3)->(4)……永远不停的执行下去。这样灯就会持续的亮灭再亮再灭实现了闪烁效果,关于延时函数下节课再叙。有什么不懂的大家可以在下面提问

下一课:  5课:单片机延时程序分析
作者: 812125810    时间: 2013-5-22 22:41
赞~\(≧▽≦)/~。。
作者: 812125810    时间: 2013-5-22 22:54
感觉好容易懂的!
作者: 只有我的    时间: 2013-5-23 12:43
好....
作者: hi__guys    时间: 2013-5-23 22:32
很不错!
作者: hi__guys    时间: 2013-5-23 22:33
{:soso_e179:}
作者: ringer_wlw    时间: 2013-5-25 18:15
C语言不错。
作者: 好再来吧    时间: 2013-6-2 15:43
好奥好
作者: iamKhan    时间: 2013-6-18 16:49
你好,为什么教程里都只有汇编语言没有C51呢

作者: 朗朗繁星    时间: 2013-7-19 23:00
赞一个
作者: 不加糖的咖啡    时间: 2013-8-1 17:06
太厉害了
作者: 宝物沉海    时间: 2013-8-14 06:46
void main前面的程序怎么用。可以解释下吗
作者: czxsyqh    时间: 2013-8-15 14:55
很好,学习了
作者: →_→    时间: 2013-8-23 14:23
真好,学习中
作者: c2y3h2    时间: 2013-8-31 09:20
谢谢分享!!!!!
作者: 天做岸    时间: 2013-8-31 09:31
羡慕中
作者: ouyang1990    时间: 2013-9-20 16:19
慢慢看。。。。
作者: 飒露紫    时间: 2013-10-21 22:21
感谢楼主分享
作者: su31376299    时间: 2013-10-22 17:22
汇编真心不懂,太深奥!!!
作者: 温xyz    时间: 2013-11-10 21:31
很好!!讲解相当的好!!
作者: hantp    时间: 2013-11-23 09:06
C语言一定要学的。
作者: mountlion    时间: 2014-1-5 22:20
图中R2支路的作用是?
作者: zxc107105    时间: 2014-1-11 19:52
1.现在大家普遍学习的是c,下次可以把c放前面?
2.在程序讲解完附加一个实例?  帮助理解,没有例子,比较不好串联
作者: 872350646    时间: 2014-3-29 10:30
受教了
作者: yixiaow810c    时间: 2014-4-1 15:44
好帖,赞一个!!
作者: lixichunedu    时间: 2014-4-5 11:33
楼主,我想请教。如何记忆汇编指令的关键词呢?是不是
DJNZ (decrease jump no zero) 减1不为0跳转 。
作者: ivmmcu    时间: 2014-4-18 11:07
学习了,thanks
作者: 凯凯凯    时间: 2014-5-2 09:41
通俗易懂
作者: a1850976305    时间: 2014-5-13 15:24
我在学习中,嘿嘿
作者: 马明杰    时间: 2014-5-20 17:02
看不懂程序,是汇编吗
作者: 马明杰    时间: 2014-5-20 17:06
没看到最后,我错了
作者: bai926117    时间: 2014-5-28 17:29
赞一下
作者: yq11999    时间: 2014-5-29 21:08
汇编的语法有没有更详细的解释的?那些代码有没有什么书解说的!!
作者: laotouzi    时间: 2014-7-21 16:32
谢谢分享
作者: 亭子    时间: 2014-7-22 08:41
好帖子,感谢楼主分享
作者: impel    时间: 2014-7-29 20:00
很不错!
作者: 麟01    时间: 2014-8-6 23:19
#include <at89x52.h>
void DELAY()   //延时函数
{ unsigned char i,j;
    for(i=0;i<250;i++)
    {
        for(j=0;j<200;j++);
    }
}
void main() //程序从这里开始执行
{
while(1) //这句的作用就是反复的执行下面这个{}中包含的4句
    {
     P1_0=1;  //(1)熄灭灯
     DELAY(); //(2)延时一段时间
     P1_0=0;  //(3)点亮灯
     DELAY(); //(4)延时一段时间
    }
}
什么意思
作者: 浅墨画青梅    时间: 2014-8-29 14:16
很好!汇编和C一起教!
作者: yingtn    时间: 2014-9-11 15:29
那兩個FOR循環是否可以不用寫?
作者: 菜鸟009    时间: 2014-10-16 20:41
赞一个,但是汇编还没学,只会c
作者: jinanyuanyue    时间: 2014-10-19 09:17
曾经学过pic单片机,遗憾的是没有坚持,现如今打算学习51单片机,这么好机会我应把晤好,先学C语言再汇编语言,坚持就是胜利!
作者: zxj366    时间: 2014-10-19 20:18
讲的挺好的
作者: lijian790    时间: 2014-10-31 18:36
超赞!
作者: 小白two    时间: 2014-10-31 21:52
写的不错,受教了
作者: 小白two    时间: 2014-10-31 21:53
还得学汇编啊~~
作者: lwl051324    时间: 2014-11-23 11:46
很基础,很容易懂
作者: qiulin    时间: 2014-11-24 18:42
很好,通俗易懂
作者: qiulin    时间: 2014-11-24 18:42
还不错
作者: 玩知    时间: 2014-11-24 22:13
学习了!
作者: 嘟嘟1    时间: 2014-11-26 10:36
值得学习


作者: 嘟嘟1    时间: 2014-11-26 10:41

作者: 嘟嘟1    时间: 2014-11-26 10:41

作者: xiehui111    时间: 2014-11-26 13:38
非常感谢
作者: xiehui111    时间: 2014-11-26 13:39
谢谢老手,,,,
作者: xiehui111    时间: 2014-11-26 13:47
不错不错吧咱
作者: xiehui111    时间: 2014-11-26 13:47
支持老师,多多学习
作者: 最佳反馈    时间: 2014-11-29 19:12
赞~\(≧▽≦)/~。。
作者: 淘淘    时间: 2014-12-3 23:01
好啊好

作者: mrp123    时间: 2014-12-4 13:18
很好,学习了
作者: Horizon    时间: 2014-12-9 21:24
很不错,简单易懂
作者: shuai8748    时间: 2014-12-12 15:48
感谢楼主分享。
作者: 菜鸟一个666    时间: 2014-12-16 09:33
汇编和C语言各有各的好处
作者: yjj2011    时间: 2014-12-16 09:42
受益啦
作者: ardu    时间: 2014-12-16 12:18
学习了
作者: pps111    时间: 2014-12-20 12:17
哎啊~我想中奖
作者: pps111    时间: 2014-12-20 12:18
话中了。谢谢咯
作者: pps111    时间: 2014-12-20 12:18
学习中。感谢你的付出
作者: pps111    时间: 2014-12-20 12:20
貌似有点难学哦
作者: pps111    时间: 2014-12-20 12:20
我一定会慢慢学的
作者: pps111    时间: 2014-12-20 12:20
谢谢了
作者: pps111    时间: 2014-12-20 12:24
贪心的我又想奖励
作者: pps111    时间: 2014-12-20 12:24
给点奖励吧
作者: pps111    时间: 2014-12-20 12:25
原来够了
作者: hwy19861102    时间: 2014-12-22 10:36
新手报到,以后还希望各位大神多多指教。。
作者: fuwu785156    时间: 2014-12-22 14:27
太好了,试一试。
作者: jiadong    时间: 2014-12-23 19:09
好资料,谢谢分享
作者: lidongshan    时间: 2015-1-1 04:07
好,有意思,入门了。

作者: lxl2255    时间: 2015-1-4 09:59
#感觉好易懂在这里快速回复#
作者: lxl2255    时间: 2015-1-4 10:00
感觉好易懂易懂
作者: kcsj    时间: 2015-1-4 22:38
缺币啊缺币,看看拿走了                  
作者: kcsj    时间: 2015-1-4 22:38
缺币啊缺币,看看拿走了                  
作者: lxl2255    时间: 2015-1-7 13:33
详细的资料,谢谢
作者: 我就要飞刀    时间: 2015-1-20 08:45
本帖最后由 我就要飞刀 于 2015-1-20 08:49 编辑

刚才试了一下,第一个程序可以生成HEX文件,第二个不行,在proteus中编译和用keil编译都出错了。我是初学者,大家别笑话。
作者: 我就要飞刀    时间: 2015-1-20 09:01
哈哈,原来是我弄错了,原来还要再加一个.c
作者: 无名之魂love    时间: 2015-1-31 18:46
好。。。。。。。。。。
作者: kaka3511    时间: 2015-2-7 17:48
真的是很不错呢
作者: kaka3511    时间: 2015-2-7 17:48
真的是很不错呢
作者: kaka3511    时间: 2015-2-7 17:48
真的是很不错呢
作者: kaka3511    时间: 2015-2-7 17:49
楼主威武,永远带我们,哈哈
作者: kaka3511    时间: 2015-2-7 17:49
喜欢楼主,嘎嘎
作者: kaka3511    时间: 2015-2-7 17:50
楼主万岁,单片机感觉有点意思了,真的感谢楼主
作者: kaka3511    时间: 2015-2-7 17:50
楼主是活雷锋,大家说是不是
作者: kaka3511    时间: 2015-2-7 17:51
yq11999 发表于 2014-5-29 21:08
汇编的语法有没有更详细的解释的?那些代码有没有什么书解说的!!

找下汇编的指令很简单的,自己积累一点,不懂的再查
作者: kaka3511    时间: 2015-2-7 17:52
来到这个论坛,真心感觉很幸运呢
作者: kaka3511    时间: 2015-2-7 17:52
信不信我一直压马路压下去?O(∩_∩)O~
作者: kaka3511    时间: 2015-2-7 17:53
单片机我要学透就靠这个论坛了,顶起
作者: kaka3511    时间: 2015-2-7 17:53
信不信这次是10M币,我信了
作者: kaka3511    时间: 2015-2-7 17:53
10M币,我就不信你不出来!!!!
作者: kaka3511    时间: 2015-2-7 17:54
阿门,我要一直回下去
作者: kaka3511    时间: 2015-2-7 17:54
这确是极好的




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1