图 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 “pic68.h” //包含自定义头文件
//定义芯片工作时的配置位
__CONFIG (HS & PROTECT & PWRTEN & BOREN & WDTDIS);
//声明本模块中所调用的函数类型
void SetSFR(void);
void Clock(void);
void KeyScan(void);
void Measure(void);
void LCD_Test(void);
void LCD_Disp(unsigned char);
//定义变量
unsigned char second, minute, hour;
bit flag1,flag2;
//函数和子程序
void main(void)
{
SetSFR();
PORTC = 0x00;
TMR1H += TMR1H_CONST;
LED1 = LED_OFF;
LCD_Test();
//程序工作主循环
while(1) {
asm(“clrwdt”);
Clock();
KeyScan();
Measure();
SetSFR();
}
}
PICC 中的变量定义
例 11-1 C 语言原程序框架举例
11.5.1 PICC 中的基本变量类型
PICC 遵循 Little-endian 标准,多字节变量的低字节放在存储空间的低地址,高字节放
在高地址。
11.5.2 PICC 中的高级变量
基于表 11-1 的基本变量,除了 bit 型位变量外,PICC 完全支持数组、结构和联合等复
合型高级变量,这和标准的 C 语言所支持的高级变量类型没有什么区别。例如:
数组:unsigned int data[10];
结构:struct commInData {
unsigned char inBuff[8];
unsigned char getPtr, putPtr;
};
联合:union int_Byte {
unsigned char c[2];
unsigned int i;
};
例 11-2 C 语言高级变量举例
11.5.3 PICC 对数据寄存器 bank 的管理
为了使编译器产生最高效的机器码,PICC 把单片机中数据寄存器的 bank 问题交由编程
员自己管理,因此在定义用户变量时你必须自己决定这些变量具体放在哪一个 bank 中。如
果没有特别指明,所定义的变量将被定位在 bank0,例如下面所定义的这些变量:
unsigned char buffer[32];
bit flag1,flag2;
float val[8];
除了 bank0 内的变量声明时不需特殊处理外,定义在其它 bank 内的变量前面必须加上
相应的 bank 序号,例如:
bank1 unsigned char buffer[32]; //变量定位在
bank1 中
bank2 bit flag1,flag2;
bank3 float val[8];
//变量定位在 bank2 中
//变量定位在 bank3 中
中档系列 PIC 单片机数据寄存器的一个 bank 大小为 128 字节,刨去前面若干字节的特
殊功能寄存器区域,在 C 语言中某一 bank 内定义的变量字节总数不能超过可用 RAM 字节
数。如果超过 bank 容量,在最后连接时会报错,大致信息如下:
Error[000] : Can't find 0x12C words for psect
rbss_1 in segment BANK1
连接器告诉你总共有 0x12C(300)个字节准备放到 bank1 中但 bank1
容量不够。显然,只
有把一部分原本定位在 bank1 中的变量改放到其它 bank 中才能解决此问题。
虽然变量所在的 bank 定位必须由编程员自己决定,但在编写原程序时进行变量存取操
作前无需再特意编写设定 bank 的指令。C 编译器会根据所操作的对象自动生成对应 bank 设
定的汇编指令。为避免频繁的 bank 切换以提高代码效率,尽量把实现同一任务的变量定位
在同一个 bank 内;对不同 bank 内的变量进行读写操作时也尽量把位于相同 bank 内的变量
归并在一起进行连续操作。
11.5.4 PICC 中的局部变量
PICC 把所有函数内部定义的 auto 型局部变量放在 bank0。为节约宝贵的存储空间,它
采用了一种被叫做“静态覆盖”的技术来实现局部变量的地址分配。其大致的原理是在编译
器编译原代码时扫描整个程序中函数调用的嵌套关系和层次,算出每个函数中的局部变量字
节数,然后为每个局部变量分配一个固定的地址,且按调用嵌套的层次关系各变量的地址可
以相互重叠。利用这一技术后所有的动态局部变量都可以按已知的固定地址地进行直接寻
址,用 PIC 汇编指令实现的效率最高,但这时不能出现函数递归调用。PICC 在编译时会严
格检查递归调用的问题并认为这是一个严重错误而立即终止编译过程。
既然所有的局部变量将占用 bank0 的存储空间,因此用户自己定位在 bank0 内的变量字
节数将受到一定的限制,在实际使用时需注意。
11.5.5 PICC 中的位变量
bit 型位变量只能是全局的或静态的。PICC 将把定位在同一 bank 内的 8 个位变量合并
成一个字节存放于一个固定地址。因此所有针对位变量的操作将直接使用 PIC 单片机的位
操作汇编指令高效实现。基于此,位变量不能是局部