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

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

3天内不再提示

单片机led模块定义函数的问题

GReq_mcu168 来源:CSDN 作者:CSDN 2022-03-11 10:10 次阅读

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

01问题提出

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

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

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

25a78be2-8f01-11ec-952b-dac502259ad0.png

▲ 图1.1 实验板上的未点亮的LED居然微微发亮

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

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

25c67dcc-8f01-11ec-952b-dac502259ad0.png

▲ 图1.2 实验板上后面六个LED就不再点亮了

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

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

02程序去哪儿了?

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

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

2.1 盘古开天辟地

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

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

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

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

NAME?C_STARTUP ?C_C51STARTUPSEGMENTCODE ?STACKSEGMENTIDATA RSEG?STACK DS1 EXTRNCODE(?C_START) PUBLIC?C_STARTUP CSEGAT0 ?C_STARTUP:LJMPSTARTUP1 RSEG?C_C51STARTUP STARTUP1: IFIDATALEN<>0 MOVR0,#IDATALEN-1 CLRA IDATALOOP:MOV@R0,A DJNZR0,IDATALOOP ENDIF IFXDATALEN<>0 MOVDPTR,#XDATASTART MOVR7,#LOW(XDATALEN) IF(LOW(XDATALEN))<>0 MOVR6,#(HIGH(XDATALEN))+1 ELSE MOVR6,#HIGH(XDATALEN) ENDIF CLRA XDATALOOP:MOVX@DPTR,A INCDPTR DJNZR7,XDATALOOP DJNZR6,XDATALOOP ENDIF IFPPAGEENABLE<>0 MOVPPAGE_SFR,#PPAGE ENDIF IFPDATALEN<>0 MOVR0,#LOW(PDATASTART) MOVR7,#LOW(PDATALEN) CLRA PDATALOOP:MOVX@R0,A INCR0 DJNZR7,PDATALOOP ENDIF IFIBPSTACK<>0 EXTRNDATA(?C_IBP) MOV?C_IBP,#LOWIBPSTACKTOP ENDIF IFXBPSTACK<>0 EXTRNDATA(?C_XBP) MOV?C_XBP,#HIGHXBPSTACKTOP MOV?C_XBP+1,#LOWXBPSTACKTOP ENDIF IFPBPSTACK<>0 EXTRNDATA(?C_PBP) MOV?C_PBP,#LOWPBPSTACKTOP ENDIF MOVSP,#?STACK-1 LJMP?C_START END

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

25e5150c-8f01-11ec-952b-dac502259ad0.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,#0x7F CLRA MOV@R0,A DJNZR0,(3) MOVSP,#0x0C LJMPmain

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

2.2.2 MAPLAB编译器

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

※总  结 ※

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

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

审核编辑 :李倩

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

    关注

    40

    文章

    3427

    浏览量

    128210
  • C51
    C51
    +关注

    关注

    5

    文章

    279

    浏览量

    57641

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

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    51单片机-LED模块

    LED模块是通过74573锁存器芯片与单片机IO口连接,并与数码管共用IO口。
    的头像 发表于 05-23 09:14 8432次阅读
    51<b class='flag-5'>单片机</b>-<b class='flag-5'>LED</b>灯<b class='flag-5'>模块</b>

    单片机SFR定义的头文件盘点

    本源程序是每一个MCS-51系列单片机C语言程序的必备内容,包括程序开始处的说明信息、头文件、SFR定义、子函数、主函数和C语言常用的 5大语句(if,while,do while
    发表于 07-13 02:53

    单片机程序问题,我定义函数并且在主函数里使用了定义函数,但编译却说我没使用定义函数

    单片机keil编程的定义函数使用问题。如图有很多提醒说我定义函数但是没有用上,我举一个DS18B20的初始化
    发表于 04-28 19:03

    51单片机C语言延时函数怎么定义

    描述51单片机C语言延时函数怎么定义C语言定义延时函数主要通过无意义指令的执行来达到延时的目的。C程序中可使用不同类型的变量来进行延时设计。
    发表于 07-15 06:42

    51单片机的变量的位如何定义

    51单片机的变量的位如何定义,在单片机编程使用中,会涉及到将某些函数定义到指定的code区。此时需要对工程文件进行配置修改才可完成。本期针对
    发表于 07-19 09:02

    理解IO驱动,51单片机、STM32单片机、嵌入式Linux分别点亮LED灯 精选资料分享

    无论是学开发什么板子,接触的第一个程序一般都是点亮LED灯。下面分别从51单片机、STM32单片机(寄存器、库函数、RTOS)、嵌入式Linux五个方面解释,这里我们假设都是低电平点亮
    发表于 08-18 06:50

    单片机8051接一个LED闪烁的方法

    单片机8051接一个LED闪烁(2)题目:将8051的P0.1端口接一个LED,每隔大约10ms开关一次。1.仿真电路(软件为Proteus)2.程序(软件为keil)点亮#include//
    发表于 12-08 06:03

    基于AT32(STM32)单片机模块化代码分享

    基于AT32(STM32)单片机模块化代码之——Led代码模块化上个文章讲了按键的模块化代码,这个文章贴一下我写的
    发表于 12-13 07:34

    定义单片机寄存器操作和模块接口相关的函数

    :/* 定义单片机寄存器操作和模块接口相关的函数, 方便在不同平台间移植 */// 单片机: STM32F103VE,
    发表于 12-13 07:43

    单片机控制的LED灯、最小系统及八路流水灯

    1、 单片机控制一个LED灯的C语言程序范例 单片机控制一个LED灯的C语言程序范例1: //用单片机点亮1个
    发表于 09-06 10:37 23次下载

    51单片机C语言延时函数怎么定义和使用

    C语言定义延时函数主要通过无意义指令的执行来达到延时的目的。下面给出一个经典的延时函数。C程序中可使用不同类型的变量来进行延时设计。经实验测试,使用unsigned char类型具有
    发表于 11-16 17:06 8.3w次阅读

    51单片机STC89C52控制LED闪烁(将延时程序写成子函数有形参)

    头文件 /*-----------------------端口/引脚定义区域----------------------*/sbit LED=P2^0; //位定义P2.0引脚名为LED
    发表于 11-20 17:36 6次下载
    51<b class='flag-5'>单片机</b>STC89C52控制<b class='flag-5'>LED</b>闪烁(将延时程序写成子<b class='flag-5'>函数</b>有形参)

    51单片机 点亮一个LED LED闪烁

    (1) //循环 { }}使用51单片机点亮一个LED#include <reg52.h> //51单片机头文件sbit LED=P2^0;
    发表于 11-23 17:06 5次下载
    51<b class='flag-5'>单片机</b> 点亮一个<b class='flag-5'>LED</b> <b class='flag-5'>LED</b>闪烁

    C语言&单片机不定参数个数的函数定义

    在学习使用C语言的时候都会告知main函数是可以接入多个参数的,那么问题来了,不定参数个数的函数如何定义的呢,它是否可以在单片机中使用呢定义
    发表于 11-29 09:51 8次下载
    C语言&<b class='flag-5'>单片机</b>不定参数个数的<b class='flag-5'>函数</b><b class='flag-5'>定义</b>

    单片机led模块定义函数程序去哪了

    正常的程序,都不会跳出main,但是,如果跳出了 main 函数,程序到底去哪儿了,你有相关这个问题吗?
    的头像 发表于 08-25 10:42 699次阅读