PIC 单片机 C 语言编程简介
用 C 语言来开发单片机系统软件最大的好处是编写代码效率高、软件调试直观、维护升级方便、
代码的重复利用率高、便于跨平台的代码移植等等,因此 C 语言编程在单片机系统设计中已得到越
来越广泛的运用。针对 PIC 单片机的软件开发,同样可以用 C 语言实现。
但在单片机上用 C 语言写程序和在 PC 机上写程序绝对不能简单等同。现在的 PC 机资
源十分丰富,运算能力强大,因此程序员在写 PC 机的应用程序时几乎不用关心编译后的可
执行代码在运行过程中需要占用多少系统资源,也基本不用担心运行效率有多高。写单片机
的 C 程序最关键的一点是单片机内的资源非常有限,控制的实时性要求又很高,因此,如
果没有对单片机体系结构和硬件资源作详尽的了解,以笔者的愚见认为是无法写出高质量实
用的 C 语言程序。这就是为什么前面所有章节中的的示范代码全部用基础的汇编指令实现
的原因,希望籍此能使读者对 PIC 单片机的指令体系和硬件资源有深入了解,在这基础之
上再来讨论 C 语言编程,就有水到渠成的感觉。
本书围绕中档系列 PIC 单片机来展开讨论,Microchip 公司自己没有针对中低档系列 PIC
单片机的 C 语言编译器,但很多专业的第三方公司有众多支持 PIC 单片机的 C 语言编译器
提供,常见的有 Hitech、CCS、IAR、Bytecraft 等公司。其中笔者最常用的是 Hitech 公司的
PICC 编译器,它稳定可靠,编译生成的代码效率高,在用 PIC 单片机进行系统设计和开发
的工程师群体中得到广泛认可。其正式完全版软件需要购置,但在其网站上有限时的试用版
供用户评估。另外,Hitech 公司针对广大 PIC 的业余爱好者和初学者还提供了完全免费的学
习版 PICC-Lite 编译器套件,它的使用方式和完全版相同,只是支持的 PIC 单片机型号限制
在 PIC16F84、PIC16F877 和 PIC16F628 等几款。这几款 Flash 型的单片机因其所具备的丰富
的片上资源而最适用于单片机学习入门,因此笔者建议感兴趣的读者可从 PICC-Lite 入手掌
握 PIC 单片机的 C 语言编程。
在此列出几个主要的针对 PIC 单片机的 C 编译器相关连接网址,供读者参考:
Hitech-PICC: www.htsoft.com
IAR:www.iar.com CCS:www.ccsinfo.com/picc.shtml ByteCraft:www.bytecraft.com/mpccaps.html
本章将介绍 Hitech-PICC 编译器的一些基本概念,由于篇幅所限将不涉及 C 语言的标准
语法和基础知识介绍,因为在这些方面都有大量的书籍可以参考。重点突出针对 PIC 单片
机的特点而所需要特别注意的地方。
11.2
Hitech-PICC 编译器
PICC 基本上符合 ANSI 标准,除了一点:它不支持函数的递归调用。其主要原因是因
为 PIC 单片机特殊的堆栈结构。在前面介绍 PIC 单片机架构时已经详细说明了 PIC 单片机
中的堆栈是硬件实现的,其深度已随芯片而固定,无法实现需要大量堆栈操作的递归算法;
另外在 PIC 单片机中实现软件堆栈的效率也不是很高,为此,PICC 编译器采用一种叫做“静
态覆盖”的技术以实现对 C 语言函数中的局部变量分配固定的地址空间。经这样处理后产
生出的机器代码效率很高,按笔者实际使用的体会,当代码量超过 4K 字后,C 语言编译出
的代码长度和全部用汇编代码实现时的差别已经不是很大(<10%),当然前提是在整个 C
代码编写过程中须时时处处注意所编写语句的效率,而如果没有对 PIC 单片机的内核结构、
各功能模块及其汇编指令深入了解,要做到这点是很难的。
11.3
MPLAB-IDE 内挂接 PICC
PICC 编译器可以直接挂接在 MPLAB-IDE 集成开发平台下,实现一体化的编译连接和
原代码调试。使用 MPLAB-IDE 内的调试工具 ICE2000、ICD2 和软件模拟器都可以实现原
代码级的程序调试,非常方便。
首先必须在你的计算机中安装PICC编译器,无论是完全版还是学习版都可以和
MPLAB-IDE挂接。安装成功后可以进入IDE,选择菜单项Project Set Language Tool
Locations…,打开语言工具挂接设置对话框,如图 11-1 所示:
图 11-1 MPLAB-IDE 语言工具设置对话框
在对话框中选择“HI-TECH PICC Toolsuite”栏,展开可执行文件组“Executable”后,
列出了将被 MPLAB-IDE 后台调用的编译器所用到的所有可执行文件,其中有汇编编译器
“PICC Assembler”、C 原程序编译器“PICC Compiler”和连接定位程序“PICC Linker”。同
时在此列表中还显示了对应的可执行程序名,请注意在这里都是“PICC.EXE”。用鼠标分别
点击选中这三项可执行文件,观察对话框下面“Location”一栏中显示的文件路径,用
“Browse…”按纽,从计算机中已经安装的 PICC 编译器文件夹中选择 PICC.EXE 文件。实
际上 PICC.EXE 只是一个调度管理程序,它会按照所输入的文件扩展名自动调用对应的编译
器和连接器,用户要注意的是 C 语言原程序扩展名用“.c”,汇编原程序用“.as”即可。
工具挂接完成后,在建立项目时可以选择语言工具为“HI-TECH PICC”,具体步骤可以
参阅第三章 3.1.3 节,此处不再重复。项目建立完成后可以加入 C 或汇编原程序,也可以加
入已有的库文件或已经编译的目标文件。最常见的是只加入 C 原程序。用 C 语言编程的好
处是可以实现模块化编程。程序编写者应尽量把相互独立的控制任务用多个独立的 C 原程序文件实
现,如果程序量较大,一般不要把所有的代码写在一个文件内。
图 11-2 列出的是笔者建立的一个项目中所有 C 原程序模块,其中主控、数值计算、I2C 总线操
作、命令按键处理和液晶显示驱动等不同的功能分别在不同的独立的原程序模块中实现。
图 11-2 C 语言多模块编程
11.4 PIC 单片机的 C 语言原程序基本框架
基于 PICC 编译环境编写 PIC 单片机程序的基本方式和标准 C 程序类似,程序一般由以
下几个主要部分组成:
&O1540; 在程序的最前面用#include 预处理指令引用包含头文件,其中必须包含一个编译器
提供的“pic.h”文件,实现单片机内特殊寄存器和其它特殊符号的声明;
&O1540; 用“__CONFIG”预处理指令定义芯片的配置位;
&O1540; 声明本模块内被调用的所有函数的类型,PICC 将对所调用的函数进行严格的类型
匹配检查;
&O1540; 定义全局变量或符号替换;
&O1540; 实现函数(子程序),特别注意 main 函数必须是一个没有返回的死循环。
下面的例 11-1 为一个 C 原程序的范例,供大家参考。
#include //包含单片机内部资源预定义
#include “pc68.h” //包含自定义头文件
//定义芯片工作时的配置位
__CONFIG (HS & PROTECT & PWRTEN & BOREN & WDTDIS);
//声明本模块中所调用的函数类型
void SetSFR(void);
void Clock(void);
void KeyScan(void);
void Measure(void);