资源目录
压缩包内文档预览:
编号:551008
类型:共享资源
大小:7.57MB
格式:RAR
上传时间:2015-12-06
上传人:QQ28****1120
认证信息
个人认证
孙**(实名认证)
辽宁
IP属地:辽宁
6
积分
- 关 键 词:
-
毕业设计论文
- 资源描述:
-
0420、单片机常用芯片和器件手册,毕业设计论文
- 内容简介:
-
C-51程序设计 1 我们不仅提供产品,更提供技术与服务! 单片机电子研发室 Franklin C-51语言设计基础 1 1 Franklin C-51数据类型 Franklin C-51 编译器支持下列数据类型: 数 据 类 型 长 度 值 域 bit 1 字节 0 或 1 signed char 1 字节 -128 +127 unsigned char 1 字节 0 255 signed int 2 字节 -32768 +32867 unsigned int 2 字节 0 65535 signed long 4 字节 -2147483648 +2147483647 unsigned long 4 字节 0 4294967295 float 4 字节 1.176E-38 3.40E+38 指针 13 字节 对象地址 sbit 1 位 0 或 1 sfr 1 字节 0 255 sfr16 2 字节 0 65535 编译的数据类型 (如结构 )包含上表所列的数据类型。由于 8051 系列 是 8 位机,因而不存在字节校准问题。这意味着数据结构成员是顺序放置的。 数据类型的转换:当计算结果隐含着另外一种数据类型时,数据类型可以自动进行转换,例如,将一个位变量赋给一个整型变量时,位型值自动转换为整型值,有符号变量的符号也能自动进行处理。这些转换也可以用 C 语言的标准指令进行人工转换。 单片机 编程器 西南销售服务中心 nts 2 C-51程序设计 1. 2 数据类型的物理结构 1 2 1 bit “ bit”类型只有 1 位,不允许有位指针和位数组。位对象始终位于 8051 CPU 的可寻址 RAM 空间。如果程序控制流允许, L51 将位对象交迭。 1 2 2 signed/unsigned char; data/idata/pdata 指针 “ char”类型标量和基于存贮器的“ data/idata/pdata”指针具有 1 个字节长度( 8 bits)。 1 2 3 signed/unsigned int/short; xdata/code 指针 “ int”和“ short”类型标量及指向 xdata/code 区域的指针具有 2 字节长度( 16 bits)。 整型值(或偏移) 0x1234 以下面方式保存在内存中: 地址: +0 +1 内容: 0x12 0x34 1 2 4 signed/unsigned long “ long”类型标量长为 4 个字节( 32 bits),值 0x12345678 以下面方式放置: 地址: +0 +1 +2 +3 内容: 0x12 0x34 0x56 0x78 1 2 5 “一般”指针 “一般”指针包括 3 个字节: 2 字节偏移和 1 字节存贮器类型: 地址: +0 +1 +2 内容: 存贮器类型 偏移高位 偏移低位 第一个字节代表了指针的存贮器类型,存贮器类型编码如下: 存贮器类型 IDATA XDATA PDATA DATA CODE 值 1 2 3 4 5 使用其它类型值可能导致不可预测的程序动作。 XDATA 类型的 0x1234 地址作为指针表示如下: 地址: +0 +1 +2 内容: 0x02 0x12 0x34 当用常数作指针时,必须注意正确定义存贮器类型和偏移。下例将值 0x41 写入绝对地址为 0x8000 的外部数据存贮器: #define XBYTE ( char *) 0x20000L) XBYTE0x8000=0x41; 上例中用其它常数索引或索引变量也起作用。这样,各种存贮器类型的绝对地址可以一种非常有效的方式访问。但有一个例外,即 SFR。 nts C-51程序设计 3 注意:绝对地址定义为“ long”型常量,低 16 位包含偏移,高 8 位表明了 xdata 类型。为了表示这种指针,必须用长整数来定义存贮器类型。 C51 编译器不检查指针常数,用户必须选择有实际意义的值。 1 2 6 float “ float”类型为 4 个字节( 32 位),使用的格式与 IEEE-754 标准( 32 位)具有 24位精度,尾数的高位始终为“ 1”,因而不保存,位的分布如下: 1 位符号 8 位指数位 23 位尾数 符号位是最高位,尾数为最低的位,内存中按字节存贮如下: 地址: +0 +1 +2 +3 内容: MMMM MMMM MMMM MMMM E MMM MMMM S EEE EEEE 其中: S:符号位, 1=负, 0=正 E:指数(在两个字节中),偏移为 127 M: 23 位尾数,最高位“ 1” 浮点值 12.5 的十六进制为 0xC1480000,它按下面方式存贮: 地址: +0 +1 +2 +3 内容: 0x00 0x00 0x48 0xc1 8051 不包括捕获浮点错误(例外)的中断向量。用户软件因此必须对错误条件作出适当反应。下面推荐一种方法(也可以用其它可靠办法):“ union”用来保存浮点值,这个“ union”必须包括一个“ float”和一个“ unsigned long”,以根据 IEEE 对错误作出响应。除了通常浮点值外, IEEE 标准可能出错的条件以下面二进制值表示,为检查可能出现的计算错误,可在计算后进行检查。因为当执行一个运算时考虑了每个运算符的错误状态并且该状态被送到结果中。 NaN 0xFFFFFFF 不是一个数 +INF 0x7F80000 正无穷(正溢出) -INF 0XFF80000 负无穷(负溢出) 1.3 C-51 的扩充定义 1 3 1 特殊功能寄存器的声明 MSC-51 系列包括多种寄存器,其中一些具有特殊功能,如定时器,端口的控制寄存器等,为了能够直接访问这些寄存器, C51 编译器提供了一种定义的自主形式,这是必要的,因为这些定义与标准 C 语言是不兼容的。 为了支持这些特殊功能寄存器( SFR)的声明,引入了关键词“ sfr”,语法如下: sfr-dcl: sfr sfr_name=int_constant 例: nts 4 C-51程序设计 sfr p0=0x80; sfr p1=0x90; 必须注意的是“ sfr”后不是一个地址而是一个名字。因此上例中名字 P0和 P1( port0和 port1)定义为特殊功能寄存器并被赋予相应的绝对地址,名字可按意愿自由选取,源文件中不应有先定义的 sfr 名字。 “ =”号后的地址必须是常数,不允许带有运算符的表达式,这个常数表达式必须在特殊功能寄存器的地址范围内,位于 0X80 到 0XFF 之间。 8051 系列寄存器数量和类型是极其不同的,因此建议将所有特别的“ sfr”声 明放入一个头文件,头文件包括 8051 一些系列成员中的 SFR 定义。进一步的定义可由用户用一文件编辑器产生。 1 3 2 对 SFR的 16 位数据访问 在新的 8051系列产品中, SFR在功能上经常组合为 16位的,为了有效的访问这类 SFR,使用定义“ sfr16”,当“ SFR”的高端直接位于低端后时,对 SFR16 位的访问是可能的。例如 8052 的定时器 2 就是这种情况, 16 位声明的语法与“ sfr”相同, SFR 低地址部分必须作为 sfr16 的地址: 例: sfr16 T2=0xCC /*Timer2: T2L=0CCH, T2H=0CDH */ sfr16 RCAP2=0xCA /*RCAP2L=0CAH, PCAP2H=0CBH */ 本例中, T2(由 T2L 和 T2H 组成)和 RCAP2(由 RCAP2L 和 RCAP2H 组成)被定义为 16位 SFR,即使在这种情况下,声明中的名字后仍不是赋值语句,而是一个 SFR 地址,高字节必须直接位于低字节之后,这种声明适用于所有新的 SFR,但不能用于 Timer0和 Timer1。 1 3 3 SBIT:特殊功能位声明 在典型的 8051 应用问题中,经常需要单独访问 SFR 中的位, C51 扩充功能使之 成为可能,特殊位,象 SFR 一样,不与标准 C 语言兼容,使用保留字“ sbit”可访问位寻址对象。与 SFR 声明一样,用保留字“ sbit”声明某些特殊位接受符号名,“ =”后语句将绝对值地址赋给变量名,这种地址分配有三种方法: 方法 1: sfr_nameint_constant 当字节是特殊功能寄存器的地址可用这个方法。 sfr_name 必须是已定义的 SFR 的名字,“ ”后的语句定义了基地址上的特殊位的位置,该位置必须是一个 0 7 的数。 例: sfr PSW=0xD0; sfr LE=0xA8; sbit OV=PSW2; sbit CY=PSW7; 方法 2: int_constantint_constant 这种方法以一整常数作基地址,该值必须在 0x80 0xFF 之间,并能被 8 整除,确定位的位置方法同上。 例: sbit OV=0xD02; nts C-51程序设计 5 sbit CV=0xD07; sbit EA=0xA87; 方法 3: int_constant 这种方法是将位的绝对地址赋给变量,地址必须位于 0x80 0xFF 之间。 例: sbit OV=0xD2; sbit CY=0xD7; sbit EA=0xAF; 特殊功能位代表了一个独立的声明类,它不能与其它声明和位域互换。 1 3 4 BIT:位标量声明 除了通常的 C 数据类型外, C51 编译器支持“ bit”数据类型,对此有下列扩充与限制: ( 1) 函数可包含类型为“ bit”的参数,也可将其作为返回值。 bit bfunc( bit b0, bit b1) /* */ return( b1); 注:使用禁止中断( #pragma disable)或包含明确的寄存器组切换( using n)的函数不能返回位值,在这种情况下,编译器会识别出来并产生 一个错误信息。 ( 2) 位标量声明的语法及 C 声明的语义 static bit dirction_bit; extern bit lock_printer_port; bit display_invers; ( 3) 对于位声明的限制 位不能声明为一个指针( bit *bit_poiter) 不存在位数组( bit b_array5) 位声明中允许定义存贮器类型,位都被放入一个位段,它总是在 8051 内部 RAM 中,因此存贮器类型限制为 DATA 或 IDATA,声明为其它存贮器类型都将导致编译出错。 1 3 5 可位寻址对象 可位寻址对象指可以 字节或位寻址的对象,当对象位于 MSC-51 可寻址 RAM 中时会有这种情况, C51 允许带“ bdata”类型的对象放入可位寻址存贮器中。 bdata int ibase; /*位寻址指针 int*/ bdata char bary4; /*位寻址数组 arrray*/ 使用“ sbit”声明可独立访问可位寻址对象的位: sbit mybit0=ibase0; sbit mybit15=ibase15; sbit ary07=bary07; sbit ary37=bary37; nts 6 C-51程序设计 对象“ ibase”和“ bary”也可位寻址: ary37=0; /*寻址“ bary3”中的位 7*/ ibase=-1; /*寻址字节地址 */ mybit15=0; /*寻址“ ibase”的位 15*/ sbit 声明要求基址对象的存贮器类型为“ bdata”,否则只有绝对的位声明方法是合法的。位位置( 操作符号后)的最大值依赖于指定的基类型,这个值于 char/uchar 而言是 0 7,对于 int/uint/short/ushort 而言是 0 15,对于 long/ulong 而言是 0 31。 在编译器 内存贮器类型 bdata与 data一样操作,并且只作与可再定位的 sbit的运算。注:可位寻址的的段长最大不能超过 16 字节,可再定位的 sbit 声明自动转为公共的( PBULIC)以使它们能被其它 C 模块使用。 模块 1: sbitary37=bary37; 模块 2: extern bit ary37; sbit 声明也可为结构和函数所用: union lft float mf;long ml; ; bdata struct bad char ml; union lft u; tcp; sbit tcpf31=tcp.u.ml31; /*浮点限制 */ sbit tcpml0=tcp.ml0; sbit tcmpl7=tcp.ml.7; 注:位位置的指定不能直接被 float 类型所用,如果需要这样做,浮点标量必须与一个长整型标量一起放入一个联合中并且位位置必须由长整型标题指定(见上例)。 1 4 存贮器类型 C51 编译器完全支持 8051 微处理器及其系列的结构,可完全访问 MCS-51 硬件系统所有部分。每个变量可准确地赋予不同的存贮器类型( data, idata, pdata, xdata, code)。访问内部数 据存贮器( idata)要比访问外部数据存贮器( xdata)相对要快一些,因此,可将经常使用的变量置于内部数据存贮器中,而将较大及很少使用的数据单元置于外部数据存贮器中。 存贮器类型 描 述 data 直接寻址内部数据存贮器,访问变量速度最快( 128bytes) bdata 可位寻址内部数据存贮器,允许位与字节混合访问( 16 bytes) iIdata 间接寻址内部数据存贮器,可访问全部地址空间( 256bytes) pPdata 分页( 256bytes)外部数据存贮器,由操作码 MOVX Ri 访问 xdata 外部数据存贮器( 64K),由 MOVX DPTR 访问 code 代码数据存贮器( 64K),由 MOVC A+DPTR 访问 变量说明举例: data char charvar; nts C-51程序设计 7 char code msg=”ENTER PARAMETER:”; unsigned long xdata array100; float idata x,y,z; unsigned char xdata vector1044; sfr p0=0x80; sbit RI=0x98; char bdata flags; sbit flago=flags0; 如果在变量说明时略去存贮器类型标志符,编译器会自动选择默认的存贮器类型。默认的存贮器类型进一步由控制指令 SMALL、 COMPACT 和 LARGE 限制。例如:如果声明 char charvar,则默认的存贮器模式为 SMALL, charvar 放在 data 存贮器;如果使用 COMPACT模式,则 charvar 放入 idata 存贮区;在使用 LARGE 模式的情况下, charvar 被放入外部存贮区或 xdata 存贮区。 1 5 存贮器模式 存贮器模式决定了自动变量和默认存贮器类型,参数传递区和无明确存贮区类型的说明。在固定的存贮器地址变量参数传递是 C51 的一个标准特征,在 SMALL 模式下参数传递是在内部数据存贮区中完成的。 LARGRE 和 COMPACT 模式允许参数在外部存贮器中传递。 C51同时也支持混合模式,例如在 LARGE 模式下生成的程序可将一些函数分页放入 SMALL 模式中从而加快执行速度。 存贮器模式 描 述 SMALL 参数及局部变量放入可直接寻址的内部寄存器(最大 128bytes,默认存贮器类型是 DATA) COMAPCT 参数及局部变量放入分页外内部存贮区(最大 256bytes,默认存贮器类型是 PDATA) LARGE 参数及局部变量直接放入外部数据存贮器(最大 64K,默认存贮器类型是 XDATA) 1 6 指针 Franklin C-51 支持“基于存贮器的”和“一般指针”。 1.6.1 基于存贮器的指针 基于存贮器的指针由 C 源代码中存贮器类型决定并在编译时确定,用这种指针可 高效访问对象且只需一个字节( idata*, data*, pdata*)或 2 个字节( code*, xdata*)。操作较短指针的代码被缩短,一般被“内行”编码;库调用不再必要。 声明举例: nts 8 C-51程序设计 char xdata *pt 在 XDATA 存贮器中声明一个指向对象类型为“ CHAR”的指针。指针默认自身在默认存贮区(决定于编译模式 ),长度为 2 字节。(值为 0 0XFFFF) char xdata *data pdx; 除了指针明确位于内部数据存贮器( data)中外,与上例相同。它与编译模式无关。 data char xdata *pdx; 本例与上例完全相同。存贮器类型定义既可放在声明的开头也可直接放在声明的对象之前。这种形式是为了与早期 C-51 编译器版本兼容。 上面例子阐明了指针的一般声明及使用。它们与所有的数据类型和存贮器类型相关。所有用于一般指针的操作同样可用于基于存贮器的指针。 1.6.2 一般指针 “一般”指针需 3 个字节: 1 个字节为存贮类型, 2 个字节为偏移量。存贮器类型决定了对象所用的 8051 存贮器空间,偏移量指向实际地址。一个“一般”指针可访问任何变量而不管它在 8051 存贮器空间中的位置。这样就允许一般性函数,如 memcpy 将数据从任意一个地址拷贝到另一个地址空间。 1.6.3 基于存贮器的指针与一般指针的转换 一个已定位指针可转换为一个一般指针( 3 字节)及副本。这在某些时候是很有用的。例如库函数包含一个一般指针变量,象 printf(), sprintf(), gets()等包含一个一般指针变量,如同以前的编译器和库版本一样。这些函数因而广泛适用。 例: extern int printf( void *format,); 在 printf 调用中, 2 字节指针自动转换为一个 3 字节指针,而 printf 的原型正需要一个一般指针( 3 字节)作为其 第一参量。 注:如果没有函数原型,函数调用的参量中指针总是转换为一般指针。如果函数确实需要一个短指针作参量,这会产生错误,为了避免在程序中发生这类错误,需要使用头文件,或某些函数声明函数原型。这将保证让编译器转换为所需类型,否则会产生类型不匹配错误。 例:指针定义说明 指 针 说 明 长 度 指 向 float *p; 3 字节 所有 8051 存贮器空间中的“ float”(一般指针) char data *dp; 1 字节 “ data”存贮器中的“ char” int idata *ip; 1 字节 “ idata”中的“ int” long pdata *pp; 1 字节 “ pdata”中的“ long” char xdata *xp; 2 字节 “ xdata”中的“ char” int code *cp; 2 字节 “ code”中的“ int” 1.6.4 抽象指针类型 抽象指针类型用来在每个存贮区访问任意绝对地址,或来产生绝对 CALLs。在这个过nts C-51程序设计 9 程中,常数类型或字符型、整型都用抽象类型作了原则性修改(类型整理)以允许进行绝对访问或 调用。 例: char xdata *px; char idata *pi; char code *pc; char c; int i; pc = (void*)main; i = (int(code*)(void)0xFF00(); /*LCALL 0FF00H */ c = *(char code*)0x8000); /*char code0x8000*/ i = *(int code*)0x1200); /*int from code0x1200*/ px = *(char xdata *xdata*)0x4000); /*x ptr from xdata0x4000*/ px = (char xdata *xdata*)0x4000)0; /*同上 */ px = (char xdata *xdata *)0x4000)1 /*x ptr from xdata0x4002*/ 1.7 寄存器组定义 8051 系列的器件包含 4 个相同的寄存器组,每个寄存器组包括 8 个寄存器( R0 R7),C51 编译器可使在一函数中决定用哪一寄存器组成为可能。绝对寄存 器的访问可用AREGS/NOAREGS 和 REGISTERBANK 来控制。 定义一个带扩展性的函数语法如下: 返回类型 函数名( 参数 ) 模式 再入 中断 nusing n 再入和中断将在后两节讨论。 例: void rb_function(void) using 3; “ using”不允许用于外部函数,它对函数的目标代码影响如下: 函数入口处将当前寄存器保存入栈; 指它的寄存器还会改变; 函数退出前寄存器组被恢复。 “ using”定义对于返回一个寄存器内的值的函数是无用的。编程者必须十分小心以保证任 何寄存器切换都只在仔细控制的区域发生。如果不做到这一点将会产生不正确的函数结果。即使当编程者使用同一寄存器组时,带“ using”属性的函数原则上也不能返回一个位值。 实际产生的代码决定于编译器及不同开关条件,有时用命令产生绝对的寄存器地址,当需要进行这样的地址计算时,使用 REGISTERBANK 指令的影响只是计算 Arn 寄存器使用的地址,而必进行实际切换。 1.8 中断服务程序 C51 编译器及其对 C 语言的扩充允许编程者对中断的所有方面进行控制。这种支持能nts 10 C-51程序设计 使系统编程者创建高效的中断服务程序,用户只需在普通和高级方式下关 心中断及必要的寄存器组切换操作, C51 编译器将产生最合适的代码。 1.8.1 中断服务程序的定义 使用中断服务函数的完整语法如下: 返回值 函数名( 参数 ) 模式 再入 interrupt nusing n “ interrupt”后接一个 0 31 的常数,不允许使用表达式。 中断不允许用于外部函数,它对函数目标代码的影响如下: 当使用函数时, SFR 中的 ACC、 B、 DPH、 DPL 和 PSW(当需要时)入栈; 如不使用寄存器组切换,甚至中断函数所需的所有工作寄存器( Rn)都入栈; 函数退出前,所有的寄存器内容出栈 ; 函数由 8051 控制命令“ RETI”终止。 1.8.2 开发中断过程时的规则 不能进行参数传递,如果中断过程包括任何参数声明,编译器将产生一个错误信息; 无返回值,如果想定义一个返回值将产生错误,然而,如果返回整型值编译器将不产生错误信息,因为整型值是默认值,因而编译器不能清楚识别。 编译器会识别对中断过程的直接调用并拒绝它们,在任何情况下不能直接调用中断过程,因为退出该过程是由操作码 RETI 完成的。 RETI 影响 8051 芯片的硬件中断系统,由于硬件上没有中断请求存在,因而这个操作码的结果是不定的并且通常是致命的。由 于疏忽,可能用指针来间接调用它,这是值得注意的。 编译器从绝对地址 8n+3 处产生一个中断向量,其中 n 为中断号,该向量包括一个到中断过程的跳转,向量的产生可由指令 NOINTVECTOR 压缩。因而用户有能力从独立的汇编模块中提供中断向量。 C51 编译器允许 0 31 个中断,究竟允许哪些中断依赖于使用的 8051 系列芯片,编译器不能检查。 如果中断程序中有浮点运算,必须保持浮点寄存器状态,当没有其它程序执行浮点运算时,可能不保存,函数“ fsave”和“ fprestore”用来保存浮点状态。 中断过程调用的函数所使用的 寄存器必须与中断过程相同,当没有使用“ using”指令时,编译器会选择一个寄存器组作绝对寄存器访问,当子程序使用另一个寄存器组时会发生错误,用户必须保证按要求使用相应寄存器组, C 编译器不会对此检查。 例: unsigned int interruptent; unsigned char second; time() interrupt 1 using 2 /*定时器 0 中断服务程序 ,工作寄存器使用 2 区 */ nts C-51程序设计 11 if(+interruptcnt=4000) second+; /*秒计数加 一 */ interruptcnt=0; /*清中断计数 */ 1 9 再入函数 再入函数可被递归调用,调用可发生在任何时候,即使是在中断过程中。在实时处理的应用问题中常常需要再入函数。 使用关键字“ reentrant”可有选择地定义函数有再入能力。在存贮器模式的基础上为再入函数在内部或外部存贮器中模拟了一个栈区域。由于 MCS-51 缺乏合适的寻址方法,使用栈结构是相当必要的。因而应尽量少用再入函数。 定义一再入函数的语法如下: 返回值 函数名( 参数 ) 模式 reetrantinterrupt nusing n 例: int calc(char i,int b) reentrant int x; x=tablei; return(x*b); 使用再入函数有如下规定 : 不能传递类型为“ bit”的参数。也不能声明一个局部标量,再入功能不能包括位操作及 MCS-51 可位寻址区域。 不能在“ alien”函数调用再入函数。 再入函数可同时有其它属性,如“ using”函数模式和“ interrupt”。 再入函数不能同时有“ alien”属性,从而遵守 PL/M 规则。 返回地址及可 能的 PUSH/POP 操作存入 MCS-51 的栈中或被执行(不在再入栈中)。 在同一模块中,任意模块的再入函数( small reentrant, lage reentrant, compact reentrant)不能与具有不同模式的再入函数混合。 再入函数举例: /*这个再入函数可以从“ main”及中断程序中调用 */ int calc(char i,int b)reentrant int x; x=tablei; return(x*b); 1 10 参数传递 nts 12 C-51程序设计 通过 CPU的寄存器可传递至多三个参数。这样产生 与汇编子程序相当的有效参数机制。如果寄存器被占用,或说明了“ #pragma NOREGPARMS”,参数变量将使用固定的存贮器位置,存贮器模式决定了 8051 存贮器为参数提供的位置。 表:候选的参数寄存器 参数类型 CHAR, 1 字节指针 INT, 2 字节指针 LONG, FLOAT 一般指针 一个参数 R7 R6, R7 R4 R7 R1, R2, R3 二个参数 R5 R4, R5 R4 R7 R1, R2, R3 三个参数 R3 R2, R3 R1, R2, R3 函数的返回值放在 CPU 固定的寄存器中,列表如下。这样,与汇编子程序的接口变得非常容易。 表:函数返回值的寄存器用法 返 回 值 寄 存 器 意 义 bit 进位标志 C (unsigned) char R7 (unsigned) int R6,R7 高位在 R6,低位在 R7 (unsigned) long R4 R7 高位在 R4,低位 在 R7 float R4 R7 32 位 IEEE 格式 指 针 R1,R2,R3 类型选择在 R3,高位在 R2,低位在 R1 1 11 PL/M51接口 Franklin C51 利用关键字“ alien”提供了一个与 Intel PL/M-51 直接和简单和接口,关键字“ alien”在所有存贮器模式下可用于“ extern”和“ public”函数。现有的 PL/M-51程序利用 C 语言的强大功能可与 Franklin C-51 连接起来。 使用关键字“ alien”, C51 可用 PL/M-51 规定的参数 传递方式工作。“ alien”可用于外部或公共函数,并可用于任一模式,这样,已有的 PL/M-51 程序可加入到 C-51 中。 Alien函数始终包含一个标准的参数数量,因此, C 中定义的三点()记号不被接受,且会产生一个错误信息。 例: extern alien char plm_function(unsigned char,unsigned int); extern char c_function(unsigned char x,unsigned char y) return(x*y); PL/M-51 兼容函数必须定义以关键字“ alien”。这样, PL/M 函数的参数传递及参数返回规定在 C 编译器中才被考虑。 nts C-51程序设计 13 1 12 汇编接口 参数是通过固定的 CPU 寄存器传给汇编程序的,当使用“ #pragma NOREGPARMS”时,则通过固定的存贮器位置传递参数。这样就给汇编与 Franklin C-51 之间提供了一个非常简洁的接口。返回值在 CPU 寄存器中。 下例为在汇编中用来编码的“ toupper”函数,参数传递发生在寄存器中。 UPPER SEGMENT CODE ;程序代码段 PUBLIC _toupper ;入口地址 RESG UPPER ;选择程序代码段 toupper: MOV A,R7 ; char 参数在寄存器 R7 中 CJNE A,#a,UPP1 UPP1: JC UPPERT CJNE A,#z+1,UPP2 UPP2: JNE UPPRET CLR ACC.5 UPPRET: MOV R7,A ; char 返回值在寄存器 R7 中 RET ;返回 C 1 13 内部函数 Franklin C-51 支持下列内部函数。内 部函数既是再入的又是有效的。 表: C51 的内部函数 函 数 描 述 memcpy,memsset,memchr,memmove,memcmp ANSI 的内存操作功能 strcmp,strcpy ANSI 字符串处理功能 _crol_,_irol_,lrol_ 左移字符、整数、长整数 _crolr_,_irolr_,lrolr_ 右移字符、整数、长整数 _nop_ 空操作 _testbit_ 测试并清 位( JBC 指令) 1 14 代码优化 Franklin C51 可将即使有经验的程序员编制的代码进行优化。用户可选 6 个优化级,另外,用 OPTIMIZE( SIZE), NOREGPARMS 和 NOAREGS 时会影响生成代码的类型。 C51 的所有优化如下: ( 1) 一般优化: 常数折迭:发生在一个表达式或地址计算中的几个常数值组合为一个常数。 跳转优化:跳转转到最终的目标地址,以提高程序效率。 死码消除:不可执行代码(死码)可从程序中去掉。 nts 14 C-51程序设计 寄存器变量:只要有可能,自动变量和参量放入寄存器中,为这些变量保留的数据存贮器将去除。 通过 寄存器传递参数:寄存器中可传递最多三个参数。 全局公共子式消除:相同的子表达式或地址计算(多次发生在同一函数中)将被识别出来,并且只要有可能,将只计算一次。 ( 2) 基于 8051 的优化: 窥孔( PEEPHOLE)优化:只要能节省存贮空间或执行时间,复杂的运算都将化简。 访问优化:常数和变量直接包含在操作中。 数据覆盖:函数的数据和位移被标记为 OVERLAYABLE,被 L51 用其它数据和位覆盖。 CASE/SWITCH 优化: SWITCH/CASE 语句优化为一个跳转或一串跳转。 ( 3) 代码生成选项: OPTMIZE( SIZE):共同的“ C”操作被子程序代替:程序码长被压缩。 NOAREGS:不使用绝对寄存器访问,程序代码在这种方式下独立于寄存器组。 NOREGPARMS:参数传递总是在本数据段完成,程序代码与早期 C-51 版本兼容。 1 15 C 库 C-51 编译器包含 6 个不同的编译库,可根据不同函数的需要进行优化,这些库几乎支持所有的 ANSI 函数调用。因此,用此标准的 C 程序可在编译和连接后立即运行。 库 描 述 C51S.LIB SMALL 模式,无浮点运算 C51FPS.LIB 浮 点数学运算库( SMALL 模式) C51C.LIB COMPACT 模式,无浮点运算 C51FPC.LIB 浮点运算库( COMPACT 模式) C51L.LIB LARGE 模式,无浮点运算 C51FPL.LIB 浮点运算库( LARGE 模式) C51 编译器包含的库模块,都有源代码,对它们可作与硬件相关的修改。用户改变对于现有硬件输入和输出结构的两个模块,就可修改所有库函数,同样也可以重新很快地构造如“ printf”和“ puts”函数用 LCD 显示。 L51 连接器的检查从而保证所有模块都用一 种模式编译并自动选择编译库,从而使用户完全可以不用不同库的细节。 1 16 配置文件 C51 编译器可根据不同的硬件环境由 4 个文件作出修改。下列配置文件包括在 C-51软件包中: STARTUP51.51: C51 编译器的启动程序,所有的栈指针和存贮器, 只要需要,将被初始化。 nts C-51程序设计 15 INIT.A51: 在文件中已明确初始化了变量作初始化。如果系统装入“看门狗”,该文件可包含附加的“看门狗”刷新。 PUBCHAR.C: 函数“ printf”、“ puts”等的字符输出核心程序,该程序可根据用户硬件加以修改(如 LCD 显示)。 GETKEY.C: 函数“ getchar”、“ scanf”等的字符输入核心程序,该程序可根据硬件加以修改(如矩阵键盘)。 所有的文件都包含在 C 运行库中,因此,不能在连接时指定调用。如果用户改变一个文件,可将其编译后与其它目标文件一起连接,因而不必改动运行库。库中原文件自动忽略。 例: L51 DEMO1.OBJ,DEMO2.OBJ,STARTUP.OBJ,PUTCHAR.OBJ 本例将用户建立的 STARTUP.OBJ 和 PUTCHAR.OBJ 连接起来 STARTUP.A51 文件 STARTUP.51 开头包含一些 C 编译结构使用的 EQU 语句。每个 EQU 语句的功能描述如下: IDATALEN 声明系统开始时有多少内存需要用 0 初始化。默认值为 80H,因为几乎每个 8051 指令至少包含 128 字节内部 RAM。对于 256 字节内部 RAM 的 8052 可使用 100H。当用户程序在开始时需要使用 0 初始化的内存时才有必要作改动。如果内存初始化必须保持对掉电模式系统的完全抑制, IDATALEN 应设为 0。这种情况下至少得保持所有位于段? C_LIB_DATA 和? C_LIB_DBIT 中的变量都置为 0。否则有些库函数不能 完全发挥作用,? C_LIB_DATA 段的长度因不同应用问题而不同 ,其当前长度可在 MAP 文件中找到。 XDATASTART XDATALEN 表明了需要以 0 初始化的 PDATA 区首址和长度, XDATASTART 指明了 XDATA区首址, XDATALEN 表明了需初始化的字节数。 PDATASTART PDATALEN 表明了需以 0 初始化的 PDATA 区首址及长度, PDATASTART 指明了首址,XDATALEN 指定了长度。 LBPSTACK LBPSTACKTOP 定义了 SMALL 模式下创建的再入函数使用的栈区。 LBPSTACK 表明是否对栈指针(变量? C_LBP)初始化, LBPSTACKTOP 指明了栈顶首址。对于具有 256字节内部 RAM 的 8051 系统,当存贮区作首址为 0XFF 的栈时,可不初始化。C51 不作栈区是否满足特定应用的检查,用户必须自己进行测试。 XBPSTACK XBPSTACKTOP 为在 LARGE 模式下创建的再入函数定义了栈区, XBPSTACK 表明指针(变量?C_XBP)是否初始化, XBPSTACKTOP 指定了栈顶地址。当存贮区作为首址为nts 16 C-51程序设计 0Xffff(在 XDATA 区)的栈时,可不作初始化。同上一样, C51 不作栈检查,需要用户自己测试。 PBPSTACK PBPSTACKTOP 为在 COMPACT 模式下创建的再入函数定义了栈区, PBPSTACK 表明栈指针(变量? C_PBP)是否初始化。 PBPSTACKTOP 指定了栈顶地址。当存贮区作为首址为 0Xff(在 PDATA 区)的栈时,可不作初始化。同上一样, C51 不作栈检查,需要用户自己测试。 PPAGEENABLE PPAGE 当在 COMPACT 模式中用 16 位寻址 XDATA 存贮区时需要这些指令。对于使用LARGE 模式的程序,可用它提高运行速度或减小代码长度。 PPAGEENABLE 允许 8051 端口 2 的初始化,对端口 2 的寻址允许在任意 XDATA 页 256 字节变量空间的映射。这两个指令必须和 L51 的控制指令 PDATA 一起使用。 PDATA指定了 XDATA存贮器中 PDATA区的首址。例:在 STARTUP.A51中, PPAGEENABLE置为 1, PPAGE 置为 10H。这种情况下 PDATA 区首址为 1000H( 10H 页),而L51 必须包含一个值在 1000和 10FFH 之间的控制语句: L51输入模块 PDATA( 1050H)。注: L51 和 C51 都不对 PPAGE/PDATA 指令正确性进行检查 ,用户必须保证 PPAGE 和 PDATA 包含一个合适的值。 INIT.A51: 文件 INIT.A51 包含一个定义了“看门狗”刷新的宏。当系统包括“看门狗”以及用户变量初始化时间比“看门狗”刷新时间要长时,必须改变这个宏。这种情况下,宏 WATCHCOG必须包含“看门狗”刷新的代码。 例:
- 温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

人人文库网所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。