单片机执行程序的过程,侧重硬件过程(一)(组图)

单片机执行程序的过程,重点是硬件过程

为了加深初学者对51条单片机指令的理解,现将指令执行的过程在这里详细讲解,希望对大家有所启发!单片机执行程序的过程,其实就是执行我们编译好的程序的过程。即,一个指令一个指令的过程。计算机每执行一条指令,可分为三个阶段。即取指令—–分析指令—–执行指令。取指令的任务是根据程序计数器 PC 中的值从程序存储器中读取当前指令,并将其发送到指令寄存器。分析指令阶段的任务是:取出指令寄存器中的指令操作码,对其进行解码,分析其指令性质。

计算机执行程序的过程,其实就是一个一个地重复上面的操作过程,直到遇到停止命令程序计数器是到哪里去指,可以循环等待命令。普通计算机工作时,程序和数据首先通过输入接口电路,通过外部设备通过数据总线送到内存中,然后被取出执行。但单片机中的程序一般是通过烧写器预先固化在片上或片外的程序存储器中。因此程序计数器是到哪里去指,命令一开机就可以执行。下面我们举一个例子来说明指令的执行过程:当电脑开机时,程序计算器PC变为0000H。然后单片机在时序电路的作用下自动进入执行程序的过程。执行过程实际上是一个取指令(取内存中预存的指令)和执行指令(分析并执行指令)的循环过程。例如,执行指令:MOV A,#0E0H,其机器码为“74H E0H”,该指令的作用是将操作数E0H送入累加器,74H已存入0000H单元,E0H已存入累加器。存储在 0001H 单元中。当单片机开始运行时,首先进入取指令阶段,时序如下:执行过程实际上是一个取指令(取内存中预存的指令)和执行指令(分析并执行指令)的循环过程。例如,执行指令:MOV A,#0E0H,其机器码为“74H E0H”,该指令的作用是将操作数E0H送入累加器,74H已存入0000H单元,E0H已存入累加器。存储在 0001H 单元中。当单片机开始运行时,首先进入取指令阶段,时序如下:执行过程实际上是一个取指令(取内存中预存的指令)和执行指令(分析并执行指令)的循环过程。例如,执行指令:MOV A,#0E0H,其机器码为“74H E0H”,该指令的作用是将操作数E0H送入累加器,74H已存入0000H单元,E0H已存入累加器。存储在 0001H 单元中。当单片机开始运行时,首先进入取指令阶段,时序如下:74H 已存储在 0000H 单元中,E0H 已存储在 0001H 单元中。当单片机开始运行时,首先进入取指令阶段,时序如下:74H 已存储在 0000H 单元中,E0H 已存储在 0001H 单元中。当单片机开始运行时,首先进入取指令阶段,时序如下:

1. 将程序计数器(此时为0000H)的内容发送到地址寄存器;2. 程序计数器的内容自动加1(到0001H);3.地址寄存器(0000H)的内容,通过内部地址总线发送到内存,与内存中的地址解码,从而选择地址为0000H的单元;4. CPU使能读控制线;5. 在读命令的控制下选择内存单元的内容(此时应该是74H)发送到内部数据总线。因为是取指令阶段,所以内容通过数据总线发送到指令寄存器。至此,取指令阶段完成,进入解码分析和指令执行阶段。

由于本次输入指令寄存器的内容是74H(操作码),用译码器译码后,单片机就知道该指令是向A累加器发送一个数字,该数字就是代码中的下一个代码。存储单元。因此,要执行指令,必须从内存中取出数据(E0H)到CPU,即必须从内存中取出第二个字节。

该过程与fetch阶段非常相似,只是此时PC已经是0001H。指令译码器结合时序成分产生74H操作码的一系列微操作,从而从0001H单元中取出数字E0H。因为指令需要将取数送入A累加器,所以取数通过内部数据总线进入A累加器,而不是进入指令寄存器。至此,一条指令的执行完成。

单片机PC=“0002H”,CPU每次从内存中取指令或数时,PC自动加1,单片机进入下一个取指令阶段。重复此过程,直到接收到暂停命令或暂停循环等待命令。这就是CPU如何一一执行指令来完成所有指定的功能。

51单片机程序执行流程详解

单片机没有操作系统。keil写的代码是裸机代码,也就是你写的代码类似于操作系统。深入编写裸机代码有助于了解硬件的特性。

如果不是硬件特性已经确定的情况,其他流程都是代码问题。突然想到探探51单片机的执行过程。这个想法源于我一开始在每个51程序的main函数中看到了一个while(1);语句。为什么要加一个while无限循环让程序停留在main函数中。把while(< @1);去掉语句有什么效果?

写一个很简单的程序试试。

图片[1]-单片机执行程序的过程,侧重硬件过程(一)(组图)-老王博客

执行上述程序后,P1口控制的水灯闪烁。程序终于进入了while(1);的纠缠,这很好解释。

现在阻塞while(1);语句。我还以为程序不能正确执行,因为主main函数退出了,就像Render需要循环来实现一样(虽然刚才闪灯的程序不是在循环中)。里面,但我还是忍不住有这种错觉。)程序执行的结果是:流水灯一直闪烁!

看到这种现象后的猜测和行动^-^:

(1)这个板子坏了!(在linux字符界面等操作系统下运行无死循环的C语言文件后,会返回linux shell程序)。快换板子再测试再次,显然还是同样的结果。

(2) MCU会一直执行main函数中的最后一条语句?(基于在OS平台下运行标准C语言文件的经验,没想到main函数被多次调用或者进入次数)

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

(4)赶紧谷歌百度一下单片机的执行过程(虽然我在谷歌百度搜索“51单片机程序执行过程”,没有找到相关内容)。改简单搜索词:“51微控制器main”。然后有一个和我一样疑惑的问题:为什么程序在while(1);语句后没有加到main函数中重复执行?答案中的关键词包括“the程序跑掉,看门狗,重置”。

(5)趁着嵌入式的机会,拿出了《51单片机程序执行过程》,把我写的程序的现象告诉了老师,包括我是怎么验证的等等。

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

然后我用keil软件模拟运行了上面的代码:

图片[2]-单片机执行程序的过程,侧重硬件过程(一)(组图)-老王博客

图片[3]-单片机执行程序的过程,侧重硬件过程(一)(组图)-老王博客

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

图片[4]-单片机执行程序的过程,侧重硬件过程(一)(组图)-老王博客

继续单击单步,直到进入循环:

图片[5]-单片机执行程序的过程,侧重硬件过程(一)(组图)-老王博客

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

图片[6]-单片机执行程序的过程,侧重硬件过程(一)(组图)-老王博客

可以看出r0的初始值为0x7f。这里我们会循环0x7f(128)次。r0的值的含义可以马上查出来。那么这个循环之后程序会去哪里呢?跳过这个循环post程序运行如下:

图片[7]-单片机执行程序的过程,侧重硬件过程(一)(组图)-老王博客

再次进入它:

图片[8]-单片机执行程序的过程,侧重硬件过程(一)(组图)-老王博客

根据Disassembly的内容,这条语句执行完后,会再次回到main函数。试试看:

图片[9]-单片机执行程序的过程,侧重硬件过程(一)(组图)-老王博客

是的!

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

为什么我们在linux等不死循环的情况下运行C语言代码后程序会自行终止。这是不同的运行过程:

(1)C51单片机没有OS(操作系统),代码的执行情况由STARTUP.A51从这个角度来安排,没有更大的程序来管理如何调用主函数。

(2)Linux之类的平台自带操作系统。运行C语言程序是Linux的任务。除了运行C语言程序的任务之外,还有其他任务。当运行C语言程序时,程序完成时,这个任务也就完成了,比如运行一个文件名为“hello.c”的C语言程序,其功能是在linux shell界面中输出“hello world!”,过程如下:

编译:gcc hello.c –o hello

运行:./你好

运行hello可执行文件时,可以认为是shell调用了hello可执行程序。hello运行完成后,将返回值等返回给shell接口。整个 C 语言文件的生死由 Linux shell 程序管理。

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论