分类: C/C++
2006-09-11 18:27:00
1. 编程语言的使用原则
在目前的单片机应用系统研制过程中,主要使用汇编语言和C语言作为开发语言,两者各有特点。
汇编语言的特点:
l 直接操作硬件及资源。
l 生成代码精简高效。
l 起步要求较高,程序员需对硬件有深刻的了解,一个好的程序员往往能大大减少开发与调试的周期。
l 可移植性较差,硬件或资源改变代码需要大量修改。
C语言的特点:
l 对程序员要求较低,往往只需要程序员了解一定的硬件知识即可。
l 可移植性较好,可以编写跨平台的嵌入式软件。
l 不需要程序员管理堆栈。在调用子程序和中断子程序时,不需要用户处理繁锁的栈操作,加快了开发进度,同时减少了栈操作出错的可能性。
l 生成代码的效率取决于编译器和程序员的编程风格。HC08C的编译器已经对部分硬件资源进行了封装,如:堆栈、子程序的跳转、中断处理时现场的保护。C代码中的函数、控制语句在编译时都会被编译器编译成相应的汇编指令,这些语句生成的代码量也不尽相等。而且同样功能的总代码生成量比使用汇编语言略高20%
任何一款编译器都不会比一个有经验的汇编语言程序员编写的汇编程序效率高,但是写一个好的C程序然后转换为高效的汇编程序比直接写高效的汇编程序就容易多了。
综上所述,无论是采用C语言还是汇编语言都各有其利弊。我们既不推荐在学习与开发嵌入式软件过程中完全采取汇编语言(因为汇编语言对一个不懂硬件的新手来说,是需要一定的时间才能上手的),也不赞同完全使用C语言(因为有许多底层的操作,C的语句是无法做到的)。所以在开发过程中,我们往往采用C和汇编结合的一种编程风格,要充分利用这两者的优势。例如我们通常把底层的对硬件的操作留给汇编指令,把与硬件无关或相关性较少的部分用C代码实现。当然,要充分发挥两者的性能,需要程序员对编译器有一定了解,并注重平时的积累
2. C语言对硬件的要求
并不是所有的MCU都可以用C语言来开发,它们必需具备一定的硬件条件:
l 完整的指令系统
l 拥有分别为运算和指针服务的16位寄存器,在HC08中就是HX和PC
l 堆栈指针和堆栈结构指针,在HCS08 C 语言中它们都是SP
l 连续的地址空间
3. 嵌入式C语言与标准C语言的区别
纯粹的ANSI C语言并不适合单片机开发,这是因为:
l 嵌入式系统与硬件密切相关
l 大部分嵌入式系统使用中断
l ANSI C 语言的变量类型提升规则对存储器消耗非常大
l 有些MCU不支持C语言堆栈.
l 很多MCU具有多种存储空间,例如51单片机的程序存储器、数据存储器、特殊功能存储器等
因此嵌入式C语言必需适合嵌入式的特殊环境:
l 有限 RAM
l 有限 ROM
l 有限堆栈空间
l 要求具有硬件编程向导
l 严格的时序(ISR, tasks, ...)
l 必需具有多种指针类型 (far/near/rom/uni/paged/...)
l 必需具有特殊关键字/符号 (@, interrupt, tiny, ...)
4. 嵌入式C编译器应具有的功能
l 适合ROM代码
l 优化代码
l 重入代码
l 支持CPU系列的不同成员
l 支持不同的存储器模式
对于一个编译器我们还应该注意以下细节,不同的编译器在这些方面差异较大
l 能内嵌汇编、混合编程
l 具有中断服务编程能力
l 可输出汇编语言源文件
l 带有标准库
l 具有初始化硬件和建立C语言运行环境的启动代码
5. 嵌入式C连接器应具有的功能
l 合并不同代码段
l 为CPU分配存储器 (RAM, ROM, stack, special areas)
l 产生调试文件 (包括符号、行号等)
l 产生目标文件的存储器映像
Metrowerks 是MOTOROLA于1999收购并独立运作的子公司,其软件产品CodeWarrior专门是面向Motoroal(freescale)所有的MCU与DSP嵌入式应用、跨平台的软件工具,是Motorola向用户的推荐产品。
CodeWarrior for HCS08 是面向以HC08或S08为CPU的单片机嵌入式应用开发的软件包。其中包括集成环境IDE、处理器专家库、全芯片仿真、可视化参数显示工具、项目工程管理器、C交叉编译器、汇编器、链接器以及调试器。可以完成从源代码编辑、编译到调试的全部工作,本书将在以后的章节中介绍其使用方法,以下所提到C语言均是指CodeWarrior for HCS08的C交叉编译器所支持的C语言。
HCS08C语言的语法基本与标准C相同。有关标准C语言的语法本书不再介绍,请读者自行参考相关书籍。本节主要介绍HCS08 C语言对标准C语言的扩展语法。
数据类型 |
大小 |
无符号(unsigned)数据范围 |
有符号(signed)数据范围 |
Char |
8 bits |
0 ~ 255 |
–128 ~ 127 |
Short int |
16 bits |
0 ~ 65535 |
–32768 ~ 32767 |
Int |
16 bits |
0 ~ 65535 |
–32768 ~ 32767 |
long int |
32 bits |
0 ~ 4294967295 |
–2147483648 ~ 2147483647 |
ANSI C没有为int类型规定长度,不过八位的单片机的C编译器一般都把int定义为16位有符号数。但是由于8位机处理8位数据是效率最高的,所以int类型和更大的类型都应该在必需要时才使用。最好不用使用浮点数。
char类型可能在不同编译器有不同的定义,或者根本没有定义,为了便于程序移植要,最好不要用char这个符号应给它起个别名。
可以为所有用到的数据类型进行重新定义。
typedef unsigned char UINT8;
typedef signed char SINT8;
typedef unsigned int UINT16;
typedef int SINT16;
typedef unsigned long int UINT32;
typedef long int SINT32;
使用这样的定义程序移植性较好。
为了节约有限的RAM资源应该为每个变量尽量用最小的数据类型;尽量少用有符号数据;可以在表达式中用强制类型转换把数据长度缩到最短。