您的位置 首页 电子技术

编写一个简单的C51程序

对于嵌入式系统,如果没有运行RTOS,那么程序开发中的 主函数(main())需要通过某种机制使其永远愉快的运行下去,它没有终点。如果想从main函数中退出,具体干什么是由所使用的C语言编译器决定的。\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

简 介: 对于嵌入式系统,如果没有运行RTOS,那么程序开发中的 主函数(main())需要通过某种机制使其永远愉快的运行下去,它没有终点。如果想从main函数中退出,具体干什么是由所使用的C语言编译器决定的。

01 问题提出

今天在CSDN的 单片机led模块定义函数的问题[1] 中看到一个有趣的问题。提问者在进行基本的C51编程实验,编写了一个简单的C51程序如下:

#includevoidtest(num){switch(num){case1:P2_0=0;P2_1=0;break;}}voidmain(void){test(1);}

  程序执行完之后,可以看到实验板上的有两个LED被点亮,另外六个居然微微发亮。

  如果在主程序中,增加一个无限循环:while(1); ,则电路板上的就不再会出现“微微点亮”的现象了。

#includevoidtest(num){switch(num){case1:P2_0=0;P2_1=0;break;}}voidmain(void){test(1);while(1);}

  上面两种情况的区别,在于第二个程序中 主循环 main() 函数始终没有退出,而第一个程序,main() 函数退出了。似乎前面LED 微微点亮 应该与 主函数 退出之后,单片机都干了些啥有关系。

那么就剩下一个问题:对于普通的嵌入式系统,C语言编程中 main()函数退出之后,程序去哪儿了?

02 程序去哪儿了?

从上面提问者书写的代码来看,应该是一位C51的爱好者,使用的是C51的编译器,在一款C51开发板上愉快的进行实验。他一开始没有安装嵌入式程序开发的惯例在主程序void main(void) 中利用无限循环将程序控制在主程序函数中,就出现了前面实验结果中令人迷惑的情况。 注:他是一个胆大心细的人,观察还挺仔细的。

2.1 盘古开天辟地

  对于C语言编程来说,所有的用户程序世界是从主程序 main() 开始的。给用户程序开天辟地的任务是由 一小段 盘古代码 STARTUP.A51

  关于C51是如何启动的, 在如下面博文中也被测试说明:

51单片机程序执行流程(STARTUP.A51管理Main函数的执行)

  下面截取了 STARTUP.A51 代码的一段,可以看到盘古在单片机 RESET 之后做了点准备工作(初始化全局变量、堆栈指针)之后,就直接跳转至:?C_START

NAME?C_STARTUP?C_C51STARTUPSEGMENTCODE?STACKSEGMENTIDATARSEG?STACKDS1EXTRNCODE(?C_START)PUBLIC?C_STARTUPCSEGAT0?C_STARTUP:LJMPSTARTUP1RSEG?C_C51STARTUPSTARTUP1:IFIDATALEN0MOVR0,#IDATALEN-1CLRAIDATALOOP:MOV@R0,ADJNZR0,IDATALOOPENDIFIFXDATALEN0MOVDPTR,#XDATASTARTMOVR7,#LOW(XDATALEN)IF(LOW(XDATALEN))0MOVR6,#(HIGH(XDATALEN))+1ELSEMOVR6,#HIGH(XDATALEN)ENDIFCLRAXDATALOOP:MOVX@DPTR,AINCDPTRDJNZR7,XDATALOOPDJNZR6,XDATALOOPENDIFIFPPAGEENABLE0MOVPPAGE_SFR,#PPAGEENDIFIFPDATALEN0MOVR0,#LOW(PDATASTART)MOVR7,#LOW(PDATALEN)CLRAPDATALOOP:MOVX@R0,AINCR0DJNZR7,PDATALOOPENDIFIFIBPSTACK0EXTRNDATA(?C_IBP)MOV?C_IBP,#LOWIBPSTACKTOPENDIFIFXBPSTACK0EXTRNDATA(?C_XBP)MOV?C_XBP,#HIGHXBPSTACKTOPMOV?C_XBP+1,#LOWXBPSTACKTOPENDIFIFPBPSTACK0EXTRNDATA(?C_PBP)MOV?C_PBP,#LOWPBPSTACKTOPENDIFMOVSP,#?STACK-1LJMP?C_STARTEND

  上面的代码也被博文 51单片机程序执行流程(STARTUP.A51)中进行逐步调试跟踪验证过:

http://news.vvfanli.com/wp-content/uploads/2022/03/20220313063435-622d907b515c8.jpg▲ 图2.1.1 显示LJMP C_START 就是进入 main() 程序2.2 世界尽头

  由于进入main() 函数是长跳转,所以main函数是不会正常返回到启动程序 STARTUP.A51,那么程序去哪了?

  在博文 单片机C语言while(1)的问题 中作者对于 KEIL编译器和PIC的 MAPLAB编译器对于main函数的最后时光进行了反汇编查看。

2.2.1 Keil编译器

  在main函数的最后,程序增加了一下几行代码:

MOVR0,#0x7FCLRAMOV@R0,ADJNZR0,(3)MOVSP,#0x0CLJMPmain

  这几条语句,前4条,是将我们单片机的内存的前128个地址清零,第5条,是定义堆栈,第6条,是将程序重新跳转到main函数的首行进行执行。

2.2.2 MAPLAB编译器

  PIC 单片机语言程序进行跟踪,发现main() 函数最后一条语句为 reset,也就是单片机直接复位,这是 MAPLAB编译器根据 PIC 单片机特点增加的复位语句。

总  结

对于嵌入式系统,如果没有运行RTOS,那么程序开发中的 主函数(main())需要通过某种机制使其永远愉快的运行下去,它没有终点。

如果想从main函数中退出,具体干什么是由所使用的C语言编译器决定的。

原文标题:程序结束后去哪儿了?

文章出处:【微信公众号:嵌入式ARM】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红

免责声明:文章内容不代表本站立场,本站不对其内容的真实性、完整性、准确性给予任何担保、暗示和承诺,仅供读者参考,文章版权归原作者所有。如本文内容影响到您的合法权益(内容、图片等),请及时联系本站,我们会及时删除处理。

作者: admin

为您推荐

智慧路灯照明系统的应用为智慧城市的发展建设添砖加瓦

智慧路灯照明系统的应用为智慧城市的发展建设添砖加瓦

智慧路灯照明系统的应用为智慧城市的发展建设添砖加瓦-夜间的路灯不仅照亮了黑暗的街道,而且照亮了回家的道路。从街上望去,闪烁的路灯发出暖光,指引着我们家的方向。城市里的路灯就像“守护者”,给长途旅行回来的游客带来了极大的安全感。 当今,路灯智能控制时代的到来,极大地促进了传统路灯的人工机械化运行。虽然对此感到兴奋,但我们不禁要问:随着路灯智能控制的早期到来,除了改善路灯的运行模式,还能带来什么? 为城市交通提供安全保障 城市公共照明系统中的智能路灯在每个路

晶振在五种不同行业中的应用说明

晶振在五种不同行业中的应用说明-晶振在五种不同行业的应用-由TST嘉硕代理KOYU光与电子

几种不同的物联网控制APP模式

本文就简单介绍当前几种物联网控制APP模式,让大家了解几种不同的技术路线。\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

苹果稳坐全球可穿戴设备数量首位,占据日本市场超7成份额

苹果稳坐全球可穿戴设备数量首位,占据日本市场超7成份额

苹果公司占据2021年日本第四季度可穿戴设备71.5%份额,占据全球可穿戴设备市场34.9%份额。\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

如何用GPUDirect存储器如何缓解CPU I / O瓶颈

除了使用 GPUs 而不是 CPU 加快计算的好处外,一旦整个数据处理管道转移到 GPU 执行,直接存储就起到了一个力倍增器的作用。这一点变得尤为重要,因为数据集大小不再适合系统内存,而且 GPUs 的数据 I / O 增长成为处理时间的瓶颈。当人工智能和数据科学继续重新定义可能的艺术时,启用直接路径可以减少甚至完全缓解这个瓶颈。\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注