0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

单片机的程序结束后都干嘛去了?

jf_pJlTbmA9 来源:TsinghuaJoking公众号 作者:TsinghuaJoking公众号 2023-10-17 17:16 次阅读

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

一、问题提出

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

#include 

void test(num) {
    switch(num) {
        case 1: P2_0=0; P2_1=0; 
            break;
    }
}

void main(void) {
    test(1);
}

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

wKgaomUD3cCAN5uTAA1RmE0XHgg376.png

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

#include 

void test(num) {
    switch(num) {
        case 1: P2_0=0; P2_1=0; 
            break;
    }
}

void main(void) {
    test(1);
    while(1);
}

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

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

二、程序去哪儿了?

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

“注:他是一个胆大心细的人,观察还挺仔细的。”

2.1 盘古开天辟地

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

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

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

NAME    ?C_STARTUP

?C_C51STARTUP   SEGMENT   CODE
?STACK          SEGMENT   IDATA

                RSEG    ?STACK
                DS      1

                EXTRN CODE (?C_START)
                PUBLIC  ?C_STARTUP

                CSEG    AT      0
?C_STARTUP:     LJMP    STARTUP1

                RSEG    ?C_C51STARTUP

STARTUP1:

IF IDATALEN <> 0
                MOV     R0,#IDATALEN - 1
                CLR     A
IDATALOOP:      MOV     @R0,A
                DJNZ    R0,IDATALOOP
ENDIF

IF XDATALEN <> 0
                MOV     DPTR,#XDATASTART
                MOV     R7,#LOW (XDATALEN)
  IF (LOW (XDATALEN)) <> 0
                MOV     R6,#(HIGH (XDATALEN)) +1
  ELSE
                MOV     R6,#HIGH (XDATALEN)
  ENDIF
                CLR     A
XDATALOOP:      MOVX    @DPTR,A
                INC     DPTR
                DJNZ    R7,XDATALOOP
                DJNZ    R6,XDATALOOP
ENDIF

IF PPAGEENABLE <> 0
                MOV     PPAGE_SFR,#PPAGE
ENDIF

IF PDATALEN <> 0
                MOV     R0,#LOW (PDATASTART)
                MOV     R7,#LOW (PDATALEN)
                CLR     A
PDATALOOP:      MOVX    @R0,A
                INC     R0
                DJNZ    R7,PDATALOOP
ENDIF

IF IBPSTACK <> 0
EXTRN DATA (?C_IBP)

                MOV     ?C_IBP,#LOW IBPSTACKTOP
ENDIF

IF XBPSTACK <> 0
EXTRN DATA (?C_XBP)

                MOV     ?C_XBP,#HIGH XBPSTACKTOP
                MOV     ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF

IF PBPSTACK <> 0
EXTRN DATA (?C_PBP)
                MOV     ?C_PBP,#LOW PBPSTACKTOP
ENDIF

                MOV     SP,#?STACK-1
                LJMP    ?C_START

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

wKgaomUD3caAYpp7AAG4gK1aF2U913.png

2.2 世界尽头

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

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

Keil编译器

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

MOV R0, #0x7F
CLR A
MOV @R0, A
DJNZ R0, (3)
MOV SP, #0x0C
LJMP main
这几条语句,前4条,是将我们单片机的内存的前128个地址清零,第5条,是定义堆栈,第6条,是将程序重新跳转到main函数的首行进行执行。

MAPLAB编译器

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

总结

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

来源:TsinghuaJoking公众号
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6001

    文章

    43978

    浏览量

    620871
  • 编译器
    +关注

    关注

    1

    文章

    1577

    浏览量

    48625
  • maplab
    +关注

    关注

    0

    文章

    3

    浏览量

    1242
收藏 人收藏

    评论

    相关推荐

    ADuC7039单片机进入休眠JTAG无法下载程序怎么解决?

    ADuC7039单片机测试休眠功能,单片机进入休眠,JTAG丢失与单片机链接,这是正常现象,但JTAG再无法下载,重启复位单片机和JTAG
    发表于 01-11 07:14

    单片机芯片怎么写入程序

    单片机芯片的程序写入是通过将程序代码写入单片机芯片的非易失性存储器(如Flash)中实现的。 在计算机科学和电子工程领域,单片机是一种集成电
    的头像 发表于 01-05 14:06 2763次阅读

    51单片机for循环结束之后还在运行

    当我们设计并编写嵌入式系统时,使用51单片机编写程序时,常常会用到循环结构来重复执行一段代码。然而,有时我们可能会遇到51单片机在循环结束之后还在运行的问题,这可能会导致系统的功能异常
    的头像 发表于 12-26 14:06 338次阅读

    单片机485通讯断线问题

    大家好请教,单片机485通讯断线,再接上单片机就不能通信了,需重启才能通信,485模块是自动收发的,程序设计是定时循环通信
    发表于 12-19 11:13

    单片机boot脚干嘛

    单片机boot脚是单片机的引导脚,用于控制单片机的启动和引导过程。在单片机系统中,boot脚的作用十分重要,它影响着整个单片机的工作状态和功
    的头像 发表于 12-19 09:47 2820次阅读

    怎么读取单片机程序

    怎么读取单片机程序
    发表于 11-01 06:21

    系统复位单片机从哪个单元开始取指令执行程序

    大佬帮忙解答下,系统复位单片机从哪个单元开始取指令执行程序
    发表于 10-31 07:10

    单片机下载程序程序下载进去串口就无法下载程序了是为什么?

    问一下有没有遇到过给单片机下载程序程序下载进去串口就无法下载程序了,必须下电一会儿,然后上电第一次能够下载,如果不下载其他
    发表于 10-27 06:00

    单片机main函数结束干嘛去了

    单片机main函数结束干嘛去了
    的头像 发表于 10-18 17:37 396次阅读
    <b class='flag-5'>单片机</b>main函数<b class='flag-5'>结束</b><b class='flag-5'>干嘛</b><b class='flag-5'>去了</b>?

    请问51单片机中的看门狗是干嘛的?

    51单片机中的看门狗是干嘛的?
    发表于 10-08 06:06

    TFT LCD电阻显示屏幕插入单片机程序烧入失败?

    TFTLCD电阻显示屏幕插入单片机程序烧入失败
    发表于 09-26 07:39

    51单片机烧写程序的方法

    STC89C51是应用广泛的51单片机,很多人都是通过该单片机入门学习的,单片机的学习需要勤动手。单片机需要烧写程序,要用到相关的软件和硬件
    的头像 发表于 09-11 10:10 3609次阅读
    51<b class='flag-5'>单片机</b>烧写<b class='flag-5'>程序</b>的方法

    ML51单片机INT1将单片机从掉电模式唤醒定时器工作不正常怎么解决?

    在ML51TC0AE试验板和NuMaker-ML51PC开发板上试验,新唐ML51单片机INT1将单片机从掉电模式唤醒定时器工作不正常。定时器是在唤醒才初始化的,唤醒
    发表于 06-14 09:14

    结束-【书籍评测活动NO.14】 Proteus实战攻略:从简单电路到单片机电路的仿真

    、循迹避障小车电路和花卉养护装置电路使读者了解多路 PWM应用、单片机间相互通信、可视化编程及上位与下位通信等知识。每个实例按照总体要求、硬件电路设计、
    发表于 06-01 14:09

    单片机学了以后可以干嘛

    学习单片机后,你可以进行许多有趣和实用的项目和应用。单片机是嵌入式系统的核心,具有丰富的外设和功能模块,以下是一些你可以利用单片机实现的应用。
    的头像 发表于 05-26 14:40 1753次阅读