当前位置:首页 > 单片机 > 单片机
[导读]  主要介绍Keil C51的预处理方法如宏定义、常用的预处理指令及文件包含指令,C51编译库的选择及代码优化原理,C51与汇编混合编程的方法与实现以及超过64KB空间的地址分页方法的C51实现。教学目标  1.了解Keil C5

  主要介绍Keil C51的预处理方法如宏定义、常用的预处理指令及文件包含指令,C51编译库的选择及代码优化原理,C51与汇编混合编程的方法与实现以及超过64KB空间的地址分页方法的C51实现。

教学目标

  1.了解Keil C51的预处理方法,主要有宏定义#define、常用的预处理指令#define、#error、#if 、#else、#elif、#endif、#ifdef、#ifndef 、#undef 、#line 、#pragma 及文件包含指令#include。

  2.了解small、compact、large三种编译模式信代码优化方法。

  3. 掌握C51模块内部调用汇编程序的三种方法,理解C51模块与汇编模块之间的接口规则,主要有C51函数名与汇编程序名的转换规则、C51函数及其相关段的命名规则、C51函数的参数传递规则。

  4.理解Keil C51的Bankswitch原理,了解Keil C51的三种分页方式、公共空间的概念,掌握BL51有关分页的配置,以PSD813F2为硬件基础,掌握Keil C51分页的实现过程,能进行分页的程序设计。

  一、预处理器

  1.1宏定义

宏定义格式如下:#define 名称 替换文字

宏是一种简单的替换,在程序中凡是出现“名称”之处均被“替换文字”替代,替换文字可以是数字,也可以是字符串。

  1.2预处理指令

由ANSI C的标准规定,预处理指令主要包括: #define、#error、#if 、#else、#elif、#endif、#ifdef、#ifndef 、#undef 、#line 、#pragma。

  #define 指令
  例如:#define PI 3.1415926凡是出现“PI”的地方均以“3.1415926”替换。宏的出现有助于提高程序的可读性及书写方便性,也有助于程序的调试。但是,出现在引号中的字符串是不能替换的。如printf(“PIn”);该语句运行后输出的是:PI而不是3.1415926。

  define注意事项:
1)在宏定义语名后没有“;”;
2)在C51程序中习惯上用大写字符作为宏替换名,常放在程序开头;
3)宏定义还有一个特点,就是宏替换名可以带有形式参数,在程序中用到时,实际参数会代替这些形式参数。
例如: #define MAX(x, y) (x>y)?x:y

main(){inti=10,j=15;printf("TheMaxmumis%d",MAX(i,j);}

上例宏定义语句的含义是用宏替换名MAX(x, y)代替x, y中较大者,同样也可定义:
#define MIN(x, y) (x表示用宏替换名MIN(x, y)代替x, y中较小者。
4)#define命令在程序之外,其有效范围为定义命令之后到源文件结束,但是可以用#undef命令终止宏定义的作用域。如:

#definePI3.1415926voidmain(void){……}#undefPI

PI的范围从#define 开始到#undef PI 结束。

  #if、#else、#endif指令
#if、#els和#endif指令为条件编择指令, 它的一般形式为:

#if常数表达式语句段;#else语句段;#endif

上述结构的含义是: 若#if指令后的常数表达式为真, 则编译#if到#else 之间的程序段; 否则编译#else到#endif之间的程序段。
例如:

#defineMAX200main(){#ifMAX>999printf("compiledforbiggern");#elseprintf("compiledforsmalln");#endif}

  #undef指令
#undef指令用来删除事先定义的宏定义, 其一般形式为:
#undef 宏替换名
例如:

#defineTRUE1...#undefTURE

#undef主要用来使宏替换名只限定在需要使用它们的程序段中。

  #include
文件包含是指用#include通常用来将一些常用的宏定义或变量定义所在的源文件包含到“#include”所在的文件中来。
通常格式如下:
#include“filename”或#include
在编译预处理时,将#include命令进行文件包含处理,即将filename中的全部内容复制插入到该指令处,减少重复劳动。通常引号包含的文件与现文件在同一个位置,否则用“<>”括起来。
在源文件开始处一般都要用一些#include指令,如

#include“stdio.h”#include“reg51.h”

如用户自定义了一个字库文件”kzk.h”,在源文件开始用#include “hzk.h”,之后,则可以在源程序中使用字库。

  二、C51编译库及代码优化技术

  2.1 C51编译库
  C51编译器包含6个不同的编译库,如表12-2-1可根据不同需要进行优化 , C51 编译器包含的库模块,都有源代码,对它们可作与硬件相关的修改。用户改变对于现有硬件输入和输出结构的两个模块,就可修改所有库函数,同样也可以重新很快地构造如“printf”和“puts”函数系统默认串口为输出设备,但用户可修改为LCD 显示。

  2.2 代码优化
C51可将即使有经验的程序员编制的代码进行优化,用户可选6个优化级,C51的所有优化方法如下:
  1)一般优化:
常数折迭:发生在一个表达式或地址计算中的几个常数值组合为一个常数;
跳转优化:跳转转到最终的目标地址,以提高程序效率;
死码消除:不可执行代码(死码)可从程序中去掉;
寄存器变量:只要有可能,自动变量和参量放入寄存器中;
通过寄存器传递参数:寄存器中可传递最多三个参数;
全局公共子式消除:相同的子表达式或地址计算(多次发生在同一函数中)将被识别出来,并且只要有可能,将只计算一次。
  2)基于8051 的优化
窥孔(PEEPHOLE)优化:只要能节省存贮空间或执行时间,复杂的运算都将化简。
访问优化:常数和变量直接包含在操作中。
数据覆盖:函数的数据和位移被标记为OVERLAYABLE,被L51 用其它数据和位覆盖。
CASE/SWITCH 优化:SWITCH/CASE 语句优化为一个跳转或一串跳转。
  3)代码生成选项:
OPTMIZE(SIZE):共同的“C”操作被子程序代替:程序码长被压缩。
NOAREGS:不使用绝对寄存器访问,程序代码在这种方式下独立于寄存器组。
NOREGPARMS:参数传递总是在本数据段完成,程序代码与早期C51 版本兼容。

  三、C51与ASM混合编程技术
  3.1 混合编程意义
通常用C51来编写主程序。然而,在一些时序要求严格的采用汇编程序设计具有更高的效率,因此要求在C程序中调用一些用汇编语言编写的子程序。
另一方面,在以汇编语言为主体的程序开发过程中,如果涉及到复杂的数学运算,往往需要借助C51提供的运算库函数和强大的数据处理能力,这就要求在汇编中调用C51函数。
  3.2 C51模块内的汇编接口
模块内接口通常是指在C函数内部插入汇编代码,也称内嵌汇编语句 。
在线汇编提供了能直接读写硬件的能力,如读写中断控制允许寄存器等,但编译器并不检查和分析在线汇编语言,插入在线汇编语言改变汇编环境或可能改变C变量的值可能导致严重的错误。
  方法一、直接在函数体内的每个汇编语句前加?“asm”预编译指令。

voidreset_data(void){asmMOVR1,#0AHasmLOOP:INCAasmDJNZR0,LOOPreturn;}

  方法二、把asm作为关键字后续汇编用大括号括起来即可。

voidreset_data(void){asm{MOVR1,#0AHLOOP:INCADJNZR0,LOOP}return;}

  方法三、在C模块内通过语句“#pragma”嵌入汇编代码。

voidreset(void){#pragmaasmMOVR1,#0AHLOOP:INCADJNZR0,LOOP#pragmaendasmreturn;}

  Keil C51编译环境相关设置
  将嵌有汇编语句源文件加入要编译的项目文件,将光标指向此文件,选择右键菜单“option?for?file?'asm.c'”,将属性单“properties”中的“Generate?Assembler?SRC?File”与“Assemble?SRC?File”两项设置成黑体的“√”,将“Link?Public?Only”的“√”去掉,再编译即可。用此方法可以在C51源代码的任意位置用#pragma?asm和#pragma?endasm嵌入汇编语句。如果编译时未用SRC指令,则C51中的汇编代码会被编译器忽略。

3.3 C51与汇编的模块间接口
1、C51函数名与汇编程序名的转换规则
C51程序模块编译成目标文件后,其中的函数名依据其定义的性质不同会转换为不同的函数名,因此在C51和汇编程序的相互调用时要求汇编程序必须服从这种函数名的转换规则。C51中函数名转换规则如表12-3-1所列。


2、C51函数及其相关段的命名规则
一个C51源程序模块被编译后,其中的每一个函数以“?PR?函数名?模块名”为名的命名规则被分配到一个独立的CODE段。
如:模块“FUNC51”内包含一个名为“func”的函数,则其CODE段的名字是“?PR?FUNC?FUNC51”。
如果一个函数包含有data和bit对象的局部变量,编译器将按“?函数名?BYTE和?函数名?BIT”命令规则建立一个data和bit段,它们代表所要传递参数的起始位置,其偏移值为零。这些段是公开的,因而它们的地址可被其它模块访问。另外,这些段被编译器赋予“OVERLAYABLE”标志,故可被L51连接/定位器作覆盖分析。
依赖于所使用的存储器模式,这些段的段名按表12-3-2所列规则命名,在相互调用时,汇编语言必须服从C51有关段名的命名规则。
各种存储器模式下函数相关段名的命名规则

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

单片机内部有很多的特殊功能寄存器,每个寄存器在单片机内部都分配有唯一的地址,一般我们会根据寄存器功能的不同给寄存器赋予各自的名称,当我们需要在程序中操作这些特殊功能寄存器时,必须要在程序的最前面将这些名称加以声明,声明的...

关键字: C51 数据类型 扩充定义

数据元(Data Element),也称为数据元素,是用一组属性描述其定义、标识、表示和允许值的数据单元,在一定语境下,通常用于构建一个语义正确、独立且无歧义的特定概念语义的信息单元。数据元可以理解为数据的基本单元,将若...

关键字: C51 数据类型

KeilμVision4是Keil软件公司为8051系列微控制器及其兼容产品设计的集成式软件开发环境。μVision4集成了C51编译器和A51汇编器,其界面类似于Microsoft VS,支持C语言和汇编语言程序的编写...

关键字: 程序 编译 链接

第五届中国国际进口博览会,丹纳赫集团携手中国健康传媒集团,在创新技术在疫苗、细胞治疗药物、中药研发以及质量控制中的应用等领域签署战略合作。同时,双方将共同编译并出版《生物制药工艺》等书籍,以支持相关领域国际前沿技术工具在...

关键字: 编译 质量控制

之后新建新的工程,添加.a文件就可以使用了,当然也可以使用keil来添加,但是keil默认的是用.lab,需要自己配置一下文件属性,改为lib文件即可。一半release sdk的时候用这种方式很关键的,毕竟自己的核心代...

关键字: keil 文件属性 lib文件

(全球TMT2022年9月27日讯)新思科技近日宣布推出业内首款基于其ZeBu® EP1硬件仿真系统的硬件仿真与原型验证统一硬件系统,致力为SoC验证和前期软件开发提供更高水平的性能和灵活性。新思科技ZeBu...

关键字: 硬件仿真 新思科技 硬件系统 编译

LoRa是semtech公司开发的一种低功耗局域网无线标准,其名称“LoRa”是远距离无线电(Long Range Radio),它最大特点就是在同样的功耗条件下比其他无线方式传播的距离更远,实现了低功耗和远距离的统一,...

关键字: LoRa 智慧城市 连接技术

3个SystemVerilog新特性!01`begin_keyword`end_keyword硬件描述语言中有很多特殊的编译或者综合等工具的预执行指令,在某些场景下我们可以利用一下HDL之外的语法去指导工具,而不是信马由...

关键字: SYSTEMVERILOG DEFINE PACKAGE 编译

你知道,为什么在C中使用了pow函数不需要链接libm库吗?什么情况需要指定链接库?在解释之前,先回顾一下。//来源:公众号【编程珠玑】//https://www.yanbinghu.com#include#includ...

关键字: 编译 POW IBM TEST

▼点击下方名片,关注公众号▼欢迎关注【玩转单片机与嵌入式】公众号,回复关键字获取更多免费资料。回复【加群】,限时免费进入知识共享群;回复【3D封装库】,常用元器件的3D封装库;回复【电容】,获取电容、元器件选型相关的内容...

关键字: C51 MDK RealView
关闭
关闭