新闻中心

EEPW首页>嵌入式系统>设计应用> PIC 单片机 C 语言编程简介(3)

PIC 单片机 C 语言编程简介(3)

作者: 时间:2016-11-22 来源:网络 收藏
例 11-5C 语言中断函数举例

本文引用地址://m.amcfsurvey.com/article/201611/319597.htm

PICC 会自动加入代码实现中断现场的保护,并在中断结束时自动恢复现场,所以编程

员无需象编写汇编程序那样加入中断现场保护和恢复的额外指令语句。但如果在中断服务程

序中需要修改某些全局变量时,是否需要保护这些变量的初值将由编程员自己决定和实施。

用 C 语言编写中断服务程序必须遵循高效的原则:

&O1540;代码尽量简短,中断服务强调的是一个“快”字。

&O1540;避免在中断内使用函数调用。虽然 PICC 允许在中断里调用其它函数,但为了解决

递归调用的问题,此函数必须为中断服务独家专用。既如此,不妨把原本要写在其

它函数内的代码直接写在中断服务程序中。

&O1540;避免在中断内进行数学运算。数学运算将很有可能用到库函数和许多中间变量,就

算不出现递归调用的问题,光在中断入口和出口处为了保护和恢复这些中间临时变

量就需要大量的开销,严重影响中断服务的效率。

中档系列 PIC单片机的中断入口只有一个,因此整个程序中只能有一个中断服务函数。

11.6.5标准库函数

PICC 提供了较完整的 C 标准库函数支持,其中包括数学运算函数和字符串操作函数。

在程序中使用这些现成的库函数时需要注意的是入口参数必须在 bank0 中。

如果需要用到数学函数,则应在程序前“#include ”包含头文件;如果要使

用字符串操作函数,就需要包含“#include ”头文件。在这些头文件中提供了函数

类型的声明。通过直接查看这些头文件就可以知道 PICC 提供了哪些标准库函数。

C语言中常用的格式化打印函数“printf/sprintf”用在单片机的程序中时要特别谨慎。

printf/sprintf 是一个非常大的函数,一旦使用,你的程序代码长度就会增加很多。除非是在

编写试验性质的代码,可以考虑使用格式化打印函数以简化测试程序;一般的最终产品设计

都是自己编写最精简的代码实现特定格式的数据显示和输出。本来,在单片机应用中输出的

数据格式都相对简单而且固定,实现起来应该很容易。

对于标准 C 语言的控制台输入(scanf)/输出(printf)函数,PICC 需要用户自己编写

其底层函数 getch()和 putch()。在单片机系统中实现 scanf/printf 本来就没什么太多意义,如

果一定要实现,只要编写好特定的getch()和 putch()函数,你就可以通过任何接口输入或输

出格式化的数据。


11.7

PICC 定义特殊区域值

PICC 提供了相关的预处理指令以实现在原程序中定义单片机的配置字和标记单元。

11.7.1定义工作配置字

在原程序中定义 PIC 单片机工作配置字的重要性在前面章节中已经阐述。在用 PICC 写


程序时同样可以在 C 原程序中定义,具体方式如下:

__CONFIG (HS & UNPROTECT & PWRTEN & BORDIS & WDTEN);

上面的关键词“__CONFIG”(注意前面有两个下划线符)专门用于是芯片配置字的设

定,后面括号中的各项配置位符号在特定型号单片机的头文件中已经定义(注意不是pic.h

头文件),相互之间用逻辑“与”操作符组合在一起。这样定义的配置字信息最后将和程序

代码一起放入同一个 HEX 文件。

在这里列出了适用于16F7x系列单片机配置位符号预定义,其它型号或系列的单片机

配置字定义方式类似,使用前查阅一下对应的头文件即可。


#define RC

#define HS


0x3FFF // RC 振荡

0x3FFE // HS 模式

#define XT

#define LP


0x3FFD // XT 模式

0x3FFC // LP 模式


#define WDTEN0x3FFF //看门狗打开


#define WDTDIS

#define PWRTEN


0x3FFB //看门狗关闭

0x3FF7 //上电延时定时器打开


#define PWRTDIS0x3FFF//上电延时定时器关闭

#define BOREN0x3FFF //低电压复位允许


#define BORDIS


0x3FBF //低电压复位禁止


#define UNPROTECT0x3FFF//没有代码保护

#define PROTECT0x3FEF//程序代码保护

例 11-6 头文件预定义的配置信息符号

11.7.2定义芯片标记单元

PIC 单片机中的标记单元定义可以用下面的__IDLOC(注意前面有两个下划线符)预处

理指令实现,方法如下:

__IDLOC (1234);

其特殊之处是括号内的值全部为 16 进制数,不需要用“0x”引导。这样上面的定义就设定

了标记单元内容为 01020304。

11.8


MPLAB-IDE 中实现 PICC 的编译选项设置

在 11.3 节中已经介绍了如何实现 PICC 和 MPLAB-IDE 开发平台的挂接。一旦项目建立


成功、程序编写完成后即可以通过 MPLAB 环境下的项目管理工具实现程序的编译、连接和

调试。它们的含义分别

是:


-项目维护(Make):MPLAB 检查项目中的原程序文件,只编译那些在上次编

译后又被修改过的原程序,最后进行连接;

-项目重建(Build All):项目中的所有原程序文件,不管是否有修改,都将被

重新编译一次,最后进行连接。

也可以通过 Project 菜单选择“Make”或“Build All”实现项目编译。不管采用何种方

式,在启动编译过程前一般都要设定一些编译选项。

11.8.1选择单片机型号

在选择 PICC 作为语言工具并建立了项目后,同样通过菜单项 Configure&O1616;Select Device

在 MPLAB 环境中选择具体单片机型号。请回顾一下例 11-1 的代码,我们在原程序一开始

使用了“#include ”实现了相关单片机的一些预定义符号的直接引用,但没有具体指

明是哪一个型号。实际上,“pic.h”头文件只是一个简单的管理工具(条件判别),它会按照

MPLAB 所选择的特定型号的单片机,把真正对应的头文件包含进来。有兴趣者可以直接用

文本编辑工具打开 pic.h 文件查看其是如何根据不同的单片机型号包含对应的头文件。

这样对编程员而言,程序中只需加上一句“#include ”即可。

11.8.2PICC 普通编译选项(General)设定

参考第三章3.2.7 节的内容和图 3-20的指示说明,启动编译选项设定对话框。在使用

PICC 语言工具时对话框的内容和用 MPAMS 汇编工具相比完全不同。图 11-3 为 PICC 编译

环境下普通选项设定的界面。

在此界面中用户唯一能改变的是编译器查找头文件时的指定路径(Include Path),实际

上如果编译器安装没有问题,在此界面中这些普通选项的设定无需任何改动,编译器会自动

到缺省认定的路径中(编译器安装后的相关路径)查找编译所需的各类文件。

%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/9.jpg" src="//m.amcfsurvey.com/ec/article/201611/file:///F:/data/%C3%83%C2%8F%C3%83%C2%82%C3%83%C2%94%C3%83%C2%98/PIC%C3%82%C2%B5%C3%82%C2%A5%C3%83%C2%86%C3%82%C2%AC%C3%82%C2%BB%C3%83%C2%BAC%C3%83%C2%93%C3%83%C2%AF%C3%83%C2%91%C3%83%C2%94%C3%82%C2%B1%C3%83%C2%A0%3Cwbr%3E%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/9.jpg" />%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/10.jpg" src="//m.amcfsurvey.com/ec/article/201611/file:///F:/data/%C3%83%C2%8F%C3%83%C2%82%C3%83%C2%94%C3%83%C2%98/PIC%C3%82%C2%B5%C3%82%C2%A5%C3%83%C2%86%C3%82%C2%AC%C3%82%C2%BB%C3%83%C2%BAC%C3%83%C2%93%C3%83%C2%AF%C3%83%C2%91%C3%83%C2%94%C3%82%C2%B1%C3%83%C2%A0%3Cwbr%3E%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/10.jpg" />

图 11-3PICC 普通选项设定图 11-4PICC 全局选项设定

11.8.3PICC 全局选项设定(PICC Global)

全局选项将影响项目中所有 C 和汇编原程序的编译,详细的设定内容见图 11-4。其中

必须关注的有:

&O1540;Compile for MPLAB ICD:如果你准备用 ICD 调试 C 语言编译后的代码,那么此项

就必须打钩选中。这样编译后的结果就能保证ICD 本身使用的芯片资源(一小部

分的程序和数据空间)不被应用程序所占用。

&O1540;Treat ‘char’ as signed:为了提高编译后的代码效率,PICC 缺省认定‘char’型变量也

是无符号数。如果在设计中需要使用带符号的‘char’型变量,此项就应该被选中。

&O1540;Floating point ‘double’ width:同样为了提高编译后的代码效率,PICC缺省认定

‘double’型的双精度浮点数变量的实现长度为 24 位(等同于普通 float 型浮点数)。

在这里可以选择使其长度达 32 位。这样数值计算的精度将得到提高,但代码长度

将增加,计算速度也会降低,所以请在权衡利弊后作出你自己的决定。

11.8.4C 编译器选项设定(PICC Compiler)

项目中所有的 C 原程序都将通过 C 编译器编译成机器码,这些选项决定了 C 编译器是

如何工作的。所有选项又分为两组:普通选项(General)和高级选项(Advanced),分别见

图 11-5A 和 11-5B。

C 编译器的普通选项最重要的就是针对代码优化的设定。如果没有特殊原因,应该设定

全局优化级别为 9 级(最高级别优化),同时使用汇编级优化,这样最终得到的代码效率最

高(长度和执行速度两方面)。按笔者的使用经验,仅从代码长度去比较,使用最高级别优

化后代码长度至少可以减少 20%(2K 字以上的程序)。而且 PICC 的优化器相当可靠,一般

%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/11.jpg" src="//m.amcfsurvey.com/ec/article/201611/file:///F:/data/%C3%83%C2%8F%C3%83%C2%82%C3%83%C2%94%C3%83%C2%98/PIC%C3%82%C2%B5%C3%82%C2%A5%C3%83%C2%86%C3%82%C2%AC%C3%82%C2%BB%C3%83%C2%BAC%C3%83%C2%93%C3%83%C2%AF%C3%83%C2%91%C3%83%C2%94%C3%82%C2%B1%C3%83%C2%A0%3Cwbr%3E%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/11.jpg" />%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/12.jpg" src="//m.amcfsurvey.com/ec/article/201611/file:///F:/data/%C3%83%C2%8F%C3%83%C2%82%C3%83%C2%94%C3%83%C2%98/PIC%C3%82%C2%B5%C3%82%C2%A5%C3%83%C2%86%C3%82%C2%AC%C3%82%C2%BB%C3%83%C2%BAC%C3%83%C2%93%C3%83%C2%AF%C3%83%C2%91%C3%83%C2%94%C3%82%C2%B1%C3%83%C2%A0%3Cwbr%3E%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/12.jpg" />

(A)常用选项(B)高级选项

图 11-5C 编译器选项设定

不会因为使用优化从而使生成的程序出现错误。碰到的一些问题也基本都是用户编写的原程

序有漏洞所导致,例如一些变量应该是 volatile 型但编程员没有明确定义,在优化前程序可

以正常运行,一旦使用优化,程序运行就出现异常。显然,把出现的这些问题归罪到编译器

是毫无道理的。

使用优化后可能对原程序级的调试带来一些不便之处。因 PICC 可能会重组编译后的代

码,例如多处重复的代码可能会改成同一个子程序调用以节约程序空间,这样在调试过程中

跟踪原程序时可能会出现程序乱跳的现象,这基本是正常的。若为了强调更直观的代码调试

过程,你可以将优化级别降低甚至关闭所有优化功能,这样调试时程序的运行就可以按部就

班了。

C 编译器的高级选项设定基本都是针对诊断信息输出的,和生成的代码无关。用得相对

较多的选项有:

&O1540;Generate assembly list file:编译器生成 C 原程序的汇编列表文件(*.lst)。在此文件

中列出了每一行C原代码对应的汇编指令,但这些都是优化前的代码。简单的一

C 语句被翻译成汇编指令后可能有好几条。有时汇编列表文件可以作为解决问

题的辅助手段。如果你怀疑编译器生成的代码有错误,不妨先产生对应的汇编列表

文件,看看在优化前一条 C 语句被编译后的汇编码到底是什么。

&O1540;Compile to assembly only:这一选项的作用是把&n, bsp;C原程序编译成汇编指令文件

(*.as),此时将不生成目标文件,也不进行最后的连接定位。这一选项在 C 和汇

编混合编程时特别有用。通过解读 C 程序对应的汇编指令,可以掌握 C 程序中存

取变量的具体方法,然后用在自己编写的汇编指令中。我们将在稍后专门做介绍。

11.8.5连接器选项设定(PICC Linker)

连接器 PICC Linker 的选项基本不用作太多的改变,在图 11-6 的对话框中显示了可设定的各类

项目。其中有两项有用的信息输出可以考虑加以利用:

&O1540;Generate map file:生成连接定位映射文件。在此映射文件中详细列出了所有程

序用到的变量的具体物理地址;所有函数的入口地址;函数相互之间调用的层次关系和深度等。这

些信息对于程序的调试将非常有用。此文件将以扩展名“*.map”的形式存放在同一个项目路径

下,需要时可以用任何文本编辑器打开观察。

%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/13.jpg" src="//m.amcfsurvey.com/ec/article/201611/file:///F:/data/%C3%83%C2%8F%C3%83%C2%82%C3%83%C2%94%C3%83%C2%98/PIC%C3%82%C2%B5%C3%82%C2%A5%C3%83%C2%86%C3%82%C2%AC%C3%82%C2%BB%C3%83%C2%BAC%C3%83%C2%93%C3%83%C2%AF%C3%83%C2%91%C3%83%C2%94%C3%82%C2%B1%C3%83%C2%A0%3Cwbr%3E%C3%82%C2%B3%C3%83%C2%8C%C3%82%C2%BD%C3%83%C2%8C%C3%82%C2%B3%C3%83%C2%8C.files/13.jpg" />

图 11-6PICC 连接器选项设定

&O1540;Display memory-segment usage:显示详细的内存分配和使用情况报告。用户可以

了解到程序空间和数据存储器空间资源分配的细节。下面列举了在一个项目编译后实际的内存使用

信息,为方便理解笔者用“//”添加了一些注释:

Psect Usage Map://程序段定位表

Psect|Contents|Memory Range

----------|------------------------------|--------------------

powerup| Power on reset code|$0000 - $0003

intentry| Interrupt service routine| $0004 - $000C

intcode| Interrupt service routine| $000D - $002C

intret| Interrupt service routine| $002D - $0035

init| Initialization code|$0036 - $003D

end_init| Initialization code| $003E - $0040

clrtext| Memoryclearingcode|$0041 - $0047

const3| Strings and constant data| $0048 - $0060

const| Strings and constant data| $0061 - $0071

const2| Strings and constant data| $0072 - $0076

text| Program and library code| $0576 - $0582

text| Program and library code| $0583 - $07C7

float_te| Arithmetic routine code| $07C8 - $07FF

rbss_0|Bank 0RAM variables|$0021 - $0042

temp| Temporary RAM data| $0043 - $0047

nvram|Persistent RAM data|$0048 - $004A

intsave| Registers saved oninterrupt| $004B - $004D

intsave| Registers saved on interrupt | $007F - $007F

intsave_1 | Saved copy of W in bank 1| $00FF - $00FF

rbit_0|Bank 0bit variables|$0100 - $0104

config| User-programmed CONFIG bits| $2007 - $2007

Memory Usage Map:

//程序空间代码定位地址分布

//存储空间使用情况报告

ProgramROM$0000 -$0076$0077 (119) words

ProgramROM$0576 -$07FF$028A (650) words

$0301 (769)wordstotal Program ROM

//bank0 数据空间变量地址分布

Bank0 RAM$0021 -$004D$002D (45) bytes

Bank0 RAM$007F -$007F$0001 (1) bytes

$002E (46) bytestotal Bank 0RAM

//bank1 数据空间变量地址分布

Bank 1 RAM$00FF - $00FF$0001 (1) bytes total Bank 1 RAM

//bank0 数据空间位变量地址分布

Bank 0 Bits$0100 - $0104$0005 (5) bitstotal Bank 0 Bits

//配置字地址

Config Data$2007 - $2007$0001 (1) words total Config Data

Program statistics:

//程序总体资源消耗统计

Total ROM used769 words (18.8%)//生成代码字总数和程序空间使用率

Total RAM used48bytes (25.0%)//使用数据字节数和数据空间使用率

例 11-7编译后程序使用的内存信息

11.8.6汇编器选项设定(PICC Assembler)

PICC 环境提供了自己的汇编编译器,它和 Microchip 公司提供的 MPASM 编译器在原

程序的语法表达方面要求稍有不同。另外,PICC 的汇编编译器要求输入原程序文件的扩展

名是“*.as”,而 MPASM 缺省认定的原程序以“*.asm”为扩展名。

在基于 PICC 编译环境下开发 PIC 单片机的 C 语言应用程序时基本无需关心其汇编编译

器,除非是在混合语言编程时用汇编语言编写完整的汇编原程序模块文件。其编译选项设定

的对话框见图 11-7,最重要的是优化使能控制项“Enable optimization”,一般情况下应该使

用汇编器的优化以节约程序空间。




评论


技术专区

关闭