找回密码
 注册
关于网站域名变更的通知
查看: 487|回复: 1
打印 上一主题 下一主题

51单片机程序执行流程详细分析

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-2-28 06:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
51单片机程序执行流程详细分析
$ L' p9 A; Q3 w: }; i4 B/ \2 ^( Y1 X

& D; d; ~) \& D! }- l% ]

单片机是没有上操作系统的东西,在keil中编写的代码都是裸机代码,深入编写裸机代码有助于了解硬件的特性。

' {7 k. i* n1 F5 c& Q' o

若不是硬件特性已定的情况之下的其它流程都是代码作祟。忽然想到来探探51单片机的执行流程。这个念头起源于最初见到每个51程序里面的主函数里面最终都挂一个while(1);语句。为何要加一句while死循环让程序停留在main函数中呢。将while(1);语句去掉有什么影响么?

) c* \" `* b7 p  s. }1 U) F# [

写一个很简单的程序试一下。; f& t! G: K3 {  Q$ ^
" T. M# E- }0 W7 l% g2 \
执行以上程序,由P1端口控制的流水灯闪了一下。程序最终进入while(1);里纠缠去了,这个到好解释。

* n: s. ?* q* ]! r" A: ]2 N

现将while(1);语句屏蔽掉。我还以为程序不能被正确执行了呢,因为退出了main主函数,就像Render需要循环来实现一样(尽管刚刚闪灯的程序不在循环之内,但我还是不由产生了这一错觉)。程序执行的结果是:流水灯不停的闪烁!


' q2 k) c2 X, T7 n1 I4 O

看到这个现象后的猜想及动作^-^:


; c8 c% L3 [/ t

(1) 这块板坏了吧!(在带操作系统如linux字符界面下运行一个不带死循环的C语言文件完毕后就会返回到linux shell程序中)。赶紧换个板再测试一下,显然还是一样的结果。


0 z+ s. H) H5 P" Y8 R  A. S6 r

(2) 单片机中将一直执行main函数中的最后一个(些)语句?(基于带OS平台下运行标准C语言文件的经验,可从来没有想过是main函数被多次调用或多次进入)

0 R  J& N1 e0 A* k% K) P' ?

(3) 单片机内将C语言指令取出来加载到单片机内,单片机内自动生成一个主程序循环执行C语言中main函数的内容?(虽然很荒唐,还是想了)

/ ~$ G4 A% o2 {( k$ @# j& H% I

(4) 赶快谷歌百度一下单片机的执行流程(虽然在谷歌百度时以“51单片机程序执行流程”搜索,没有搜到相关内容)。换朴实的搜索词:“51单片机 main”。然后就出现跟我一样带有疑问的问题:为什么main函数中不加while(1);语句之后程序会反复执行呢?回答的关键词包括“程序跑飞、看门狗、复位”。

4 d8 q& q1 [2 o0 M, f' h

(5) 趁上嵌入式的机会将“51单片机程序执行流程”搬出来并向老师讲述了我所写程序的得到的现象,包括我怎么验证呀等等。


7 X  D  \, k, \2 G& G  L: g

老师的回答:Keil C51程序自动加载了一个名为”STARTUP.A51”的文件,在这个文件里面进行了一系列的初始化操作后进入用户编写的C语言程序入口main函数中,main函数执行完毕后,STARTUP.A51文件后有一句跳转到程序入口main函数的语句,所以会再次进入C语言主程序main函数中执行相关内容。

1 G- F$ _5 S, g5 j- Z5 y$ r0 m

然后我用keil软件模拟了运行一下以上那一段代码:

1 h9 m& v' o2 E( Q

程序开始运行就在程序入口main函数的第一条语句之处,Disassembly窗口是c语言代码与汇编代码相对应的窗口,前面是地址,后面的是C语言对应的汇编语句。下面的窗口是相应文件的运行代码的位置,由黄色箭头指向当前正要执行的代码。然后点击单步运行工具条,指导跳出main函数为止,程序跳转到STARTUP.A51中的以下代码位置:


( H' p8 g3 K% G. n# O4 i$ E* z  V

继续点击单步调试直到进入一个循环中:

$ s3 j+ h3 A/ j2 u: Z

这里是一个循环,根据DJNZ指令的功能:每执行一次DJNZ RO, IDATALOOP就将R0的值减1,若R0的值不为0则就跳到IDATALOOP地址去。很显然这是一个循环,那么RO的值是多少呢,在以下窗口显示:


' D! ?! V: H9 ]4 V/ G8 B! Y

可见r0的初值为0x7f,这里将要循环0x7f(128)次,具体在这里r0值的含义可查看一下子的。那么在这个循环之后程序又将去哪里呢?跳过这个循环后程序运行的地方如下:0 h- @1 p, }( I- ]6 R& e

. J1 N- J% A7 d. |

再单步运行一次:
# V) ?' h# |6 D0 b) h


' g; W- w" }5 U0 T- T

根据Disassembly的内容,此条语句执行了就又要回到main函数中去了,执行一下试试:! c- f' ]7 b6 H" b% _$ x

  B  d# p) q" m' d/ I& V

是的!


5 }9 D9 l! U2 p: @

所以,在51单片机中,程序的执行流程就是会不断( 以r0的值作为延迟条件, 具体含义可继续探索 )的进入main函数中执行main函数中的代码。

% x  ?: m0 l3 ?, M- W" H4 }

为什么我们在linux等上面运行不带死循环的C语言代码后程序就会自行终止呢?这是不同的操作流程:

% \; m1 g' I- f/ U# `$ {" a9 \

(1) C51单片机不带OS(操作系统),代码的执行形势在此看来就由STARTUP.A51来安排了,没有一个更大的程序来管理怎么调用main函数。


0 T/ s4 N' I5 U4 n

(2) 像Linux这类的平台是带了OS的,运行一个C语言程序对linux来说就是一个任务,除了运行C语言程序这个任务外还有其它的任务。当运行一个C语言程序完毕时,此次的任务也算是完成了。如在linux shell界面运行一个文件名为“hello.c”功能为输出“hello world!”的C语言程序,过程如下:

3 O. j  v( Y3 Y

编译:gcc hello.c –o hello


( D+ g. s% |$ r7 r, f! g( |" k# y$ m

运行:./hello


" p8 w) R) o9 T, r

在运行hello可执行文件时,可以当做是shell调用了hello这个可执行程序。在hello运行完毕后,将返回值等返回给shell界面。整个C语言文件的生死全有linux shell程序管理。

, u! K, W, g$ D* m8 i: H9 `9 R

归其原因,还是代码规定的机制不一样吧。


, s: G  V  U) Q6 }- e

该用户从未签到

2#
发表于 2019-2-28 18:03 | 只看该作者
好东东,学习一下,谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-18 06:22 , Processed in 0.109375 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表