返回首页

51单片机main循环(51单片机main函数)

来源:www.haichao.net  时间:2022-12-14 18:17   点击:282  编辑:admin   手机版

1. 51单片机main函数

单片机中主函数指的是main.函数

2. 51单片机main函数写什么

上电后程序指针PC就会从程序存储器的0地址开始执行,

中间会按照程序的要求跳到需要的地址执行,

如果执行到最后一条指令完而没有相应的跳转指令

PC会继续往存储器的下一地址执行,

而下一地址是没有烧写指令进去的(理论上是全1或全0,随厂家而定),这时就出现了跑飞,

在PC将所有地址都跑一遍之后会回到0地址,如此循环,

不过在main主函数里面最后加一句while(1);让函数进入死循环,可解决此问题。

3. 单片机MAIN

首先51单片机编程大部分都是基于c语言进行编程的,也有基于汇编语言的。任何语言在开始执行的时候都会有一个入口主函数,一般main函数就担任这个角色。进入main函数以后就开始各种调度然后进行执行。

4. 51单片机常用函数

大部分都是函数来实现功能的,有库函数和自定义函数,不过在单片机中,大部分是使用的自定义函数。 比如:void delay()函数,void main()主函数等,这些都是函数的。

5. 51单片机的程序中有几个主函数

要生成各个C文件的头文件,然后再主函数里加入这个.h的文件就好了

6. 51单片机main函数如何调用多个子函数

在c语言中,全局变量和函数声明及定义并列,也就是说,声明在最外层作用域的变量即为全局变

如在如下程序中

int i;

int main()

{

int i_copy = i;

i = 9;

return 0;

}

int

i就是一个全局变量,故在main函数中可以调用或修改i的值

所以,定义数组也和普通全局变量的方法相同,如

char str[10];

int main()

{

str[0] = 'a';

str[1] = '\0';

return 0;

}

拓展资料

c语言是一门通用计算机编程语言,应用广泛。c语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

尽管c语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的c语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称mcu)以及超级电脑等作业平台。

二十世纪八十年代,为了避免各开发厂商用的c语言语法产生差异,由美国国家标准局为c语言制定了一套完整的美国国家标准语法,称为ansi

c,作为c语言最初的标准。目前2011年12月8日,国际标准化组织(iso)和国际电工委员会(iec)发布的c11标准是c语言的第三个官方标准,也是c语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。

7. 51单片机main函数入口地址

单片机在执行程序的时候都是从main函数开始的,而且每个程序有且只有一个main函数,一上电就开始运行程序需执行的内容。

8. 单片机main指令

仿照RT-Thread的自动初始化机制,写了一个自动初始化的模块,整个代码仅52字节。

好处:可以实现自动初始化,不用在外部显式地调用。

缺点:初始化逻辑较显式调用的方式模糊,容易引入BUG。

以下是对应的头文件和源文件,初始化顺序分为9级,LOADER_BOARD_EARLY_EXPORT最早,LOADER_APP_LATE_EXPORT最迟。使用方法可以看最后面的Demo。

#ifndef _LOADER__H

#define _LOADER__H

#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */

#define LOADER_USED __attribute__((used))

#define SECTION(x) __attribute__((section(x)))

#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */

#define LOADER_USED __root

#define SECTION(x) @ x

#elif defined (__GNUC__) /* GNU GCC Compiler */

#define LOADER_USED __attribute__((used))

#define SECTION(x) __attribute__((section(x)))

#endif

typedef int (*init_func_t)(void);

#define LOADER_EXPORT(fn, level) \

LOADER_USED const init_func_t init_##fn SECTION(".loader_fn."level) = fn

#define LOADER_BOARD_EARLY_EXPORT(fn) LOADER_EXPORT(fn, "1")

#define LOADER_BOARD_EXPORT(fn) LOADER_EXPORT(fn, "2")

#define LOADER_BOARD_LATE_EXPORT(fn) LOADER_EXPORT(fn, "3")

#define LOADER_COMPONENT_EARLY_EXPORT(fn) LOADER_EXPORT(fn, "4")

#define LOADER_COMPONENT_EXPORT(fn) LOADER_EXPORT(fn, "5")

#define LOADER_COMPONENT_LATE_EXPORT(fn) LOADER_EXPORT(fn, "6")

#define LOADER_APP_EARLY_EXPORT(fn) LOADER_EXPORT(fn, "7")

#define LOADER_APP_EXPORT(fn) LOADER_EXPORT(fn, "8")

#define LOADER_APP_LATE_EXPORT(fn) LOADER_EXPORT(fn, "9")

int LoaderExec(void);

#endif

#include "Loader.h"

static int loader_start(void)

{

return 0;

}

LOADER_EXPORT(loader_start, "0");

static int loader_end(void)

{

return 0;

}

LOADER_EXPORT(loader_end, "9.end");

int LoaderExec(void)

{

int res = 0;

const init_func_t *fn_ptr;

for (fn_ptr = &init_loader_start; fn_ptr < &init_loader_end; fn_ptr++)

{

res += (*fn_ptr)();

}

return res;

}

/* Loader Demo */

/********************** led.c **********************/

#include "Loader.h"

int led_init(void)

{

/* GPIO初始化 */

return 0;

}

LOADER_APP_EXPORT(led_init);

/********************** main.c **********************/

#include "Loader.h"

int main(void)

{

HAL_Init(); /* 初始化芯片底层,实际上该函数也可以通过loader导出 */

LoaderExec(); /* 加载Loader,里面会调用led_init */

while(1)

{

/* do something */

}

}

9. 单片机main函数的作用

其实单片机的主程序其实是一个主函数,我们一般命名为Main,主函数会从上住下运行的,执行到最后又返回上面继续运行。我们用C语言编写Main主函数时,会用到while(1)让主程序不断的循环。

由此可见,主程序里的各种功能是按着顺序来执行的,谁也不能插队。那怎么样来实现中途打断插队呢?这就需要用到中断了。

单片机的中断程序是怎么执行的?

单片机有着各种和样的中断功能,比如定时器中断、外部中断、串口中断等等。比如我们要实时检测一个按键的按下事件,如果在主程序中进行扫描,就会有一定的延时,需要等主程序运行到按键扫描的程序时才可以检测到按键的状态。

10. 单片机main.c

在单片机的开发应用中,已逐渐开始引入高级语言,

C语言就是其中的一种。对用惯了汇编的人来说,总觉得高级语言’可控性’不好,不如汇编那样随心所欲。

但是只要我们掌握了一定的C语言知识,有些东西还是容易做出来的,以下是笔者实际工作中遇到的几个问题,希望对初学C51者有所帮助。

一、C51热启动代码的编制

对于工业控制计算机,往往设有有看门狗电路,当看门狗动作,使计算机复位,这就是热启动。

热启动时,一般不允许从头开始,这将导致现有的已测量到或计算到的值复位,导致系统工作异常。

因而在程序必须判断是热启动还是冷启动,常用的方法是:确定某内存单位为标志位(如0x7f位和0x7e位),

启动时首先读该内存单元的内容,如果它等于一个特定的值(例如两个内存单元的都是0xaa),就认为是热启动,

否则就是冷启动,程序执行初始化部份,并将0xaa赋与这两个内存单元。

根据以上的设计思路,编程时,设置一个指针,让其指向特定的内存单元如0x7f,然后在程序中判断,程序如下:

void main()

{ char data *HotPoint=(char *)0x7f;

if((*HotPoint==0xaa)&&(*(--HotPoint)==0xaa))

{ /*热启动的处理 */

}

else

{ HotPoint=0x7e; /*冷启动的处进

*HotPoint=0xaa;

*(++HotPoint)=0xaa;

}

/*正常工作代码*/

}

然而实际调试中发现,无论是热启动还是冷启动,开机后所有内存单元的值都被复位为0,当然也实现不了热启动的要求。这是为什么呢?原来,用C语言编程时,开机时执行的代码并非是从main()函数的第一句语句开始的,在main()函数的第一句语句执行前要先执行一段’起始代码’。正是这段代码执行了清零的工作。C编译程序提供了这段起始代码的源程序,名为CSTARTUP.A51,打开这个文件,可以看到如下代码:

.

IDATALEN EQU 80H ; the length of IDATA memory in bytes.

.

STARTUP1:

IF IDATALEN <> 0

MOV R0,#IDATALEN - 1

CLR A

IDATALOOP: MOV @R0,A

DJNZ R0,IDATALOOP

ENDIF

.

可见,在执行到判断是否热启动的代码之前,起始代码已将所有内存单元清零。如何解决这个问题呢?好在启动代码是可以更改的,方法是:修改startup.a51源文件,然后用编译程序所附带的a51.exe程序对 startup.a51编译,得到startup.obj文件,然后用这段代码代替原来的起始代码。具体步骤是(设C源程序名为HOTSTART.C):

修改startup.a51源文件(这个文件在C51LIB目录下)。

 

 

执行如下命令:

 

A51 startup.a51 得到startup.obj文件。将此文件拷入HOTSTART.C所在目录。

将编好的C源程序用C51.EXE编译好,得到目标文件HOTS

TART.OBJ。

 

用 L51 HOTSTART, STARTUP.OBJ 命令连接,得到绝对目标文件HOTSTART。

 

用 OHS51 HOTSTART 得到HOTSTART.HEX文件,即可。

 

对于startup.a51的修改,根据自已的需要进行,如将IDATALEN EQU 80H中的80H改为70H,就可以使6F到7F的16字节内存不被清零。

二、直接调用EPROM中已固化的程序

笔者用的仿真机,由6位数码管显示,在内存DE00H处放显示子程序,只要将要显示的数放入显示缓冲区,然后调用这个子程序就可以使用了,汇编指令为:

LCALL 0DEOOH

在用C语言编程时,如何实现这一功能呢?C语言中有指向函数的指针这一概念,可以利用这种指针来实现用函数指针调用函数。指向函数的指针变量的定义格式为:

类型标识符 (*指针变量名)();

在定义好指针后就可以给指针变量赋值,使其指向某个函数的开始存地址,然后用

(*指针变量名)()即可调用这个函数。如下例:

void main(void)

{

void (*DispBuffer)(); /*定义指向函数指针*/

DispBuffer=0xde00; /*赋值*/

for(;;)

{ Key();

DispBuffer();

}

}

三、将浮点数转化为字符数组

笔者在编制应用程序时有这样的要求:将运算的结果(浮点数)存入EEPROM中。我们知道,浮点数在C语言中是以IEEE格式存储的,一个浮点数占用四个字节,例如浮点数34.526存为(160,26,10,66)这四个数。要将一个浮点数存入EEPROM,实际上就是要存这四个数。那么如何在程序中得到一个浮点数的组成数呢?

浮点数在存储时,是存储连续的字节中的,只要设法找到存储位置,就可以得到这些数了。可以定义一个void的指针,将此指针指向需要存储的浮点数,然后将此指针强制转化为char型,这样,利用指针就可以得到组成该浮点数的各个字节的值了。具体程序如下:

#define uchar unsigned char#define uint unsigned intvoid FtoC(void)

{ float a;

uchar i,*px

uchar x[4]; /*定义字符数组,准备存储浮点数的四个字节*、

void *pf;

px=x; /*px指针指向数组x*/

pf=&a; /*void 型指针指向浮点数首地址*/

a=34.526;

for(i=0;i<4;i++)

{ *(px+i)=*((char *)pf+i); /*强制void 型指针转成char型,因为*/

} /*void型指针不能运算*/

}

如果已将数存入EEPROM,要将其取出合并,方法也是一样,可参考下面的程序。

#define uchar unsigned char#define uint unsigned int

void CtoF(void)

{ float a;

uchar i,*px

uchar x[4]={56,180,150,73};

void *pf;

px=x;

pf=&a;

for(i=0;i<4;i++)

{ *((char *)pf+i)=*(px+i);

}

}

以上所用C语言为FRANKLIN C51 VER 3.2。

11. 51单片机main函数会自动循环吗

单片机开机基本步骤如下:

1.内核初始化;

2.强制PC指针指向中断向量表的复位中断向量执行复位中断函数;

3.在复位中断函数中调用 SystemInit 函数,初始化时钟,配置中断向量表等;

4.调用 main 函数完成全局/静态变量的初始化和重定位工作,初始化堆栈和库函数;

5.跳转到main函数中执行二 内核初始化在单片机上电后首先会进行一系列内核的初始化。

顶一下
(0)
0%
踩一下
(0)
0%