PIC 单片机 C 语言编程简介(3)
PICC 会自动加入代码实现中断现场的保护,并在中断结束时自动恢复现场,所以编程
员无需象编写汇编程序那样加入中断现场保护和恢复的额外指令语句。但如果在中断服务程
序中需要修改某些全局变量时,是否需要保护这些变量的初值将由编程员自己决定和实施。
用 C 语言编写中断服务程序必须遵循高效的原则:
&O1540;
&O1540;
递归调用的问题,此函数必须为中断服务独家专用。既如此,不妨把原本要写在其
它函数内的代码直接写在中断服务程序中。
&O1540;
算不出现递归调用的问题,光在中断入口和出口处为了保护和恢复这些中间临时变
量就需要大量的开销,严重影响中断服务的效率。
中档系列 PIC 单片机的中断入口只有一个,因此整个程序中只能有一个中断服务函数。
11.6.5
PICC 提供了较完整的 C 标准库函数支持,其中包括数学运算函数和字符串操作函数。
在程序中使用这些现成的库函数时需要注意的是入口参数必须在 bank0 中。
如果需要用到数学函数,则应在程序前
用字符串操作函数,就需要包含“#include ”头文件。在这些头文件中提供了函数
类型的声明。通过直接查看这些头文件就可以知道 PICC 提供了哪些标准库函数。
C
printf/sprintf 是一个非常大的函数,一旦使用,你的程序代码长度就会增加很多。除非是在
编写试验性质的代码,可以考虑使用格式化打印函数以简化测试程序;一般的最终产品设计
都是自己编写最精简的代码实现特定格式的数据显示和输出。本来,在单片机应用中输出的
数据格式都相对简单而且固定,实现起来应该很容易。
对于标准 C 语言的控制台输入(scanf)/输出(printf)函数,PICC 需要用户自己编写
其底层函数 getch()和 putch()。在单片机系统中实现 scanf/printf 本来就没什么太多意义,如
果一定要实现,只要编写好特定的
出格式化的数据。
11.7
PICC 定义特殊区域值
PICC 提供了相关的预处理指令以实现在原程序中定义单片机的配置字和标记单元。
11.7.1
在原程序中定义 PIC 单片机工作配置字的重要性在前面章节中已经阐述。在用 PICC 写
程序时同样可以在 C 原程序中定义,具体方式如下:
__CONFIG (HS & UNPROTECT & PWRTEN & BORDIS & WDTEN);
上面的关键词“__CONFIG”(注意前面有两个下划线符)专门用于是芯片配置字的设
定,后面括号中的各项配置位符号在特定型号单片机的头文件中已经定义(注意不是
头文件),相互之间用逻辑“与”操作符组合在一起。这样定义的配置字信息最后将和程序
代码一起放入同一个 HEX 文件。
在这里列出了适用于
配置字定义方式类似,使用前查阅一下对应的头文件即可。
#define RC
#define HS
0x3FFF // RC 振荡
0x3FFE // HS 模式
#define XT
#define LP
0x3FFD // XT 模式
0x3FFC // LP 模式
#define WDTEN
#define WDTDIS
#define PWRTEN
0x3FFB //
0x3FF7 //
#define PWRTDIS
#define BOREN
#define BORDIS
0x3FBF //
#define UNPROTECT
#define PROTECT
例 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.2
参考第三章
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="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" />
图 11-3
11.8.3
全局选项将影响项目中所有 C 和汇编原程序的编译,详细的设定内容见图 11-4。其中
必须关注的有:
&O1540;
就必须打钩选中。这样编译后的结果就能保证
分的程序和数据空间)不被应用程序所占用。
&O1540;
是无符号数。如果在设计中需要使用带符号的‘char’型变量,此项就应该被选中。
&O1540;
‘double’型的双精度浮点数变量的实现长度为 24 位(等同于普通 float 型浮点数)。
在这里可以选择使其长度达 32 位。这样数值计算的精度将得到提高,但代码长度
将增加,计算速度也会降低,所以请在权衡利弊后作出你自己的决定。
11.8.4
项目中所有的 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="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" />
(A)常用选项
不会因为使用优化从而使生成的程序出现错误。碰到的一些问题也基本都是用户编写的原程
序有漏洞所导致,例如一些变量应该是 volatile 型但编程员没有明确定义,在优化前程序可
以正常运行,一旦使用优化,程序运行就出现异常。显然,把出现的这些问题归罪到编译器
是毫无道理的。
使用优化后可能对原程序级的调试带来一些不便之处。因 PICC 可能会重组编译后的代
码,例如多处重复的代码可能会改成同一个子程序调用以节约程序空间,这样在调试过程中
跟踪原程序时可能会出现程序乱跳的现象,这基本是正常的。若为了强调更直观的代码调试
过程,你可以将优化级别降低甚至关闭所有优化功能,这样调试时程序的运行就可以按部就
班了。
C 编译器的高级选项设定基本都是针对诊断信息输出的,和生成的代码无关。用得相对
较多的选项有:
&O1540;
中列出了每一行
条
题的辅助手段。如果你怀疑编译器生成的代码有错误,不妨先产生对应的汇编列表
文件,看看在优化前一条 C 语句被编译后的汇编码到底是什么。
&O1540;
(*.as),此时将不生成目标文件,也不进行最后的连接定位。这一选项在 C 和汇
编混合编程时特别有用。通过解读 C 程序对应的汇编指令,可以掌握 C 程序中存
取变量的具体方法,然后用在自己编写的汇编指令中。我们将在稍后专门做介绍。
11.8.5
连接器 PICC Linker 的选项基本不用作太多的改变,在图 11-6 的对话框中显示了可设定的各类
项目。其中有两项有用的信息输出可以考虑加以利用:
&O1540;
序用到的变量的具体物理地址;所有函数的入口地址;函数相互之间调用的层次关系和深度等。这
些信息对于程序的调试将非常有用。此文件将以扩展名“*.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="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-6
&O1540;
了解到程序空间和数据存储器空间资源分配的细节。下面列举了在一个项目编译后实际的内存使用
信息,为方便理解笔者用“//”添加了一些注释:
Psect Usage Map:
Psect
----------|------------------------------|--------------------
powerup
intentry
intcode
intret
init
end_init
clrtext
const3
const
const2
text
text
float_te
rbss_0
temp
nvram
intsave
intsave
intsave_1 | Saved copy of W in bank 1
rbit_0
config
Memory Usage Map:
//程序空间代码定位地址分布
//存储空间使用情况报告
Program
Program
//bank0 数据空间变量地址分布
Bank
Bank
//bank1 数据空间变量地址分布
Bank 1 RAM
//bank0 数据空间位变量地址分布
Bank 0 Bits
//配置字地址
Config Data
Program statistics:
//程序总体资源消耗统计
Total ROM used
Total RAM used
例 11-7
11.8.6
PICC 环境提供了自己的汇编编译器,它和 Microchip 公司提供的 MPASM 编译器在原
程序的语法表达方面要求稍有不同。另外,PICC 的汇编编译器要求输入原程序文件的扩展
名是“*.as”,而 MPASM 缺省认定的原程序以“*.asm”为扩展名。
在基于 PICC 编译环境下开发 PIC 单片机的 C 语言应用程序时基本无需关心其汇编编译
器,除非是在混合语言编程时用汇编语言编写完整的汇编原程序模块文件。其编译选项设定
的对话框见图 11-7,最重要的是优化使能控制项“Enable optimization”,一般情况下应该使
用汇编器的优化以节约程序空间。
评论