您好,欢迎来电子发烧友网! ,新用户?[免费注册]

当前位置:电子发烧友网 > 图书频道 > 电子 > 《单片机原理与应用》 > 第8章 单片机高级程序设计

第1节 Keil C51开发系统基本知识

  8.1.1 为什么要用高级语言

  当设计一个小的嵌入式系统时,一般我们都用汇编语言。在很多工程中这是一个很好的方法,因为代码一般都不超过8K, 而且都比较简单。如果硬件工程师要同时设计软件和硬件,经常会采用汇编语言来做程序。我的经验告诉我:硬件工程师一般不熟悉像C一类的高级语言。

  使用汇编的麻烦,在于它的可读性和可维护性。特别当程序没有很好的标注的时候,代码的可重用性也比较低,如果使用C的话可以很好的解决这些问题。

  用C 编写的程序,因为C 语言很好的结构性和模块化,更容易阅读和维护。而且,由于模块化用C 语言编写的程序,有很好的可移植性,功能化的代码能够很方便的从一个工程移植到另一个工程,从而减少了开发时间。用C 编写程序比汇编更符合人们的思考习惯,开发者可以更专心的考虑算法,而不是考虑一些细节问题。这样,就减少了开发和调试的时间。

  使用像C 这样的语言,程序员不必十分熟悉处理器的运算过程。这意味着对新的处理器也能很快上手,不必知道处理器的具体内部结构。使得用C 编写的程序比汇编程序有更好的可移植性,很多处理器支持C 编译器。

  所有这些,并不说明汇编语言就没了立足之地。很多系统,特别是实时时钟系统都是用C 和汇编语言联合编程。对时钟要求很严格时,使用汇编语言成了唯一的方法。除此之外,包括硬件接口的操作都应该用C 来编程。C 的特点:就是可以使你尽量少地对硬件进行操作,是一种功能性和结构性很强的语言。

  8.1.2 Keil C 和ANSI C

  下面将介绍Keil C 的主要特点和它与ANSI C 的不同之处。并给你一些对8051 使用C的启发。

  Keil 编译器,除了少数一些关键地方外,基本类似于ANSI C 。差异主要是:Keil 可以让用户针对8051 的结构进行程序设计。其它差异主要是8051 的一些局限引起的。

  8.1.3 特殊功能寄存器

  特殊功能寄存器,用sfr 来定义。而sfr16 用来定义16 位的特殊功能寄存器。如DPTR通过名字或地址来引用特殊功能寄存器,地址必须高于80H。 可位寻址的特殊功能寄存器的位变量定义,用关键字sbit SFR 的定义如列表0-1所示:对于大多数8051 成员Keil提供了一个包含了所有特殊功能寄存器和他们的位的定义的头文件。通过包含头文件可以很容易的进行新的扩展。

  列表0-1

  sfr SCON=0X98; //定义SCON

  sbit SM0=0X9F; //定义SCON 的各位

  sbit SM1=0X9E;

  sbit SM2=0X9D;

  sbit REN=0x9C;

  sbit TB8=0X9B;

  sbit RB8=0X9A;

  sbit TI=0X99;

  sbit RI=0X98;

  8.1.4 存储类型

  Keil 允许使用者指定程序变量的存储区,这使使用者可以控制存储区的使用,编译器可识别以下存储区。

  存储区描述

  DATA RAM 的低128 个字节可在一个周期内直接寻址

  BDATA DATA 区的16 个字节的可位寻址区

  IDATA RAM 区的高128 个字节必须采用间接寻址

  PDATA 外部存储区的256 个字节通过P0 口的地址对其寻址

  使用指令MOVX @Rn,需要两个指令周期

  XDATA 外部存储区使用DPTR 寻址

  CODE 程序存储区使用DPTR 寻址

  8.1.5 中断服务

  8051 的中断系统十分重要,C51 使你能够用C 来声明中断和编写中断服务程序(当然你也可以用汇编来写) ,中断过程通过使用interrupt 关键字和中断号(0 到31)来实现。中断号告诉编译器,中断程序的入口地址、中断号对应着IE 寄存器中的使能位。换句话说IE寄存器中的0 位对应着外部中断0 。相应的外部中断0 的中断号是0, 表0-6 反映了这种关系:

  一个中断过程,并不一定带上所有参数,可以没有返回值。有了这些限制,编译器不须要担心寄存器组参数的使用和对累加器状态寄存器B 、寄存器数据指针和默认的寄存器的保护。只要他们在中断程序中,被用到编译的时候,会把他们入栈在中断程序结束时将他们恢复。中断程序的入口地址被编译器放在中断向量中,C51 支持所有5 个8051/8052 标准中断、从0 到4 和在8051 系列中多达27 个中断源,一个中断服务程序的例子如下:

  列表0-2

  #include

  #include

  #define RELOADVALH 0x3C

  #define RELOADVALL 0xB0

  extern unsigned int tick_count;

  void timer0(void) interrupt 1

  {

  TR0=0; // 停止定时器0

  TH0=RELOADVALH; // 50ms后溢出

  TL0=RELOADVALL;

  TR0=1; // 启动T0

  tick_count++; // 时间计数器加1

  printf("tick_count=%05u\n", tick_count);

  }

  有关KEIL C的集成环境使用可参考本书附录,这里就不详述。

  使用C 来开发系统,方便快捷。他既不会降低你对硬件的控制能力,也不会使你的代码长度增加多少,如果你运用得好的话,你能够开发出非常高效的系统,并且非常利于维护。