frescale单片机C编程要点
3. C语言编程要点
CW中针对 Freescale的8位单片C语言编程基本符合ANSI规范,因此关于标准C语言编程的话题就不再重复。这里主要介绍和单片机资源密切相关的一些编程要点。
3.1 变量类型和定义
CW中08系列单片机C编译器支持的基本变量类型及其缺省的长度位数由表3.1所示。有些变量的长度可以按实际项目需要而改变,见对话框图3-1。此对话框经由上面的图2-3中“Type Size”配置按纽打开。
表 3.1中所示的整形数变量 char、short、int、long等都有对应的无符号型式(前面冠以 unsigned)。CW 给定的头文件已经将最常用的一些无符号变量类型做了类型名简化替换,例如用“byte”代替“unsigned char”,用“word”代替“unsigned int”。这样在程序编写是可以节约点敲键盘的时间。
在单片机程序设计中对于变量类型的选择确认有两条最基本的原则须遵循:能用短的变量就不用长的;能用无符号数就不用有符号数。这两条基本原则将在很大程度上决定你代码的长度和效率。因此请多多使用byte或word类型变量。
由于08系列单片机内部硬件寄存器定义的特点,对于多字节组成的变量,例如int、long 等,C 编译器缺省的变量内存排列方式是“big endian”模式,即高位字节放在低地址,低位字节放在高地址,又俗称“大头朝上”。这一点相比普通Intel 格式,例如 51 系列和 PIC 系列正好相反,它们都是“little endian”模式,即“大头朝下”,在程序跨平台移植时请特别注意。当然 CW 编译器本身可以设定改变成“little endian”模式,但单片机内部寄存器地址排列顺序无法改变,故这样做将使最终的程序代码效率降低,特别是在存取一些 16 位长的寄存器组时,它们在硬件上都是由顺序排列的两个8位寄存器组成,高字节在前,低字节在后。
单片机程序设计中经常会用到的位变量作为一些标志。CW中没有特别的位变量定义关键词,位变量必须由位域结构体的型式来定义。例如:
struct {
unsigned powerOn : 1;
unsigned alarmOn : 1;
unsigned commActive : 1;
unsigned sysError : 1;
} myFlag;
若引用某个位变量,只需
myFlag.alarmOn = 1;
myFlag.sysError = 0;
这样定义的各个位变量将被顺序排放在一起,以字节为基本单位,字节的第 0位放第一个位变量,一个字节含8个位变量。因此如果位域结构中定义的位变量数目很多,在最后内存分配上将占居多个字节。
有时为了编程方便,位变量需单独定义和操作但又希望一次整个字节一起初始化(清零或赋值),这时我们可以定义字节(或字)和位域结构的联合体:
union {
byte flagByte;
struct {
unsigned powerOn : 1;
unsigned alarmOn : 1;
unsigned commActive : 1;
unsigned sysError : 1;
} bits;
} myFlag;
整字节操作可以
myFlag.flagByte = 0;
单独某一个位操作可以可以
myFlag.bits.powerOn = 1;
myFmActive = !myFmActive;
若嫌这样的位变量名称太长,大可以在你自己的头文件里用“#define”预定义,用更简洁易懂的名称进行替换。
最后要提醒的是在定义位变量时尽量将它们指定分配到内存空间的第 0页(地址范围 0x00-0xff),这样对位变量操作的 C 代码将直接被编译成对应的汇编位操作指令,代码效率最高。具体的定位方法将在介绍“#pragma”时说明。
3.2 变量的特殊修饰
上面介绍的各类基本变量和由其合成的高级变量如数组、结构和联合,将满足95%以上的单片机程序设计工作。由于单片机资源的有限性和特殊型,还有一小部分因素需要在定义变量时加以考虑:
3.2.1 变量的绝对定位
变量绝对定位是特别针对芯片内部的硬件寄存器定义的。所有的硬件寄存器在编写C程序时均被视为变量,它们都已在 CW给定的头文件中预先定义。由于是硬件资源,其地址是唯一且不可改的,所以在头文件中定义这些寄存器时都采用绝对定位的方式,如定义9S08AW32的PORTA:
/*** PTAD - Port A Data Register; 0***/
t