访问手机版页面
你的位置:老古开发网 > PIC单片机开发环境MPLAB > 正文  
MPLAB-C18 C编译器的优化技巧
内容导读:

  Microchip推出的PIC18系列单片机由于采用改进型的哈佛结构及优化的硬件结构,内含三个间接寻址寄存器FSR0、FSR1和FSR2, RAM 和ROM 空间都比较大, 因此PIC18非常适合于采用C语言进行软件设计。C语言具有可读性强, 便于移植等优点。 虽然MPLAB-C18 C语言编译器的编译效率比较高, 但与汇编语言相比, C的效率终究差一些, 因此在某些应用场合, 如何优化C的效率, 减小代码, 提高执行速度, 是许多工程师们的追求目标。下面介绍MPLAB-C18 C编译器的一些优化技巧, 与大家共享。

1  使用静态型局部变量

  局部变量的缺省存储类型为自动型,存取时使用软件堆栈,即使用直接寻址方式。如果声明为静态型,则静态型局部变量编译时将分配固定地址, 访问时将使用直接寻址。显然, 直接寻址比间接寻址存取速度快,占用的代码空间少。下面举例比较静态型与自动型局部变量生成汇编代码的差别。

  源程序代码

void sub1(void) {
static unsigned char local1; //静态型
  unsigned char local2; // 自动型
  local1+=5; // 占用5个字
  local2+=6; //仅占用3个字
} 生成的汇编代码
MOVF POSTINC1,F,ACCESS
MOVLW 0X05
MOVLB 0X0
ADDWF L1,F,BANKED
MOVF POSTDEC1,F,ACCESS
MOVLW 0X06
MOVLB 0X0
MOVWF LOCAL1,BANKED

  注意:①静态型局部变量将占用更多的数据存储器空间;② 如果该函数是可重载的, 则局部变量不能声明为静态型。

2  使用全局变量传递函数参数

  当有足够的数据存储空间且该函数不可重载时, 可使用全局变量传递函数参数, 优化你的代码。因为全局变量编译时将分配固定地址, 访问时将使用直接寻址方式。例如调用sub1子程序, 可采用下面使用全局变量传递函数参数的方法。

unsigned char sub1_var1,sub1_var2;
void sub1(void);
void main(void){
  sub1_var1=1;
  sub1_var2=2;
  sub1();
}

  替代如下传递函数参数的方法。

void sub1(unsigned char var1,unsigned char var2)
viod main(void)
{
  sub1(1,2)
}

  当然也可以把var1、var2声明为静态型存储类型, 达到相同优化代码的目的。即:void sub1(static unsigned char var1, static unsigned char var2)。

3  使用合适的数据类型

  MPLAB C-18支持的数据类型及占用的字节数如下:

类型 最小值 最大值 字节数
unsigned char 0 255 1
signed char -128 127 1
unsigned int 0 655536 2
signed int -32768 32767 2
unsigned short long 0 16777215 4
signed short long -8388608 8388607 4
unsigned long 0 4294967295 8
signed long -2147483648 2147483647 8

  不同数据类型占用的数据存储器字节数不同, 因此尽可能使用较短的数据类型。 另外如果是无符号数, 应声明为无符号型。 例如下例变量i、j加一立即数, 其中i为int型,j为char型, 可见它们生成的代码大小不一样。

  源程序代码

int i;
unsigned char j;
void main(void) {
  i+=5; //占用4个字
  j+=6; // 仅占用3个字
}

  生成的汇编代码

MOVLW 0X06
ADDWF I,F,BANKED
MOVLW 0
ADDWF 0XB8,F,BANKED
MOVLW 0X05
MOVLB 0X0
ADDWF J,F,BANKED

4  把变量分配于ACCESS RAM区

  PIC18系列数据存储器分为16个存储器组(BANK 0~15), 每个存储器组为256个字节, 使用直接寻址方式访问数据存储器时, 先要选择存储器组(BANK)。 为了快速访问数据存储器, PIC18把BANK0的0x0~0x7F和BANK15的0x80~0xFF构成ACCESS RAM。 访问ACCESS RAM时, 不需要选择BANK, 从而达到快速访问的目的。 下面举例比较变量分配于ACCESS RAM区与不在ACCESS RAM的区别。

  源程序代码

unsigned char var1 //不在Access RAM区
#pragma udata access mydata near unsigned char var2 //声明于Access RAM区
#pragma
void sub1(void){
  var1+=5; // 占用3个字
  var2+=6; //仅占用2个字
}

  生成的汇编代码

MOVLW 0X05
MOVLB 0X01
ADDWF 0xvar1,F,BANKED
MOVLW 0X06
ADDWF 0xvar2,F, ACCESS

5  使用#pragma varlocate伪指令

  #pragma varlocate 伪指令告诉编译器变量所属的存储器组位置, 从而使编译器更有效地执行存储器组切换。 例如在多模块编程中, 文件1把变量I、J分配在存储器组1。

  #pragma udata bank1
  unsigned char I,J

  在文件2中要使用变量I、J, 用# pragma varlocate 声明变量I、J位于存储器组位置1, 这样编译时可省掉一条MOVLB 指令。

extern unsigned char I,J
#pragma varlocate 1 c1,c2
void main (void)
{
  I+=5; // 此处编译时可省掉一条MOVLB 指令
  J+=6;
}

6  使用指针

  下面举例说明使用指针与不使用指针的区别,其中例子1使用指针,例子2不使用指针。编译后,可以发现例子1生成的代码比例子2 少很多。

struct mystruct
{
  char a;
  char b;
}
mystruct mydata [10];
mystruct *p=&(mydata[0]);

  例子1

for(i=0; i<10; i++)
{
  p->.a = i;
  p->.b = 88;
  p++;
}

  例子2

for (i=0;i,10;i++)
{
  mydata[i].a=i
  mydata[i].b=88; }

7  嵌入汇编

  因为汇编的效率最高, 因此在有些场合例如中断服务子程序使用嵌入汇编的方法。 MPLAB-C18支持C与汇编的混合编程。

8  使用最新版本的C编译器

  MPLAB-C18编译器的版本不断更新,最新版本除了支持新型号的PIC18单片机之外,还对它的优化效率不断改善。因此尽量使用最新版本的C编译器。

9  使用优化命令行选项

  在优化功能命令项的选项对话框中,选中表示使能。 但请注意有些优化选项将会影响源程序级调试。限于篇幅,各优化功能命令项的作用这里不一一介绍。

标签:
来源:单片机与嵌入式系统应用 作者:廖珍爱 时间:2006/2/12 0:00:00
相关阅读
推荐阅读
阅读排行
最近更新
商品推荐