C51编译器-语言扩展(4)-函数

发布者:科技独行者最新更新时间:2016-11-14 来源: eefocus关键字:C51  编译器  语言扩展  函数 手机看文章 扫描二维码
随时随地手机看文章
Function Declarations函数声明

Cx51对标准C进行了一定的扩展,使用这些扩展可以:

(1)把一个函数声明为一个中断过程

(2)选择使用的寄存器组

(3)选择存储器模式

(4)声时可重入

(5)声明外部函数

在函数声中包含这些扩展或属性,使用下面的方法声明Cx51函数

[return_type] funcname ([args]) [{small | compact | large}][reentrant][interrupt n][using n]

这里

return_type                 返回值类型

funcname                函数名称

args                        参数

small, compact, or large 存储器模式

reentrant            是否可重入

interrupt            是否是中断函数

using                使用哪个寄存器组

Function Parameters and the Stack函数参和堆栈

经典的8051堆栈指针只访问内部的数据存储器。Cx51紧接着在所有的数据之后放堆栈区。堆栈指针间接地访问内部数据存储器,可以访问所有的00-FFH的空间

在经典的8051中堆栈的空间是受限制的,最大只有256字节。除了函数参数消耗堆栈空间,Cx51为每个函数指定了一些固定的内存空间。当函数被调用时,调用者必须在进入函数之前把参数拷贝到这个固定的空间中。然后函数从这个固定的空间中读取并使用这些参数。在这个过程中只有返回地址存放在堆栈中。中断函数会需要更多的堆栈空间,因为程序必须切换寄存器组并且保存一些寄存器的值到堆栈中。

注:Cx51允许使用在某些8051的增强型变种中可用的扩展的堆栈区。通过这种方式,堆栈区域的大小可以增加到几K字节。

在缺省的情况下,Cx51使用三个寄存器传递函数的参数,这样可以提高代码的执行速度。

注:有些8051变种仅提供64字节的片上数据存储器,大多数器件有256字节。在使用存储器模式时应该把这些都考虑进去,毕竟片上的data和idata数据存储器直接影响到堆栈空间的大小。

Passing Parameters in Registers通过寄存器传递参数

Cx51允许使用CPU寄存器传递三个参数,由于这种方式不需将参数写入存储器和从存储器中读出,所以明显地提高了系统的性能。参数的传递受上一章讲到的REGPARMS 和NOREGPARMS指令控制。

下表列出了用于不同位置参数和数据类型的寄存器。

 

参数个数

 

Char, 1-yte ptr

 

Int, 2-byte ptr

 

Long, float

 

Generic ptr

 

1

 

R7

 

R6&R7

 

R4-R7

 

R1-R3

 

2

 

R5

 

R4&R5

 

R4-R7

 

R1-R3

 

3

 

R3

 

R2&R3

 

 

 

R1-R3

 

没有可用的寄存器来传递参数,则用一个固定的存储器区域来传递函数参数。

Function Return Values函数返回值

函数返回值总是使用CPU寄存器。下表列出了返回值的类型和所用的寄存器。

 

返回值

 

寄存器

 

描述

 

Bit

 

进位标志

 

 

 

Char, unsigned char, 1-byte ptr

 

R7

 

 

 

Int, unsigned int, 2-byte ptr

 

R6&R7

 

高位字节为R6,低位字节为R7

 

Long, unsigned long

 

R4-R7

 

高位字节为R4,低位字节为R7

 

Float

 

R4-R7

 

32位IEEE格式

 

Generic ptr

 

R1-R3

 

存储器类型在R3,高位R2,低位R1

 

注:如果函数的第一个参数是bit类型的,其他的参数据是不通过寄存器传递的。这是因为能在寄存器中传递的参数与前述的编号方案都不相同。因此,bit类型的参数应该在参数列表中末尾声明。

Specifying the Memory Model for a Function

声明函数的存储器模式

Cx51函数通常采用缺省的存储器模式来决定哪个存储器空间用于函数的参数和局部变量。

可以通过包含small, compact,或large在函数的属性中来指定函数的存储器类型。

如:

int large_func (int i, int k) large /* Large model */

{

return (mtest (i, k) + 2);

}

函数使用small存储器模式的好处是函数的参数和局部变量都放在8051的RAM中。因此,数据访问效率非常高。然而,内部的数存储器有限。有时候有限的内部数据存储器的大小不能满足需要,就必须使用其他的存储器模式。在这种情况下,可以使用上面的方法定义一个函数使不同的存储器模式。

通过指定函数的存储器模式,可以从三种可能的可重入堆栈和结构指针中择优使用。堆访问SMALL模式要比访问LARGE模式快得多。

Specifying the Register Bank for a Function

指定函数使用的寄存器组

8051系列器件的低32字节被分成了4个组,每个组8个寄存器。程序可以通过R0-R7访问这些寄存器。寄存器组可以通过程序状态字(PSW)的两个位选择。寄存器组对中断处理或者是使用实时操作系统非常有用。在中断服务程序中CPU切换寄存器组而不把不当前的寄存器都保存起来。

关键字using用来指定函数使用的寄存器组:

void rb_function (void) using 3

{

    。。。。。。。

}

关键字using的参数是一个0-3的整型常量,而且表达式中不允许有操作符出现。在函数的原型中不允许出现using关键字。这个关键词对函数代码有如下影响:

(1)当前选择的寄存器组在函数的入口处被保存在堆栈中

(2)指定的寄存器组被设定

(3)前面使用的寄存器组被保存下来直到当前的函数退出

不能关键字using来声明一个返回值在寄存器中的函数。在使用的时候必须非常小心,确保寄存器组切换只出现在谨慎地控制地区域。稍不小心会得到错误的返回值。即使用同一个寄存器组,使用了using关键字声明了属性的函数也不能返回一个bit类型的值。

典型地,using属性对于声明了interrupt属的函数是非常有用的。为每一个级别的中断都声明一个不同寄存器组是比较常见的。因此,你可以在所有非中断程序中使用一个寄存器组,在高优先级中断中使用一个寄存器组,在低优先级中断中使用一个寄存器组。

Register Bank Access寄存器访问

 Cx51允许在一函数中定义缺省的寄存器组。控制指令REGISTERBANK允许程序员在源文件中指定在所有函数另使用哪一个寄存器组。然而这个指令并不产生切换寄存器的代码。

复位后,8051在PSW中装入00h从而选择寄存器组0。所以缺省地所有非中断程序代码都使寄存器组0。要想改变,必须:

(1)       修改startup代码以选择其他的寄存器组

(2)       使用REGISTERBANK指令进行声明

缺省地,Cx51编译器生成用绝对地址访问R0-R7的代码。这是为了最高的执行效率。绝对地址的使用通过指令AREGS和NOAREGS控制。使用绝对址进行寄存器访问的函数不能被使用其他寄存器组的函数调用。由于调用者使用了不同的寄存器组,这样做会引起不可预料的后果。要使用函数对当前的寄存器组不敏感,函数必须在编译前使用控制指令NOAREGS。这对于那种可能在主函数中调用,也可能被使用不同寄存器组的中断程序调用的函数很有用。注:Cx51编译器并不检查函数间的寄存器组是否一致。因此,必须确保使用不寄存器组的函数只调用那些不指定缺省寄存器组的函数。

关键字:C51  编译器  语言扩展  函数 引用地址:C51编译器-语言扩展(4)-函数

上一篇:C51编译器-语言扩展(5)-中断函数
下一篇:C51编译器-语言扩展(3)-指针

推荐阅读最新更新时间:2024-03-16 15:20

keil C51存储区域类型是什么
keil C51存储区域分为程序存储区和数据存储区2大类型。 一.程序存储区(Pragram Area): 欲将声明的数据存放在程序存储区域,可以使用关键字“code”说明。 例 unsigned char code i=10;则表示 i为无符号字符型数据存放区域为程序存储区。 二.数据存储区(Data Memory): 数据存储区域分为内部数据存储区、外部数据存储区域和特殊功能寄存器寻址区。 1.内部数据存储区域(Internal Data Memory):可以使关键字 data、iadta、bdata 做相应说明。 data:直接寻址区,声明的数据存储范围为内部RAM低128字节 0X00~0X7F
[单片机]
KEIL C51的#pragma NOIV
CYRESS给出的USB例程,在periph.c中普遍在开头一行加了下列编译指令: #pragma NOIV 它的注释是,不产生中断向量。查找C51手册,说明如下: NOINTVECTOR Compiler Directive Abbreviation NOIV Arguments None. Default INTVECTOR (0) Vision Options C51 Interrupt vectors at address. Description The NOINTVECTOR directive
[单片机]
keil C51 指针总结
  变量就是一种在程序执行过程中其值能不断变化的量。要在程序中使用变量必须先用标识符作为变量名,并指出所用的数据类型和存储模式,这样编译系统才能为变量分配相应的存储空间。定义一个变量的格式如下:     数据类型   变量名表   在定义格式中除了数据类型和变量名表是必要的,其它都是可选项。存储种类有四种:自动(auto)、外部(extern)、静态(static)和寄存器(register),缺省类型为自动(auto)。这些存储种类的具体含义和使用方法,将在第七课《变量的存储》中进一步进行学习。   而这里的数据类型则是和我们在第四课中学习到的名种数据类型的定义是一样的。说明了一个变量的数据类型后,还可选择说明该变量的存储器类型
[单片机]
keil <font color='red'>C51</font> 指针总结
STM32几种操作的寄存器版本和库函数版本对比
1、USART1接收完成标志检测 USART1- SR&0X40 == 0 USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET 2、USART1发送数据 USART1- DR = (u8) ch; USART_SendData(USART1,(u8)ch);
[单片机]
Keil C51与Keil ARM共存
第一节 绝对地址访问 C51提供了三种访问绝对地址的方法: 1. 绝对宏: 在程序中,用“#include”即可使用其中定义的宏来访问绝对地址,包括: CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD 具体使用可看一看absacc.h便知 例如: rval=CBYTE ;指向程序存贮器的0002h地址 rval=XWORD ;指向外RAM的0004h地址 2. _at_关键字 直接在数据定义后加上_at_ const即可,但是注意: (1)绝对变量不能被初使化; (2)bit型函数及变量不能用_at_指定。 例如: idata struct link list _at_
[单片机]
STM32库函数SystemInit()的理解
SystemInit()这个函数出现在main()函数的第一行,可以看出它的重要性。以前关于SystemInit()这个函数从来没有关心过,只知道这是进行 STM32 系统初始化的一个函数。今天决定仔细看看,重新开始STM32的学习。这个函数在system_stm32f10x.c中,此C文件主要就是干具体硬件配置相关的工作。 void SystemInit (void) { RCC- CR |= (uint32_t)0x00000001; #ifndef STM32F10X_CL RCC- CFGR &= (uint32_t)0xF8FF0000; #else RCC- CFGR &= (uint32_
[单片机]
C51跟atmega64的串行通信及PROTEUS仿真设计
script src="/jf/jf-arcMain-1.js" type=text/javascript /script script type=text/javascript /script script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript /script script src="http://pagead2.googlesyndication.com/pagead/js/r20110914/r20110914/show_ads_impl.js" /script script src="
[单片机]
<font color='red'>C51</font>跟atmega64的串行通信及PROTEUS仿真设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved