2023年12月8日发(作者:夏普70寸电视价格)
MPLAB® C18C 编译器用户指南 2005 Microchip Technology Inc. DS51288J_CN请注意以下有关Microchip器件代码保护功能的要点:•••Microchip的产品均达到Microchip数据手册中所述的技术指标。Microchip确信:在正常使用的情况下,Microchip系列产品是当今市场上同类产品中最安全的产品之一。目前,仍存在着恶意、甚至是非法破坏代码保护功能的行为。就我们所知,所有这些行为都不是以Microchip数据手册中规定的操作规范来使用Microchip产品的。这样做的人极可能侵犯了知识产权。Microchip愿与那些注重代码完整性的客户合作。Microchip或任何其他半导体厂商均无法保证其代码的安全性。代码保护并不意味着我们保证产品是“牢不可破”的。••代码保护功能处于持续发展中。Microchip承诺将不断改进产品的代码保护功能。任何试图破坏Microchip代码保护功能的行为均可视为违反了《数字器件千年版权法案(Digital Millennium Copyright Act)》。如果这种行为导致他人在未经授权的情况下,能访问您的软件或其他受版权保护的成果,您有权依据该法案提起诉讼,从而制止这种行为。提供本文档的中文版本仅为了便于理解。MicrochipTechnology Inc.及其分公司和相关公司、各级主管与员工及事务代理机构对译文中可能存在的任何差错不承担任何责任。建议参考Microchip Technology Inc.的英文原版文档。本出版物中所述的器件应用信息及其他类似内容仅为您提供便利,它们可能由更新之信息所替代。确保应用符合技术规范,是您自身应负的责任。Microchip对这些信息不作任何明示或暗示、书面或口头、法定或其他形式的声明或担保,包括但不限于针对其使用情况、质量、性能、适销性或特定用途的适用性的声明或担保。Microchip对因这些信息及使用这些信息而引起的后果不承担任何责任。未经Microchip书面批准,不得将Microchip的产品用作生命维持系统中的关键组件。在Microchip知识产权保护下,不得暗中或以其他方式转让任何许可证。商标Microchip 的名称和徽标组合、Microchip 徽标、Accuron、dsPIC、KEELOQ、microID、MPLAB、PIC、PICmicro、PICSTART、PROMATE、PowerSmart、rfPIC和SmartShunt均为Microchip Technology Inc.在美国和其他国家或地区的注册商标。AmpLab、FilterLab、Migratable Memory、MXDEV、MXLAB、PICMASTER、SEEVAL、SmartSensor和The Embedded
Control Solutions Company 均为Microchip Technology Inc.在美国的注册商标。Analog-for-the-Digital Age、Application Maestro、dsPICDEM、、dsPICworks、ECAN、ECONOMONITOR、FanSense、FlexROM、fuzzyLAB、In-Circuit Serial
Programming、ICSP、ICEPIC、Linear Active Thermistor、MPASM、MPLIB、MPLINK、MPSIM、PICkit、PICDEM、、PICLAB、PICtail、PowerCal、PowerInfo、PowerMate、PowerTool、Real ICE、rfLAB、rfPICDEM、Select Mode、Smart Serial、SmartTel、Total Endurance、UNI/O、WiperLock和Zena均为Microchip Technology Inc.在美国和其他国家或地区的商标。SQTP是Microchip Technology Inc.在美国的服务标记。在此提及的所有其他商标均为各持有公司所有。© 2005, Microchip Technology Inc.版权所有。Microchip
位于美国亚利桑那州Chandler和Tempe及位于加利福尼亚州Mountain View的全球总部、设计中心和晶圆生产厂均于2003年10月通过了ISO/TS-16949:2002
质量体系认证。公司在PICmicro®
8位单片机、KEELOQ®跳码器件、串行EEPROM、单片机外设、非易失性存储器和模拟产品方面的质量体系流程均符合ISO/TS-16949:2002。此外,Microchip在开发系统的设计和生产方面的质量体系也已通过了ISO 9001:2000
认证。DS51288J_CN 第 ii页 2005 Microchip Technology ® C18 C 编译器用户指南目录前 言.................................................................................................................................1第1章 简介1.11.2概述..............................................................................................................7调用编译器...................................................................................................71.2.1 生成输出文件.................................................................................................81.2.2 显示诊断信息.................................................................................................81.2.3 定义宏............................................................................................................91.2.4 选择处理器.....................................................................................................91.2.5 选择模式.........................................................................................................9第2章 语法说明2.1数据类型及数值范围...................................................................................112.1.1 整型..............................................................................................................112.1.2 浮点型..........................................................................................................112.22.3字节存储顺序 — 12存储类别.....................................................................................................122.3.1 122.3.2 static型函数参数.....................................................................................132.4存储限定符.................................................................................................142.4.1 near/far 数据存储对象.............................................................................142.4.2 near/far程序存储对象.............................................................................142.4.3 ram/rom限定符..........................................................................................142.5包含文件搜索路径......................................................................................152.5.1 系统头文件...................................................................................................152.5.2 用户头文件...................................................................................................152.62.7预定义宏名.................................................................................................15与ISO的差异.............................................................................................152.7.1 整型的提升...................................................................................................152.7.2 数字常量.......................................................................................................162.7.3 字符串常量...................................................................................................162.7.4 stdio.h函数..............................................................................................182.8语言的扩展.................................................................................................182.8.1 匿名结构.......................................................................................................182.8.2 行内汇编.......................................................................................................19 2005 Microchip Technology 51288J_CN 第iii页MPLAB® C18 C 编译器用户指南2.9Pragma伪指令...........................................................................................202.9.1 #pragma sectiontype ............................................................................202.9.2 #pragma interruptlow fname /#pragma 272.9.3 #pragma tmpdata [section-name].....................................................312.9.4 #pragma varlocate bank variable-name#pragma varlocate "section-name" 332.9.5 #342.10针对处理器的头文件..................................................................................362.11针对处理器的寄存器定义文件....................................................................38第3章 运行时模型3.13.2存储模型....................................................................................................39关于调用的约定..........................................................................................403.2.1 非扩展模式的约定.........................................................................................403.2.2 扩展模式约定................................................................................................413.2.3 返回值...........................................................................................................423.2.4 管理软件堆栈................................................................................................433.2.5 C语言与汇编语言的混合编程.......................................................................433.3启动代码....................................................................................................483.3.1 默认操作.......................................................................................................483.3.2 定制..............................................................................................................493.4编译器管理的资源......................................................................................50合并相同的字符串......................................................................................49转移优化....................................................................................................50存储区选择优化 .........................................................................................50W寄存器内容跟踪.....................................................................................51代码排序....................................................................................................51尾部合并....................................................................................................52删除执行不到的代码..................................................................................53复制传递....................................................................................................53冗余存储删除.............................................................................................54删除死代码.................................................................................................55过程抽象....................................................................................................55应用程序:使用LED和中断的嵌入式“Hello, World!”程序....................59应用程序:创建大数据对象及读写62应用程序:使用EEDATA和多个中断源....................................................67第4章 优化4.14.24.34.44.54.64.74.84.94.104.11第5章 应用实例5.15.25.3DS51288J_CN 第iv页 2005 Microchip Technology Inc.目录附录A COFF文件格式A.1struct filehdr — 文件头..................................................................73A.1.1
unsigned short 73A.1.2 unsigned short 73A.1.3 unsigned long .73A.1.4 unsigned long .73A.1.5 unsigned long 73A.1.6 unsigned short 73A.1.7 unsigned short .74A.2struct opthdr — 可选文件头...............................................................74A.2.1 unsigned 74A.2.2 unsigned 74A.2.3 unsigned long 75A.2.4 unsigned long rom_76A.2.5 unsigned long ram_76A.3struct scnhdr — 段头.........................................................................77A.3.1 union _s.....................................................................................................78A.3.2 unsigned long 78A.3.3 unsigned long .78A.3.4 unsigned long .78A.3.5 unsigned long 78A.3.6 unsigned short 78A.3.7 unsigned short .78A.3.8 unsigned long 79A.4struct reloc — 重定位记录.................................................................79A.4.1 unsigned long 79A.4.2 unsigned long .79A.4.3 short 79A.4.4 unsigned short 80A.5struct syment — 符号表记录...............................................................81A.5.1 union _n.....................................................................................................81A.5.2 unsigned long 81A.5.3 short 82A.5.4 unsigned long 82A.5.5 char 83A.5.6 unsigned char 83A.6struct coff_lineno — 行号记录.......................................................84A.6.1 unsigned long .84A.6.2 unsigned short 84A.6.3 unsigned long 84A.6.4 unsigned short .84A.6.5 unsigned long .84A.7struct aux_file — 源文件的附加符号表记录....................................84A.7.1 unsigned long .84A.7.2 unsigned long 84A.7.3 unsigned char 85 2005 Microchip Technology 51288J_CN 第v页MPLAB® C18 C 编译器用户指南A.8struct aux_scn — 段的附加符号表记录..............................................85A.8.1 unsigned long .85A.8.2 unsigned short 85A.8.3 unsigned short 85A.9struct aux_tag — struct/union/enum标记名的附加符号表记录.85A.9.1 unsigned short 85A.9.2 unsigned long .85A.10struct aux_eos — struct/union/enum结束的附加符号表记录.....86A.10.1 unsigned long 86A.10.2 unsigned short .86A.11struct aux_fcn — 函数名的附加符号表记录.......................................86A.11.1 unsigned long 86A.11.2 unsigned long 86A.11.3 unsigned long 86A.11.4 short 86A.12struct aux_fcn_calls — 函数调用的附加符号表记录.......................87A.12.1 unsigned long 87A.12.2 unsigned long x_87A.13struct aux_arr — 数组的附加符号表记录...........................................87A.13.1 unsigned long 87A.13.2 unsigned short .87A.13.3 unsigned short x_dimen[X_DIMNUM]................................................87A.14struct aux_eobf — 块或函数结尾的附加符号表记录..........................88A.14.1 unsigned short .88A.15struct aux_bobf — 块或函数开头的附加符号表记录.........................88A.15.1 unsigned short .88A.15.2 unsigned long 88A.16struct aux_var — struct/union/enum类型变量的附加符号表记录.................................................................................88A.16.1 unsigned long 88A.16.2 unsigned short .88A.17struct aux_field — 位域的附加记录..................................................89A.17.1 unsigned short .89附录B 采用ANSI定义的方式B.1B.2B.3B.4B.5B.6B.7B.8简介............................................................................................................91标识符........................................................................................................91字符............................................................................................................91整型............................................................................................................92浮点数........................................................................................................92数组和指针.................................................................................................93寄存器........................................................................................................93结构和联合.................................................................................................93DS51288J_CN 第vi页 2005 Microchip Technology Inc.目录B.9B.10B.11B.12位域............................................................................................................93枚举............................................................................................................94Switch 语句................................................................................................94预处理伪指令.............................................................................................94附录C 命令行概述附录D MPLAB C18诊断D.1D.2D.3错误............................................................................................................97警告..........................................................................................................109消息..........................................................................................................112源代码兼容性...........................................................................................113E.1.1 栈帧大小....................................................................................................113E.1.2 static型参数..........................................................................................113E.1.3 overlay关键字........................................................................................113E.1.4 行内汇编....................................................................................................114E.1.5 预定义宏....................................................................................................114附录E 扩展模式E.1E.2E.3命令行选项差别........................................................................................115COFF文件差别........................................................................................115E.3.1 一般处理器.................................................................................................115E.3.2 文件头的f_flags字段............................................................................115术语表..........................................................................................................................117索引..............................................................................................................................123全球销售及服务网点.....................................................................................................128 2005 Microchip Technology 51288J_CN 第vii页MPLAB® C18 C 编译器用户指南DS51288J_CN 第viii页 2005 Microchip Technology ® C18 C 编译器用户指南 前 言客户须知所有文档均会过时,本文档也不例外。Microchip的工具和文档将不断演变以满足客户的需求,因此实际使用中有些对话框和/或工具说明可能与本文档所述之内容有所不同。请访问我们的网站()获取最新文档。文档均标记有“DS”编号。该编号出现在每页底部的页码之前。DS编号的命名约定为“DSXXXXXA”,其中“XXXXX”为文档编号,“A”为文档版本。欲了解开发工具的最新信息,请参考MPLAB® IDE在线帮助。从Help(帮助)菜单选择Topics(主题),打开现有在线帮助文件列表。简介本文档论述MPLAB® C18编译器的技术细节,并讲解MPLAB C18编译器的所有功能。 这里假定读者已经具备如下基本素质:•知道如何编写C程序•知道如何使用MPLAB集成开发环境(Integrated Development Environment,IDE)来创建和调试项目• 已经阅读并理解了所使用单片机的数据手册文档内容编排文档内容编排如下:•第1章:简介 — 提供对MPLAB C18编译器的概述以及有关调用编译器的信息。•第2章:语法说明 — 论述MPLAB C18编译器与ANSI标准的不同之处。•第3章:运行时模型 — 论述MPLAB C18编译器如何利用 PIC18 PICmicro® 单片机的资源。•第4章:优化 — 论述MPLAB C18编译器执行的优化功能。•第5章:示例应用程序 — 给出了几个示例应用程序,并就本用户指南中论述的各主题,对源代码进行了说明。 2005 Microchip Technology 51288J_CN 第 1页MPLAB® C18 C 编译器用户指南•附录A:COFF文件格式 — 详细阐述了Microchip的COFF格式。•附录B:采用ANSI定义的方式 — 论述按照ANSI标准的要求,MPLAB C18实现所定义的执行方式。•附录C:命令行概述 — 列出了命令行选项以及论述每个命令行选项的参考章节。•附录D:MPLAB C18诊断 — 列出了错误、警告和消息。•附录E:扩展模式 — 论述非扩展模式和扩展模式之间的区别。本指南中使用的约定本用户指南使用如下文档约定:文档约定说明Arial字体:斜体字参考书目Courier New字体:常规Courier New示例源代码文件名文件路径关键字命令行选项斜体Courier New可变参数0bnnnn0xnnnn方括号[ ]省略号...涵义示例MPLAB® IDE User’s Guide#define :mcc18h_asm, _endasm, static-Opa+, -Opa-file.o,其中file可以是任意有效的文件名二进制数,n 为其中一位0b00100, 0b10十六进制数,其中n是一个十0xFFFF, 0x007A六进制数字可选项mcc18 [options] file [options]代替重复文字var_name [, ]表示用户提供的代码void main (void){ ...}仅完全版软件支持的功能1.2.5 Selecting the Mode图标:DS51288J_CN 第 2页 2005 Microchip Technology Inc.前言PIC18参考读物readme.c18这个文件随软件提供,包含本文档中可能未提供的最新信息。PIC18 Configuration Settings Addendum(DS51537)列出了由MPLAB C18 C编译器的#pragma config伪指令和 MPASM™汇编器的CONFIG伪指令所支持的Microchip PIC18器件配置位设置。
MPLAB® C18 C编译器入门(DS51295E_CN)描述如何安装MPLAB C18编译器,如何编写简单的程序以及如何在MPLAB IDE中
使用编译器。MPLAB® C18 C编译器函数库(DS51297F_CN)关于MPLAB C18函数库和预编译目标文件的参考指南。列出了随MPLAB C18 C编译器提供的所有库函数,并详细描述了这些库函数的使用。MPLAB® IDE 快速入门指南(DS51281C_CN)描述如何安装MPLAB IDE软件,以及如何使用它来创建项目和烧写器件。
MPASM™汇编器、MPLINK™目标链接器和MPLIB™目标库管理器用户指南
(DS33014J_CN)讲述如何使用Microchip PICmicro MCU 汇编器(MPASM)、链接器(MPLINK)和库管理器(MPLIB)。PICmicro® 18C MCU系列参考手册(DS39500A_CN)重点介绍增强型单片机系列器件。说明了增强型单片机系列的架构和外设模块的工作原理,但没有涉及到每个器件的具体细节。PIC18器件数据手册和应用笔记讲述PIC18 器件工作和电气特性的数据手册。应用笔记介绍了如何使用PIC18器件。要获得上面列出的任何文档,请访问Microchip的网站(),获得Adobe Acrobat(.pdf)格式的文档。 2005 Microchip Technology 51288J_CN 第 3页MPLAB® C18 C 编译器用户指南C语言参考读物American National Standard for Information Systems – Programming Language – C.
American National Standards Institute (ANSI), 11 West 42nd. Street, New York,
New York, 10036.此标准规定了用C语言编写程序的格式,并对C程序进行了解释。其目的是提高C程序在多种计算机系统上的可移植性、可靠性、可维护性及执行效率。Harbison, Samuel P. and Steele, Guy L., C: A Reference Manual, Fourth Edition.
Prentice-Hall, Englewood Cliffs, New Jersey 07632.详细地讲述了 C编程语言。这本书是一本权威性的参考手册,它对 C语言、运行时库以及C编程的风格都进行了完整的描述,C编程强调正确性、可移植性和可维护性。Huang, Han-Way. PIC® Microcontroller: An Introduction to Software & Hardware
Interfacing. Thomson Delmar Learning, Clifton Park, New York 12065.对Microchip PIC18单片机系列进行了全面介绍,包括 PIC单片机外设功能的编程和接口。这本书可用作大学教科书,其中使用了PIC单片机汇编语言和MPLAB C18 C编译器。Kernighan, Brian W. and Ritchie, Dennis M. The C Programming Language, Second
Edition. Prentice Hall, Englewood Cliffs, New Jersey 07632.对由ANSI标准定义的C语言进行了简明阐述。对于C程序员来说是一本出色的参考书。Kochan, Steven G. Programming In ANSI C, Revised Edition. Hayden Books,
Indianapolis, Indiana 46268.学习ANSI C的另一本出色的参考书,用作大学教材。Peatman, John B. Embedded Design with the PIC18F452 Microcontroller, First
Edition. Pearson Education, Inc., Upper Saddle River, New Jersey 07458.重点介绍Microchip公司的PIC18FXXX系列单片机以及如何编写优化的应用代码。Van Sickle, Ted. Programming Microcontrollers in C, First Edition. LLH Technology
Publishing, Eagle Rock, Virginia 24085.尽管这本书主要讲的是Motorola 单片机,但其中单片机C语言编程的基本原理是很有用的。其他参考读物Standards Committee of the IEEE Computer Society – IEEE Standard for Binary
Floating-Point Arithmetic. The Institute of Electrical and Electronics Engineers,
Inc., 345 East 47th Street, New York, New York 10017.这个标准描述了MPLAB C18采用的浮点数格式。DS51288J_CN 第 4页 2005 Microchip Technology Inc.前言MICROCHIP网站Microchip网站()为客户提供在线支持。客户可通过该网站方便地获取文件和信息。只要使用常用的因特网浏览器即可访问。网站提供以下信息:•产品支持——数据手册和勘误表、应用笔记和样本程序、设计资源、用户指南以及硬件支持文档、最新的软件版本以及存档软件•一般技术支持——常见问题(FAQ)、技术支持请求、在线讨论组以及Microchip顾问计划成员名单•Microchip业务——产品选型和订购指南、最新Microchip新闻稿、研讨会和活动安排表、Microchip销售办事处、代理商以及工厂代表列表开发系统变更通知客户服务Microchip的客户通知服务有助于客户了解Microchip产品的最新信息。注册客户可在他们感兴趣的某个产品系列或开发工具发生变更、更新、发布新版本或勘误表时,收到电子邮件通知。欲注册,请登录Microchip网站,点击“变更通知客户(Customer Change Notification)”服务并按照注册说明完成注册。开发系统产品的分类如下:•编译器——Microchip C编译器及其他语言工具的最新信息,包括MPLAB C18和MPLAB C30 C编译器、MPASMTM和MPLAB ASM30汇编器、MPLINKTM和MPLAB LINK30目标链接器,以及MPLIBTM和 MPLAB LIB30目标库管理器。•仿真器——Microchip在线仿真器的最新信息,包括MPLAB ICE 2000和MPLAB
ICE 4000。•在线调试器——Microchip在线调试器MPLAB ICD 2的最新信息。•MPLAB® IDE——关于支持开发系统工具的Windows®集成开发环境Microchip
MPLAB IDE的最新信息,主要针对MPLAB IDE、MPLAB SIM模拟器、MPLAB
IDE项目管理器以及一般编辑和调试功能。•编程器——Microchip编程器的最新信息,包括MPLAB PM3和PRO MATE® II器件编程器以及PICSTART® Plus和PICkit® 1开发编程器。 2005 Microchip Technology 51288J_CN 第 5页MPLAB® C18 C 编译器用户指南客户支持Microchip产品的用户可通过以下渠道获得帮助:•••••代理商或代表当地销售办事处应用工程师(FAE)技术支持开发系统信息热线客户应联系其代理商、代表或应用工程师(FAE)寻求支持。当地销售办事处也可为客户提供帮助。本文档后附有销售办事处的联系方式。也可通过获得网上技术支持。DS51288J_CN 第 6页 2005 Microchip Technology ® C18 C 编译器用户指南第1章 简介1.1概述MPLAB C18编译器是适用于PIC18 PICmicro单片机(MCU)的独立而优化的ANSI
C编译器。仅在ANSI标准X3.159-1989与高效的PICmicro 单片机支持有冲突的情况下,此编译器才会与ANSI标准有所偏离。 此编译器是一个32位Windows®平台应用程序,与Microchip的MPLAB IDE完全兼容,它允许使用MPLAB ICE在线仿真器、MPLAB ICD 2在线调试器或MPLAB SIM软件模拟器进行源代码级调试。MPLAB C18编译器有以下特点:•••••••••与ANSI '89 兼容能集成到MPLAB IDE,便于进行项目管理和源代码级调试能生成可重定位的目标模块,增强代码的重用性与由MPASM汇编器生成的目标模块兼容,允许在同一个项目中自由地进行汇编语言和C语言的混合编程对外部存储器的读/写访问是透明的 当需要进行实时控制时能很好地支持行内汇编具有多级优化的高效代码生成引擎拥有广泛的库支持,包括PWM、SPI、I2C™、UART、USART、字符串操作和数学函数库用户能对数据和代码的存储空间分配进行完全控制1.2调用编译器《MPLAB® C18
C编译器入门》(DS51295E_CN)描述了如何在MPLAB IDE中使用C18编译器。也可以通过命令行调用编译器,命令行用法如下:mcc18 [options] file [options]可以指定一个源文件和任意个命令行选项。--help命令行选项列出编译器接受的所有命令行选项。 -verbose命令行选项使编译器在编译结束时显示版本号以及错误、警告和消息的总数等信息。 2005 Microchip Technology 51288J_CN 第 7页MPLAB® C18 C 编译器用户指南1.2.1生成输出文件默认情况下,编译器会生成一个名为file.o的输出目标文件,其中,file是在命令行上指定的源文件名,不包括扩展名。可通过-fo命令行选项改变输出目标文件名。例如:mcc18 -fo bar.o foo.c如果源文件有错误,那么编译器会生成一个名为的错误文件,其中,file是在命令行上指定的源文件名,不包括扩展名。可通过-fe 命令行选项改变错误文件名。例如:mcc18 -fe foo.c1.2.2显示诊断信息诊断信息可通过-w 和-nw 命令行选项控制。-w命令行选项设置警告诊断的级别
(1、2 或 3)。表1-1列出了警告诊断的级别以及所表示的诊断类型。-nw 命令行选项禁止特定的消息(附录D“MPLAB C18诊断”或 --help-message-list命令行选项列出由编译器生成的所有消息)。 使用--help-message-all命令行选项,可得到关于所有消息的帮助。若要获得关于某个特定诊断的帮助,可使用 --help-message命令行选项。例如:mcc18 --help-message=2068会显示以下结果:2068: obsolete use of implicit 'int' ANSI standard allows a variable to be declared without a base type
being specified, e.g., "extern x;", in which case a base type of 'int'
is implied. This usage is deprecated by the standard as obsolete, and
therefore a diagnostic is issued to that effect. 表 1-1:警告级别警告级别123所表示的诊断错误(致命的和非致命的)级别1 加警告级别2 加消息DS51288J_CN 第 8页 2005 Microchip Technology Inc.简介1.2.3定义宏-D命令行选项允许定义宏。可以用如下两种方式之一指定-D命令行选项:-Dname 或
-Dname=value。-Dname定义宏名为name并设定其值为1;-Dname=value定义宏名为name并设定其值为value。例如:mcc18 -DMODE定义了宏MODE,其值为1,而:mcc18 -DMODE=2定义宏MODE的值为2。使用-D命令行选项的一个例子是条件编译,例如:#if MODE == 1x = 5;#elif MODE == 2x = 6;#elsex = 7;#endif1.2.4选择处理器默认情况下,MPLAB C18针对一般的PIC18 PICmicro单片机编译应用程序。可以利用-pprocessor命令行选项指定为某个特定的处理器生成目标文件,其中processor 指定要使用的处理器型号。例如,要生成仅供PIC18F452使用的目标文件,应该使用命令行选项-p18f452。命令行选项-p18cxx明确指定针对一般的PIC18单片机编译源文件。1.2.5选择模式编译器可工作在如下两种不同的工作模式: 扩展模式1和非扩展模式。工作在扩展模式时,编译器使用扩展指令(即ADDFSR、ADDULNK、 CALLW、 MOVSF、 MOVSS、PUSHL、SUBFSR和 SUBULNK)和立即数变址寻址,这种寻址方式通常需要较少的指令来访问基于堆栈的变量(因此占用较小的程序存储空间)。工作在非扩展模式时,编译器不使用扩展指令或立即数变址寻址。 --extended和--no-extended命令行选项告知编译器工作模式。当指定--extended 命令行选项时,编译器要求用-p选项选择的处理器支持扩展指令集,或者在为一般的PIC18单片机编译应用程序(参见第1.2.4节“选择处理器”)。可将--no-extended命令行选项用于任何PIC18单片机,包括一般的单片机。 如果在命令行中既不指定--extended也不指定--no-extended 命令行选项,编译器将工作在非扩展模式,而与所选择的处理器无关。 表1-2概括了基于所指定命令行选项的编译器工作模式。1.当演示版过期时,编译器不能工作在扩展模式。 2005 Microchip Technology 51288J_CN 第 9页MPLAB® C18 C 编译器用户指南 表 1-2:模式选择-p extended--extended--no-extended不指定注:扩展非扩展非扩展-p no-extended错误非扩展非扩展-p18cxx扩展非扩展非扩展不指定编译器扩展非扩展非扩展如果使用mcc18 --help调用编译器,将显示关于编译器工作在非扩展模式的帮助;但是,当编译器工作在非扩展模式时,不是所有的命令行选项都有效。要查看关于编译器工作在扩展模式时的帮助,应该使用命令行选项mcc18 --extended
--help。
注:其他命令行选项将在本用户指南的后面部分中论述,在附录C“命令行概述”中可以找到对所有命令行选项的概括。DS51288J_CN 第 10页 2005 Microchip Technology ® C18 C 编译器用户指南第2章 语法说明2.1数据类型及数值范围2.1.1整型MPLAB C18编译器支持由ANSI定义的标准整型。标准整型的数值范围如表2-1所示。另外,MPLAB C18还支持24位整型short long int(或 long short
int),分为有符号和无符号两种类型。表2-1也列出了24位整型的数值范围。表 2-1:char(1,2)signed charunsigned charintunsigned intshortunsigned shortshort longunsigned short longlongunsigned long注整型数据的长度及数值范围类型长度8 位8位8位16位16 位16 位16位24 位24 位32位32 位最小值-128-1280-32,7680-32,7680-8,388,6080-2,147,483,6480最大值,7676553532,76765,5358,388,60716,777,2152,147,483,6474,294,967,2951:若char前没有符号说明,则默认为有符号型。2:可通过-k命令行选项使无符号说明的char默认为无符号型。2.1.2浮点型对MPLAB C18来说,double或float数据类型都是32位浮点型。MPLAB C18利用IEEE 754浮点型标准表示浮点类型。表2-2列出了浮点型数据的数值范围。表 2-2:类型长度32 位浮点型数据的长度及数值范围最小指数-126-126最大指数128128规格化的最小值规格化的最大值2–126 ≈ 1.17549435e - 382128 * (2-2–15) ≈ 6.80564693e + 382–126 ≈ 1.17549435e - 382128 * (2-2–15) ≈ 6.80564693e + 38floatdouble32 位 2005 Microchip Technology 51288J_CN 第 11页MPLAB® C18 C 编译器用户指南2.2字节存储顺序 — ENDIANNESSEndianness指多字节数据中的字节存储顺序。MPLAB C18 采用低字节低地址(little-endian)格式存储数据,低字节存储在较低地址中(即数据是按“低字节先存”的方式存储的)。例如:#pragma idata test=0x0200long l=0xAABBCCDD;数据在存储器中的存放结果如下:地址内容0x02000xDD0x02010xCC0x02020xBB0x02030xAA2.3存储类别MPLAB C18支持ANSI标准的存储类别(auto、extern、register、static
和typedef)。2.3.1OverlayMPLAB C18编译器引入了overlay(重叠)存储类别,仅当编译器工作在非扩展模式(参见第1.2.5节“选择模式”)时才使用此存储类别。overlay存储类别可用于局部变量(但不能用于形式参数、函数定义或全局变量)。overlay存储类别将相关变量分配到一个特定于函数的静态重叠存储区。这种变量是静态分配存储空间的,但每次进入函数时都要被初始化。例如:void f (void){ overlay int x = 5; x++;}尽管x的存储空间是静态分配的,x 在每次进入函数时都会被初始化为 5。如果没有初始化,那么进入函数时其值是不确定的。MPLINK链接器将使确保不会同时运行的函数中定义为overlay的局部变量共享存储空间。例如,在下面的函数中:
int f (void){ overlay int x = 1; return x;}int g (void){ overlay int y = 2; return y;}DS51288J_CN 第 12页 2005 Microchip Technology Inc.语法说明如果f和g永远不会同时运行,则x和y共享相同的存储空间。但是,在下面的函数中:
int f (void){ overlay int x = 1; return x;}int g (void){ overlay int y = 2; y = f (); return y;}由于f和g可能会同时运行, x和y不能共享相同的存储空间。使用overlay局部变量的优点是,其存储空间是静态分配的,也就是说,在一般情况下,存取这种变量所需要的指令较少(因此所生成代码占用的程序存储空间也较小)。 同时,由于一些变量可以共享相同的存储空间,这些变量所需分配的总的数据存储空间比定义为static时要小。如果MPLINK链接器检测到包含overlay局部变量的递归函数,就会发出错误并中止编译。如果MPLINK链接器检测到,在任意模块中有通过指针进行的函数调用,在任意模块(不一定和上述模块是同一模块)中有存储类别为overlay的局部变量,就会发出错误并中止编译。局部变量默认的存储类别是auto。可以使用关键字static或overlay显式地定义存储类别,或使用-scs(static局部变量)或-sco(overlay局部变量) 命令行选项隐式地定义存储类别。为保持完整性,MPLAB C18也支持-sca命令行选项,该选项允许把局部变量的存储类别显式地定义为auto型。2.3.2static型函数参数函数参数的存储类别可以是auto型或static型。auto型参数存放在软件堆栈中,允许重入。static型参数是全局分配存储空间的,允许直接访问,通常所需代码较少。static型参数仅当编译器工作在非扩展模式(参见第1.2.5节“选择模式”)时有效。函数参数默认的存储类别是auto型。可以使用关键字static显式地定义存储类别或使用-scs命令行选项隐式地定义存储类别。-sco命令行选项也可以隐式地把函数参数的存储类别改变为static型。 2005 Microchip Technology 51288J_CN 第 13页MPLAB® C18 C 编译器用户指南2.4存储限定符除ANSI标准的存储限定符(const和volatile)外,MPLAB C18编译器还引入了far、 near、rom和ram存储限定符。在语句构成上,这些新限定符与标识符之间的约束关系与ANSI C中const和volatile限定符与标识符的关系相同。表2-3表明,定义对象时所指定的存储限定符决定了对象在存储器中的位置。对于一个没有用显式的存储限定符定义的对象,其默认的存储限定符是far和ram。表 2-3:farnear存储限定符指定对象在存储器中的位置rom程序存储器中的任何位置在程序存储器中的地址小于64K存取存储区ram数据存储器中的任何位置(默认)2.4.1near/far数据存储对象far限定符表示变量存储在数据存储器的存储区中,访问这一变量之前需要存储区切换指令。near限定符表示变量存储在快速存取RAM中。2.4.2near/far程序存储对象far限定符表示变量可以位于程序存储器中的任何位置,或者,如果是一个指针变量,那么它能访问64K或者更大的程序存储空间。near限定符表示变量只能位于地址小于64K的程序存储空间,或者,如果是一个指针变量,那么它只能访问不超过64K 的程序存储空间。2.4.3ram/rom限定符因为PICmicro 单片机使用独立的程序存储器和数据存储器地址总线,所以MPLAB
C18需要一些扩展来区分数据是位于程序存储器还是位于数据存储器。ANSI/ISO C标准允许代码和数据位于不同的地址空间,但并不足以定位代码空间中的数据。为此,MPLAB C18引入了rom和ram限定符。 rom限定符表示对象位于程序存储器中,而ram限定符表示对象位于数据存储器中。指针既可以指向数据存储器(ram 指针),也可以指向程序存储器(rom 指针)。一般将指针视为ram 指针,除非定义为rom。指针的长度取决于指针的类型,如表2-4所示。注:写入一个rom变量时,编译器使用 TBLWT 指令;但可能还需要根据所使用的存储器类型编写附加的应用代码。详情请参阅数据手册。表 2-4:数据存储器指针指针长度指针类型例子char * dmp;rom near char * npmp;rom far char * fpmp;长度16 位16 位24 位Near程序存储器指针Far 程序存储器指针DS51288J_CN 第 14页 2005 Microchip Technology Inc.语法说明2.5包含文件搜索路径2.5.1系统头文件在MCC_INCLUDE环境变量中指定的路径和由-I命令行选项指定的目录中搜索用#include
__SMALL__ 若是用-ms命令行选项编译,为常数1。__LARGE__ 若是用-ml命令行选项编译,为常数1。__TRADITIONAL18__ 如果使用非扩展模式(参见第2.5.1节“系统头文件”),为常数1。__EXTENDED18__ 如果使用扩展模式(参见第2.5.1节“系统头文件”),为常数1。2.7与ISO的差异2.7.1整型的提升根据ISO的要求,所有算术运算都以int精度或更高精度进行。在默认情况下,MPLAB C18的算术运算以最大操作数的长度进行,即使两个操作数长度都小于int也不例外。可通过-Oi 命令行选项设定按ISO标准进行运算。例如:unsigned char a, b;unsigned i;a = b = 0x80;i = a + b; /* ISO requires that i == 0x100, but in C18 i == 0 */注意,常数也存在同样的差异。为常数选择的类型是所有合适的类型中长度最小的类型,所谓合适的类型指能无溢出地表示常数值的类型。
2005 Microchip Technology 51288J_CN 第 15页MPLAB® C18 C 编译器用户指南例如:#define A 0x10 /* A will be considered a char unless -Oi specified */#define B 0x10 /* B will be considered a char unless -Oi specified */#define C (A) * (B)unsigned i;i = C; /* ISO requires that i == 0x100, but in C18 i == 0 */
2.7.2数字常量MPLAB C18支持指定十六进制(0x)和八进制(0)值的标准前缀,另外还支持用前缀0b来指定二进制值。例如,数值237可以表示为二进制常数0b11101101。2.7.3字符串常量程序存储器中的数据主要是静态字符串。为此,MPLAB C18自动把所有字符串常量存放在程序存储器中。这种类型的字符串常量是“位于程序存储器的char数组”(const romchar [])。.stringtable段是一个包含所有常量字符串的romdata(参见第2.9.1节“#pragma sectiontype”)段。例如,如下的字符串“hello” 将被置于.stringtable段:strcmppgm2ram (Foo, "hello");由于常量字符串存放在程序存储器中,所以标准字符串处理函数有多种形式。例如,strcpy 函数就有四种形式,允许把数据存储器或程序存储器中的字符串拷贝到数据存储器或程序存储器:/*
* Copy string s2 in data memory to string s1 in data memory */char *strcpy (auto char *s1, auto const char *s2);/*
* Copy string s2 in program memory to string s1 in data * memory */char *strcpypgm2ram (auto char *s1, auto const rom char *s2);/*
* Copy string s2 in data memory to string s1 in program * memory
*/
rom char *strcpyram2pgm (auto rom char *s1, auto const char *s2);/*
* Copy string s2 in program memory to string s1 in program * memory */rom char *strcpypgm2pgm (auto rom char *s1,
auto const rom char *s2);DS51288J_CN 第 16页 2005 Microchip Technology Inc.语法说明当使用MPLAB C18时,程序存储器中的一个字符串表可以定义为:rom const char table[][20] = { "string 1", "string 2", "string 3", "string 4" };rom const char *rom table2[] = { "string 1", "string 2", "string 3", "string 4" };table定义为一个由四个字符串组成的数组,每个字符串的长度为20个字符,所以在程序存储器中占据80个字节。table2定义为一个指向程序存储器的指针数组。* 后面的rom 限定符表示把指针数组也存放在程序存储器中。table2中的所有字符串长度均为9个字节,而数组有4个元素,所以table2在程序存储器中共占用了(9*4+4*2) = 44个字节。然而,对table2 的存取可能会比对table的存取效率要低,这是由于指针需要附加的间接寻址指令。MPLAB C18独立地址空间的一个重要影响是指向程序存储器中数据的指针与指向数据存储器中数据的指针不兼容。只有当两种指针指向兼容类型的对象,而且指向的对象位于相同的地址空间时,两种指针才会兼容。例如,一个指向程序存储器中字符串的指针与一个指向数据存储器中字符串的指针是不兼容的,因为它们指向不同的地址空间。把一个字符串从程序存储器拷贝到数据存储器的函数可以这样编写:void str2ram(static char *dest, static char rom *src){ while ((*dest++ = *src++) != '0') ;}下面的代码利用PICmicro 单片机C库函数把一个位于程序存储器的字符串送到PIC18C452的USART。库函数 putsUSART(const char *str)用来把字符串送到USART,它把指向一个字符串的指针作为其参数,但是此字符串必须位于数据存储器中。rom char mystring[] = "Send me to the USART";void foo( void ){ char strbuffer[21]; str2ram (strbuffer, mystring); putsUSART (strbuffer);}另一种方法是,可以把库函数修改为从程序存储器中读字符串。/* * The only changes required to the library routine are to * change the name so the new routine does not conflict with * the original routine and to add the rom qualifier to the * parameter. */void putsUSART_rom( static const rom char *data ){ /* Send characters up to the null */ do { while (BusyUSART()) ; /* Write a byte to the USART */ putcUSART (*data); } while (*data++);} 2005 Microchip Technology 51288J_CN 第 17页MPLAB® C18 C 编译器用户指南2.7.4stdio.h函数stdio.h中定义的输出函数与ANSI定义的函数形式有所不同,这主要体现在以下几个方面:程序存储器中的数据、浮点型格式支持和MPLAB C18的特定扩展。
函数puts和fputs要求输出字符串存储在程序存储器中。函数vsprintf、vprintf、sprintf、printf、fprintf和vfprintf要求格式字符串存储在程序存储器中。函数vsprintf、vprintf、sprintf、printf、fprintf和vfprintf 不支持浮点型转换说明符。MPLAB C18对24位数据和程序存储器中数据的特定扩展,在《MPLAB® C18 C编译器函数库》的第4.7节中说明。2.8语言的扩展2.8.1匿名结构MPLAB C18支持联合内的匿名结构。匿名结构有以下形式:struct { member-list };
匿名结构定义未命名的对象。匿名结构的成员名不能与定义此匿名结构的作用域内其他名称相同。在此作用域内,可以直接使用成员而无需使用通常的成员访问语法。例如:union foo{ struct { int a; int b; }; char c;} bar;char c;...bar.a = c; /* 'a' is a member of the anonymous structure located inside 'bar' */DS51288J_CN 第 18页 2005 Microchip Technology Inc.语法说明定义了对象或指针的结构不是匿名结构。例如:union foo{ struct { int a; int b; } f, *ptr; char c;} bar;char c:...bar.a = c; /* error */->a = c; /* ok */对 bar.a 的赋值是非法的,因为此成员名与任何特定的对象都没有关联。2.8.2行内汇编MPLAB C18 提供了一个内部汇编器,它使用和MPASM汇编器相似的语法。汇编代码块必须以 _asm 开头,以 _endasm结尾。其语法如下:[label:] [
•使用C 的数制符号表示常数,而不是MPASM汇编器的符号。例如,一个十六进制数应表示为 0x1234,而不是H’1234’。•标号必须包含冒号•不支持变址寻址语法(即[])— 必须指定立即数和访问位(例如指定为CLRF
2,0,而不是CLRF [2]) 2005 Microchip Technology 51288J_CN 第 19页MPLAB® C18 C 编译器用户指南例如:_asm /* User assembly code */ MOVLW 10 // Move decimal 10 to count MOVWF count, 0 /* Loop until count is 0 */ start: DECFSZ count, 1, 0 GOTO done BRA start done:_endasm一般情况下,建议尽量少使用行内汇编。编译器不会优化任何包含行内汇编的函数。如果要编写大段的汇编代码,应使用MPASM汇编器,并用MPLINK 链接器把汇编模块链接到C模块。2.9PRAGMA伪指令2.9.1#pragma sectiontype
段声明pragma伪指令将当前段更改为MPLAB C18分配相关类型的信息的段。
段是位于特定存储器地址的应用程序的一部分。段可以包含代码或数据,可以位于程序存储器或数据存储器中。对于每种存储器,都有两种段类型。•程序存储器-code – 包含可执行指令-romdata – 包含变量和常量•数据存储器-udata– 包含静态分配的未初始化用户变量-idata– 包含静态分配的已初始化用户变量段分为绝对的、已分配的或未分配的。绝对段是指通过段声明pragma伪指令的=address明确赋予了地址的段。已分配段是指已通过链接器描述文件中的SECTION伪指令分配到某个特定段的段。未分配段既不属于绝对段,也不属于已分配段。2.9.1.1语法段伪指令:# pragma udata [属性列表] [section-name [=address]]| # pragma idata [属性列表] [section-name [=address]]| # pragma romdata [overlay] [section-name [=address]]| # pragma code [overlay] [section-name [=address]]属性列表:属性|
属性列表
属性属性:access| overlaysection-name: C 标识符address:整型常量DS51288J_CN 第 20页 2005 Microchip Technology Inc.语法说明2.9.1.2段内容code段包含可执行的内容,位于程序存储器中。romdata段包含分配到程序存储器的数据(一般是用rom限定符定义的变量)。若需要有关romdata用法(例如存储器映射外设) 的更多信息,请参阅《MPASM™汇编器、MPLINK™目标链接器和MPLIB™目标库管理器用户指南
》(DS33014J_CN)。udata段包含静态分配到数据存储器的未初始化全局数据。idata段包含静态分配到数据存储器的已初始化全局数据。
表2-5列出了下例中的每个对象位于哪个段中:rom int ri;rom char rc = 'A';int ui;char uc;int ii = 0;char ic = 'A';void foobar (void){ static rom int foobar_ri; static rom char foobar_rc = 'Z'; ...}void foo (void){ static int foo_ui; static char foo_uc; ...}void bar (void){ static int bar_ii = 5; static char bar_ic = 'Z'; ...} 2005 Microchip Technology 51288J_CN 第 21页MPLAB® C18 C 编译器用户指南表 2-5:rircfoobar_rifoobar_rcuiucfoo_uifoo_uciiicbar_iibar_icfoobarfoobar对象的段位置对象romdataromdataromdataromdataudataudataudataudataidataidataidataidatacodecodecode位置2.9.1.3默认段在MPLAB C18中,每种段类型都存在默认段(见表2-6)。表 2-6:默认段名段类型默认名称_a___filename注:filename 是所生成目标文件的名称。例如,“mcc18 foo.c -fo=foo.o” 将生成一个目标文件,默认代码段名为“.code_foo.o”。指定一个先前声明过的段名将使MPLAB C18重新把相关类型的数据分配到指定的段。段属性必须与先前的声明一致,否则会产生错误(请参见附录D“MPLAB C18诊断”)。不带段名的段pragma伪指令把相关类型的数据分配到当前模块的默认段。例如:/* * The following statement changes the current code * section to the absolute section high_vector */#pragma code high_/*
* The following statement returns to the default code * section */#DS51288J_CN 第 22页 2005 Microchip Technology Inc.语法说明MPLAB C18编译器开始编译一个源文件时,初始化的数据和未初始化的数据都有默认数据段。 这些默认段位于快速存取RAM或非快速存取RAM中,这取决于是否使用了-Oa+选项调用编译器。仅当编译器工作在非扩展模式(参见第1.2.5节“选择模式”)时才使用-Oa+ 命令行选项。当在源代码中遇到一个#pragmaidata[access]name伪指令时,当前未初始化数据段的名称就成为
name,它位于快速存取RAM或非快速存取RAM中,这取决于是否指定了可选的access属性。对于当前已初始化数据段,当遇到一个#pragma idata [access]
name 伪指令时,与上述情况相同。
当对象定义中有显式的初始化时,对象被放入当前已初始化数据段中。当对象定义中没有显式的初始化时,对象被放入当前未初始化数据段中。例如,在以下的代码片段中,i 将放入当前已初始化数据段中,而u将被放在当前未初始化数据段中。int i = 5;int u;void main(void){ ...}如果对象的定义有显式的far 限定符(参见第2.4节“存储限定符”),对象存放在非存取存储区。类似地,显式的near 限定符(参见第2.4节“存储限定符”)告知编译器对象位于存取存储区。如果对象的定义既没有near限定符也没有far 限定符,则编译器将查看是否在命令行中指定了-Oa+选项。2.9.1.4保留段名表2-7列出了供编译器使用保留的段名。
表2-7:_entry_scn_startup_scn_cinit_ATH_aisr_tmp保留段名段名 用途包含到启动代码的跳转。位于RESET向量处。包含启动代码,启动代码将调用应用程序的 main()函数。包含进行数据初始化的启动函数。包含程序存储器中未初始化数据的一份拷贝,启动代码用这个拷贝来进行初始化。包含数学库函数使用的参数、返回值和临时地址。包含非中断服务程序的编译器临时变量。包含中断服务程序isr的编译器临时变量(参见第2.9.2节“#pragma interruptlow fname / #pragma
interrupt fname”)。包含所有常量字符串(参见第2.7.3节“字符串常量”)。默认情况下,包含文件filename的可执行内容。._filename 2005 Microchip Technology 51288J_CN 第 23页MPLAB® C18 C 编译器用户指南表2-7:保留段名(续)段名
.idata__a_filename用途默认情况下,包含文件filename的已初始化数据。默认情况下,包含文件filename的未初始化数据。默认情况下,包含文件filename分配到程序存储器中的数据。包含软件堆栈。包含字符分类函数(参见《MPLAB® C18 C编译器函数库》)的可执行内容。包含库函数Delay100TCYx(参见《MPLAB® C18 C编译)。器函数库》包含库函数Delay10KTCYx(参见《MPLAB® C18 C编译)。器函数库》包含库函数Delay10TCYx(参见《MPLAB® C18 C编译器函数库》)。包含库函数Delay1KTCYx(参见《MPLAB® C18 C编译)。器函数库》包含某些延时函数(参见《MPLAB® C18 C编译器函数)使用的未初始化数据。库》包含某些延时函数(参见《MPLAB® C18 C编译器函数库》)使用的未初始化数据。包含数学函数库(参见《MPLAB® C18 C编译器函数)的可执行内容。库》包含rand和srand函数使用的已初始化数据(参见《MPLAB® C18 C编译器函数库》)。包含位于分区RAM中的特殊功能寄存器(SFR)。包含位于快速存取RAM中的特殊功能寄存器。包含标准函数库输出函数中的外设输出函数的可执行内容。包含数据转换函数(参见《MPLAB® C18 C编译器函数库》)。的可执行内容包含存储器和字符串操作函数(参见《MPLAB® C18 C编)。译器函数库》包含软件UART函数(参见《MPLAB® C18 C编译器函数)。的可执行内容库》包含软件UART函数(参见《MPLAB® C18 C编译器函数库》)。使用的未初始化数据。.config_address_filename包含为给定address和filename指定的配置设置。.stack
CTYPE
D100TCYXCODE
D10KTCYXCODE
D10TCYXCODE
D1KTCYXCODE
DELAYDAT1
DELAYDAT2
PROG
SEED_DATA
SFR_BANKED*
SFR_UNBANKED*
STDIOSTDLIB
STRING
UARTCODE
UARTDATA
*代表通配符。DS51288J_CN 第 24页 2005 Microchip Technology Inc.语法说明2.9.1.5段属性#pragma sectiontype 伪指令可以选择包含两种段属性 — access或 overlay。2.9.1.5.1accessaccess 属性告知编译器把指定的段放入数据存储器的存取区中(参见器件数据手册(DS39500A_CN),以获得更多关于存取或《PICmicro® 18C MCU系列参考手册》数据存储区的信息)。带有access属性的数据段将放入在链接器描述文件中定义为ACCESSBANK的存储区。这些存储区可以通过指令的存取位来访问,也就是说,不需要选择存储区(参见器件数据手册)。access 段中的变量必须用near关键字定义。例如:#pragma udata access my_access/* all accesses to these will be unbanked */near unsigned char av1, av2;
2.9.1.5.2overlayoverlay 属性允许其他段与此段位于相同的物理地址。通过把变量放入相同的存储单元可节约存储空间(只要两个变量不会被同时使用)。 overlay 属性可与access 属性一起使用。若要使两个段共享相同的存储空间,必须满足如下四个条件:1.两个段必须位于不同的源文件中。2.两个段必须有相同的名称。3.如其中一个段已指定access 属性,那么也必须对另一个段指定access 属性。4.如果其中一个段已指定绝对地址,那么也必须对另一个段指定相同的绝对地址。具有overlay属性的代码段可以位于与其他 overlay代码段重叠的地址中。例如:file1.c:#pragma code overlay my_overlay_scn=0x1000void f (void)
{ ...}file2.c:#pragma code overlay my_overlay_scn=0x1000void g (void)
{ ...} 2005 Microchip Technology 51288J_CN 第 25页MPLAB® C18 C 编译器用户指南具有overlay属性的数据段可以位于与其他overlay数据段重叠的地址中。这一特征是很有用的,可允许确定不会同时使用的多个变量使用同一个数据存储区。例如:file1.c:#pragma udata overlay my_overlay_data=0x1fc/* 2 bytes will be located at 0x1fc and 0x1fe */int int_var1, int_var2;
file2.c:#pragma udata overlay my_overlay_data=0x1fc/* 4 bytes will be located at 0x1fc */long long_var;更多关于处理overlay段的信息,可参阅《MPASM™汇编器、MPLINK™目标链接器和MPLIB™目标库管理器用户指南
》(DS33014J_CN)。2.9.1.6定位代码在 #pragma code 伪指令后生成的所有代码将被分配到指定的代码段,直到遇到下一个 #pragma code 伪指令。绝对代码段允许将代码分配到一个特定的地址。例如:#pragma code my_code=0x2000将把代码段
my_code分配到程序存储器地址0x2000。链接器会强制将代码段放入程序存储区;然而,代码段也可以位于指定的存储区。可以用链接器描述文件中的SECTION 伪指令把一个段分配到特定的存储区。下面链接器描述文件中的伪指令把代码段my_code1 分配到存储区page1:SECTION NAME=my_code1 ROM=page12.9.1.7定位数据对于MPLAB C18编译器,数据可以放入数据存储器或者程序存储器。如果没有用户提供的附加代码,片内程序存储器中的数据只能读不能写。如果没有用户提供的附加代码,片外程序存储器中的数据一般是只能读或者只能写。例如,下面的语句为静态分配的未初始化数据(udata)声明了一个位于绝对地址0x120的段:#pragma udata my_new_data_section=0x120rom 关键字告知编译器应该将变量放入程序存储器。编译器会把这个变量分配到当前的romdata 型段。例如:#pragma romdata const_table
const rom char my_const_array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};/* Resume allocation of romdata into the default section */#pragma romdata链接器会强制将romdata段放入程序存储区,将udata和 idata段放入数据存储区;然而,数据段也可以位于指定的存储区。可以使用链接器描述文件中的SECTION 伪指令把一个段分配到一个特定的存储区。下面的语句将把udata段my_data 分配到存储区gpr1:SECTION NAME=my_data RAM=gpr1DS51288J_CN 第 26页 2005 Microchip Technology Inc.语法说明2.9.2#pragma interruptlow fname /#pragma interrupt fnameinterrupt pragma伪指令将函数声明为高优先级的中断服务程序;interruptlow
pragma伪指令将函数声明为低优先级的中断服务程序。中断将暂停执行正在运行的应用程序,保存当前的现场信息并把控制权转交给中断服务程序,以便对事件进行处理。执行完中断服务程序后,恢复先前的现场信息,继续正常执行应用程序。对于中断来说,可保存和恢复的最小现场是 WREG、BSR 和
STATUS。高优先级中断使用影子寄存器保存和恢复最小现场,而低优先级中断则使用软件堆栈保存和恢复最小现场。因此,高优先级中断可通过一个快速“中断返回”来结束,而低优先级中断则通过一个一般“中断返回”来结束。通过软件堆栈保存现场的每个字节需要两条MOVFF 指令,WREG例外,它需要一条MOVWF指令和一条MOVF指令;因此,要保存最小现场,一个低优先级中断要比一个高优先级中断多开销10个字。
中断服务程序使用一个临时数据段,这个段和一般C函数所使用的段是不同的。中断服务程序中,在表达式求值过程中所需要的所有临时数据都被分配到此段,而且此段不与其他函数(包括其他中断函数)的临时地址重叠。中断pragma伪指令允许给中断临时数据段命名。如果没有给这个段命名,将会在名为fname_tmp的udata 段中生成编译器临时变量。例如:void foo(void);...#pragma interrupt foovoid foo(void){ /* perform interrupt function here */}中断服务程序foo的编译器临时变量将被放在udata 段foo_tmp中。 2005 Microchip Technology 51288J_CN 第 27页MPLAB® C18 C 编译器用户指南2.9.2.1语法中断伪指令: # pragma interrupt function-name [tmp-section-name][save=save-list][nosave=nosave-list]| # pragma interruptlow function-name [tmp-section-name][save=save-list][nosave=nosave-list]save-list:location-specifier| save-list, location-specifiernosave-list:location-specifier| nosave-list, location-specifierlocation-specifier:symbol-name| section("section-name")function-name:C 标识符 — 命名作为中断服务程序的C函数。tmp-section-name:C 标识符 — 命名分配中断服务程序临时数据的段。symbol-name:C 标识符 — 命名中断处理后恢复的变量。section-name:C 标识符,与一般标识符的不同之处是第一个字符可以是一个点(.) ——命名中断处理后恢复的段。2.9.2.2中断服务程序MPLAB C18中断服务程序与任何其他C 函数一样,也可以有局部变量并能访问全局变量;然而,中断服务程序必须定义为没有参数和返回值,这是因为响应硬件中断的中断服务程序是异步调用的。既可以被中断服务程序访问也可以被其他函数访问的全局变量应定义为volatile。中断服务程序只能通过硬件中断调用,而不能从其他C 函数中调用。中断服务程序使用中断返回指令(RETFIE)退出中断函数,而不是使用一般的 RETURN 指令。不恢复现场使用快速RETFIE指令退出中断服务程序,会破坏WREG、BSR 和 STATUS寄存器的值。DS51288J_CN 第 28页 2005 Microchip Technology Inc.语法说明2.9.2.3中断向量MPLAB C18不自动把中断服务程序放在中断向量处。通常将GOTO 指令放在中断向量处,从而把控制权转交给相应的中断服务程序。例如:#include
* For PIC18 devices the low interrupt vector is found at * 00000018h. The following code will branch to the * low_interrupt_service_routine function to handle * interrupts that occur at the low vector.
*/#pragma code low_vector=0x18void interrupt_at_low_vector(void){ _asm GOTO low_isr _endasm}#pragma code /* return to the default code section */#pragma interruptlow low_isrvoid low_isr (void){ /* ... */}/*
* For PIC18 devices the high interrupt vector is found at * 00000008h. The following code will branch to the * high_interrupt_service_routine function to handle * interrupts that occur at the high vector. */#pragma code high_vector=0x08void interrupt_at_high_vector(void){ _asm GOTO high_isr _endasm}#pragma code /* return to the default code section */#pragma interrupt high_isrvoid high_isr (void){ /* ... */}完整的例子,参见第5章“应用实例”。2.9.2.4中断现场保护默认情况下,MPLAB C18保存编译器管理的资源(参见第3.4节“编译器管理的资源”), save=子句允许函数保存和恢复其他任意符号。
要保存一个名为myint的用户定义全局变量,使用如下pragma伪指令:#pragma interrupt high_interrupt_service_routine save=myint 2005 Microchip Technology 51288J_CN 第 29页MPLAB® C18 C 编译器用户指南除了变量,也可以在save=子句中指定整个数据段。比如,要保存一个名为mydata的用户定义段,使用如下pragma伪指令:#pragma interrupt high_interrupt_service_routine
save=section("mydata")上述所有例子都是保存单个值,也可以使用同一个save=限定符保存多个变量和段。如果一个中断服务程序使用了myint 变量和mydata 段,则应该在中断pragma伪指令中使用save=myint, section ("mydata") 限定符来保存它们 。例如:#pragma interrupt isr save=myint, section("mydata")2.9.2.5指定资源仅用于中断由于某些应用程序仅将编译器保存的存储单元用于中断现场,因此不必主动地保存和恢复这些存储单元的值。nosave=子句允许将编译器管理的资源指定为仅用于中断服务程序 ,因此可以不跨中断主动保存这些资源。对于高优先级中断,nosave=子句中指定的存储地址可以是如下之一: FSR0、TBLPTR、TBLPTRU、TABLAT、PCLATH、PCLATU、PROD、section(“.tmpdata”)或section(“MATH_DATA”)。对于低优先级中断,nosave=子句可以指定高优先级中断的任一存储地址或以下寄存器之一:WREG、BSR或 STATUS。而且,当为扩展模式编译时,编译器还接受__RETVAL0作为MATH_DATA段的参考。例如,要指定将TBLPTR和TABLAT寄存器仅用于高优先级中断函数foo的现场,因而不需要由编译器保存和恢复这两个寄存器,将使用下面的pragma伪指令:#pragma interrupt foo nosave=TBLPTR, TABLAT2.9.2.6中断响应时间从中断发生到执行中断服务程序第一条指令之间的时间就是中断响应时间。中断响应时间受到下面三个因素的影响:1.处理器中断处理时间: 处理器识别中断并跳转到中断向量的首地址所用的时间。要确定这个值的大小,可以参考相应单片机的数据手册,以获得该型号单片机及所使用中断源方面的信息。2.中断向量执行:执行中断向量处、跳转到中断服务程序的代码所用的时间。 预处理的时间:MPLAB C18 保存编译器管理的资源和save= 列表中的数据所用的时间。2.9.2.7嵌套中断低优先级中断可以嵌套,这是因为所使用寄存器的值保存在软件堆栈中。任一时刻只能有一个高优先级中断服务程序的实例处于运行状态,因为高优先级中断服务程序使用单级深度硬件影子寄存器。
如果需要嵌套低优先级中断,可以在中断服务程序的开头部分加上一条置位GIEL 位的语句。详情请参阅单片机的数据手册。DS51288J_CN 第 30页 2005 Microchip Technology Inc.语法说明2.9.3#pragma tmpdata [section-name]tmpdata pragma伪指令更改编译器在其中创建其临时变量的当前段。默认情况下,MPLAB C18在名为.tmpdata的段中创建一般函数(非ISR)使用的临时变量。下面的语句将当前临时数据段更改为名为user_tmp的段。这条语句之后的所有非ISR函数将user_tmp段用于编译器生成的临时变量,直到编译器解析了另外一条#pragma tmpdata伪指令。#pragma tmpdata user_tmp下面这条语句将临时数据段复位为默认的临时数据段.tmpdata。#pragma tmpdata注:当编译器为ISR保护现场时,它不会保存由#pragma tmpdata伪指令创建的任何临时数据段,而仅会保存默认临时数据段.tmpdata。为了告知编译器不要增加.tmpdata段的现场保护开销,可在中断pragma伪指令中使用nosave=子句(参见第2.9.2节“#pragma interruptlow
fname / #pragma interrupt fname”)。语法2.9.3.1tmpdata伪指令: #pragma tmpdata [section-name]section-name:C 标识符——命名编译器应在其中创建其临时变量的临时数据段。2.9.3.2ISR函数和非ISR函数共用临时数据段可通过tmpdata pragma伪指令来使中断服务程序和非中断函数共用临时数据。在下面的例子中,中断服务程序isr和非中断函数increment的编译器临时变量都存放在udata段isr_tmp中。void increment (int counter);void isr (void);#pragma interrupt isr nosave=section(".tmpdata")void isr (void){ static int foo = 0; ... increment (foo); ...}#pragma tmpdata isr_tmpvoid increment (int counter){ ...}#pragma tmpdata 2005 Microchip Technology 51288J_CN 第 31页MPLAB® C18 C 编译器用户指南注:当编译器为ISR保护现场时,编译器将自动保存默认临时数据段.tmpdata,即使tmpdata pragma伪指令为ISR调用的函数指定了不同的临时数据段。为了告知编译器不要增加.tmpdata段的现场保护开销,可在中断pragma伪指令中使用nosave=子句(参见第2.9.2节“#pragma interruptlow fname / #pragma interrupt
fname”)。多个高优先级中断2.9.3.3由于每次仅处理一个高优先级中断,因此多个高优先级中断可使用同一个临时数据段,而且每个ISR调用的函数也可共用这同一个临时数据段。在下面的例子中,高优先级ISR和两个ISR调用的increment函数的编译器生成临时变量共用段isr_tmp。void increment (int counter);void isr1 (void);void isr2 (void);#pragma interrupt isr1 isr_tmp nosave=section(".tmpdata")void isr1 (void){ static int foo = 0; ... increment (foo); ...}#pragma interrupt isr2 isr_tmp nosave=section(".tmpdata")void isr2 (void){ static int foo = 0; ... increment (foo); ...}#pragma tmpdata isr_tmpvoid increment (int counter){ ...}#pragma tmpdataDS51288J_CN 第 32页 2005 Microchip Technology Inc.语法说明2.9.3.4中断嵌套中断嵌套额外增加了临时数据处理的复杂性。在嵌套中断情况下,必须注意一定要保护中断服务程序使用的临时数据。下面的例子表明,在进入中断服务程序时,必须保存用于中断服务程序中临时数据的段 。void increment (int counter);void isr1 (void);void isr2 (void);#pragma interrupt isr1 isr_tmp save=section("isr_tmp") nosave=section(".tmpdata")void isr1 (void){ static int foo = 0; ... increment (foo); ...}#pragma interruptlow isr2 isr_tmp save=section("isr_tmp") nosave=section(".tmpdata")void isr2 (void){ static int foo = 0; = 1; ... increment (foo); ...}#pragma tmpdata isr_tmpvoid increment (int counter){ ...}#pragma tmpdata2.9.4#pragma varlocate bank variable-name#pragma varlocate
"section-name" variable-namevarlocate pragma伪指令告知编译器在链接时将变量存放在哪里,这使编译器能更高效地进行存储区切换。varlocate说明不是由编译器或链接器强制执行的。应在链接器描述文件中把包含变量的段显式地分配到正确的存储区,或者在定义这些变量的模块中把包含变量的段分配到绝对段。2.9.4.1语法变量定位伪指令
: # pragma varlocate bank variable-name[, ]| # pragma varlocate "section-name" variable-name[,
<]bank:整型常量variable-name:C 标识符section-name:C 标识符 2005 Microchip Technology 51288J_CN 第 33页MPLAB® C18 C 编译器用户指南2.9.4.2使用 # pragma varlocate bank variable-name的例子在一个文件中, 把c1 和 c2显式地分配到存储区1。#pragma udata bank1=0x100signed char c1;signed char c2;在第二个文件中,编译器被告知c1 和c2 都位于存储区1。#pragma varlocate 1 c1extern signed char c1;#pragma varlocate 1 c2extern signed char c2;void main (void){ c1 += 5; /* No MOVLB instruction needs to be generated here. */ c2 += 5;}当在第二个文件中使用c1 和c2时, 编译器知道这两个变量都在相同的存储区内,当在c1后紧接着使用c2时就不需要再生成另外一条 MOVLB 指令了。2.9.4.3使用# pragma varlocate
"section-name"
variable-name
的例子在一个文件中, c3 和 c4都创建在udata 段 my_section中。#pragma udata my_sectionsigned char c3;signed char c4;#pragma udata在第二个文件中,编译程序被告知c3 和c4 都位于udata段my_section中。#pragma varlocate "my_section" c3, c4extern signed char c3;extern signed char c4;void main (void){ c3 += 5; /* No MOVLB instruction needs to be generated here. */ c4 += 5;
}当在第二个文件中用到c3 和c4时,编译器知道这两个变量都在相同的段中,当在c3后紧接着使用c4时就不需要再生成另外一条 MOVLB 指令了。2.9.5#pragma config#pragma config伪指令指定针对具体处理器的配置设置(即配置位),这些配置设置将由应用程序使用。
可用多条#pragma config伪指令来指定配置设置。MPLAB C18验证指定的配置设置对于编译时指定的处理器来说是否有效。如果任何一条#pragma config伪指令中都没有指定配置字节中的一个给定设置,则与该设置有关的位将默认为未编程的值。DS51288J_CN 第 34页 2005 Microchip Technology Inc.语法说明对于用#pragma config伪指令为其指定设置的每个配置字节来说,编译器为其生成一个名为.config_address_filename的绝对romdata段,其中address为配置字节地址的十六进制表示,filename为生成的目标文件的名字。例如,如果位于地址0x300001的配置字节指定一个配置设置,并用命令行选项mcc18 foo.c
-fo=foo.o来编译源文件,将创建一个名为.config_300001_foo.o的romdata段。2.9.5.1语法pragma-config伪指令: # pragma config setting-listsetting-list: setting | setting-list, settingsetting: setting-name = value-namesetting-name和value-name是特定于器件的,可通过使用 --help-config命令行选项来确定。另外,PIC18 Configuration Settings Addendum(DS51537)中给出了每个器件的有效设置和相关值。2.9.5.2示例下面的例子说明了如何使用#pragma config伪指令。这个例子完成如下功能:•使能看门狗定时器•将看门狗后分频器分频比设置为1:128•选择HS振荡器#pragma config WDT = ON, WDTPS = 128#pragma config OSC = HS...void main (void){...} 2005 Microchip Technology 51288J_CN 第 35页MPLAB® C18 C 编译器用户指南2.10针对处理器的头文件针对处理器的头文件是包含特殊功能寄存器外部声明的C文件,特殊功能寄存器在寄存器定义文件中定义(参见第2.11节“针对处理器的寄存器定义文件”)。例如,在PIC18C452的针对处理器头文件中,PORTA 声明为:extern volatile near unsigned char PORTA;和:extern volatile near union { struct { unsigned RA0:1; unsigned RA1:1; unsigned RA2:1; unsigned RA3:1; unsigned RA4:1; unsigned RA5:1; unsigned RA6:1; } ; struct { unsigned AN0:1; unsigned AN1:1; unsigned AN2:1; unsigned AN3:1; unsigned T0CKI:1; unsigned SS:1; unsigned OSC2:1; } ; struct { unsigned :2; unsigned VREFM:1; unsigned VREFP:1; unsigned :1; unsigned AN4:1; unsigned CLKOUT:1; } ; struct { unsigned :5; unsigned LVDIN:1; } ;} PORTAbits ;第一个声明指定PORTA 是一个字节(unsigned char)。由于变量是在寄存器定义文件中定义的,因此需要 extern 修饰符。volatile 修饰符告知编译器不能假定
PORTA 能保留赋给它的值。near 修饰符指定了端口位于快速存取RAM中。第二个声明指定PORTAbits是可位寻址的匿名结构的联合(参见第2.8.1节“匿名结构”)。特殊功能寄存器中的每一位可能有不只一种功能(因此会有不只一个名称),因此联合中对于同一个寄存器有多个结构定义。所有结构定义中的各位分别针对寄存器中相同的位。如果一个位只有一个功能,那么在其他结构定义中,这一位只是被填充。例如,在第三和第四个结构中,PORTA的第1位和第2位只是被填充,因为它们只有两个名称;而第6位有四个名称,在每个结构中都指定了第6位。DS51288J_CN 第 36页 2005 Microchip Technology Inc.语法说明可用以下任一语句使用特殊功能寄存器PORTA:PORTA = 0x34; /* Assigns the value 0x34 to the port */0 = 1; /* Sets the AN0 pin high */0 = 1; /* Sets the RA0 pin high, same as above statement */
除了寄存器声明外,针对处理器的头文件还定义了行内汇编宏。这些宏代表某些PICmicro 单片机指令,应用程序可能需要从C代码中执行这些指令。尽管这些指令可以作为行内汇编指令引用,但为方便起见,提供了C宏(见表2-8)。为了使用针对处理器的头文件, 应该在应用源代码中包含所使用器件的头文件(例如,如果使用 PIC18C452,用#include
例如,在PIC18C452针对处理器的寄存器定义文件中,PORTA 定义为:SFR_UNBANKED0 UDATA_ACS H'f80'PORTAPORTAbits RES 1 ; 0xf80第一行指定PORTA 所在的数据寄存器存储区和这个存储区的起始地址。PORTA 有两个标号,PORTAbits 和PORTA,都指向同一个地址(本例中是0xf80)。DS51288J_CN 第 38页 2005 Microchip Technology ® C18 C 编译器用户指南第3章 运行时模型本章讲述MPLAB C18编译器的运行时模型及运行所遵循的各项前提,包括MPLAB
C18编译器如何使用PIC18 PICmicro单片机的资源等信息。3.1存储模型MPLAB C18 同时为小存储模型和大存储模型(见表3-1)提供全部库支持。 使用-ms命令行选项选择小存储模型,使用-ml命令行选项选择大存储模型。如果不使用这两个选项,默认使用小存储模型。表3-1:存储模型小存储模型大存储模型存储模型概括命令行选项-ms-ml默认的ROM范围限定符nearfar指向程序空间指针的长度16 位24 位小存储模型和大存储模型之间的区别在于指向程序存储器的指针的长度不同。在小存储模型中,指向程序存储器的函数指针和数据指针都是16 位的。因此在小存储模型中,指针被限定为只能在程序存储器的前64K范围内寻址。大存储模型使用24 位长度的指针。若应用程序要使用大于64K的程序存储器地址,必须使用大存储模型。定义一个指向程序空间的指针时,可用 near 或 far限定符逐项改变存储模型的设置。指向near存储器的指针长度为16 位,和在小存储模型中一样;而指向far 存储器的指针长度为24 位,和在大存储模型中一样。
下面的例子创建一个指向程序存储器的指针,即使在使用小存储模型时,它都能寻址达到和超过64K的程序存储空间1:far rom *pgm_ptr;下面的例子创建了一个函数指针,即使在使用小存储模型时,它都能寻址达到和超过64K的程序存储空间2:far rom void (*fp) (void);如果项目中的所有文件并非都使用相同的存储模型,那么所有指向程序存储器的全局指针都应该用near 或 far限定符显式地定义,这样才能在所有模块中正确地访问这些指针。小存储模型和大存储模型都可以使用MPLAB C18的预编译库。1.在小存储模型程序中使用far数据指针后,TBLPTRU字节必须由用户清除,MPLAB C18不会清除这个字节。2.在小存储模型程序中使用far函数指针后,PCLATU字节必须由用户清除,MPLAB C18不会清除这个字节。 2005 Microchip Technology 51288J_CN 第 39页MPLAB® C18 C编译器用户指南3.2关于调用的约定MPLAB C18的软件堆栈是向上生长的堆栈数据结构,编译器把函数参数和auto存储类别的局部变量放入软件堆栈中。软件堆栈与PICmicro单片机用于保存函数调用返回地址的硬件堆栈不同。图3-1给出了一个软件堆栈的实例。图 3-1:软件堆栈实例未使用的堆栈单元 地址递增函数现场(局部变量和参数)FSR1 (堆栈指针)FSR2 (帧指针)堆栈指针(FSR1)始终指向下一个可用的堆栈地址。MPLAB C18 使用FSR2 作为帧指针,这样可以快速访问局部变量和参数。函数被调用时,其基于堆栈的参数以自右向左的顺序压入堆栈,然后再调用这个函数。进入函数时,最左端的函数参数位于软件堆栈的顶端。 图3-2显示了函数调用前的软件堆栈。图 3-2:函数调用前的软件堆栈示例未使用的堆栈单元函数参数 1函数参数 2地址递增FSR1(堆栈指针)...函数参数 n函数现场FSR2 (帧指针)3.2.1非扩展模式的约定对于非扩展模式,帧指针指向堆栈中把基于堆栈的参数和基于堆栈的局部变量分隔开的地址。基于堆栈的参数位于帧指针的下方(自帧指针负偏移量),而基于堆栈的局部变量位于帧指针的上方(自帧指针正偏移量)。刚进入C函数时,被调用函数把FSR2 的值压入堆栈,并把FSR1的值复制到FSR2,从而保存了调用函数的现场并初始化了当前函数的帧指针。然后函数基于堆栈的局部变量的总长度被加到堆栈指针,并为这些变量分配堆栈空间。基于堆栈的局部变量和基于堆栈的参数则根据其相对于帧指针的偏移量来引用。图3-3显示在非扩展模式下调用一个C函数后的软件堆栈。DS51288J_CN 第 40页 2005 Microchip Technology Inc.运行时模型图 3-3:非扩展模式下调用一个C函数后的软件堆栈实例未使用的堆栈单元局部变量 n...局部变量 2局部变量 1地址递增前一个帧指针被调用函数的参数 1被调用函数的参数 2...被调用函数的参数 n被调用函数的可变长度参数调用函数的现场FSR2 (帧指针)FSR1 (堆栈指针)3.2.2扩展模式约定对于扩展模式,帧指针指向函数指定参数中最靠右边的参数的低字节。局部变量和参数都位于位于帧指针的上方(自帧指针非负偏移量),允许函数通过立即数偏移量寻址访问这些局部变量和参数。进入被调用函数时,FSR2的值被保存到堆栈,FSR1的值被复制到FSR2,且从FSR2中减去指定参数的长度和保存的帧指针的长度。这样保存了调用函数的帧指针并初始化了当前函数的帧指针。然后,函数局部变量的总长度被加到FSR1,为这些局部变量分配空间。图3-4显示了在扩展模式下调用一个C函数后的软件堆栈。 2005 Microchip Technology 51288J_CN 第 41页
发布者:admin,转转请注明出处:http://www.yc00.com/num/1702025114a1168798.html
评论列表(0条)