g7峰会 夫人合影:几种单片机C语言编译器的语言不同之处

来源:百度文库 编辑:中财网 时间:2024/04/29 22:23:38
大多数人最先学习的单片机恐怕都是51的,采用的编译器一般是keil c, 以后再接触avr单片机的编译器时不免会产生一些疑惑.   比较一下不同的单片机平台上程序的不同: 1. 由于不同单片机指令集不同, 汇编语言的程序通常很不一样.  2. c语言则是独立与指令集的高级语言,它不受指令集的影响,大部分代码是一致的,不同之处主要是在以下几处:

a) 不同单片机的头文件定义不同(即使同一种单片机不同的编译器里也可能不同)  .所以相应的端口,寄存器名也不同

b)不同单片机端口,寄存器功能不同, C语言中使用这些寄存器,端口的方式不同,从而代码不同. 这是最重要的一点.

c)以上是单片机硬件本身的不同所造成的关于端口,寄存器相关操作代码的不同, 还有一点不同是编译器本身所支持的扩展c语言语法的不同.

 

下边主要来介绍编译器所支持的扩展C语言语法上的异同: 

1.一般最需要注意的是扩展关键字的不同

     比如端口位的定义:

         1)在keic c中,有sbit这个关键字,可以定义端口某一个引脚. .

         2)在IARAVR中, 相应的采用 PORTX_Bitn 来定义端口位.        

         3)在ICCAVR 中则没有相应的端口位定义关键字,只能通过相应的宏文件,采用按位与及按位或的方式控制端口的某一位.
     还有关于变量存储位置定义的关键字区别:

          1)keil c中采用data,xdata,code这些关键字可以定义变量或常量存储的位置

          2)IARAVR中采用__flash _regvar 等来控制变量存储位置.   

         3)ICCAVR中采用同IARAVR类似的关键字如:__flash 来控制存储位置

  2.另外就是关于数据类型长度的问题

比如某些编译器里float是32位,但是某些编译器里float是24位. 另外对于对于char int,这些具体表示有符号数还是无符号数,也会不一样.

 3. 存储器存储长字节数据的方式也不同:

         51单片机中,存放int ,long这些大于一个字节长度的数据时, 是低地址存放高位字节, 高地址存放低位字节.

        而AVR中恰恰相反, 低地址存放低位字节,高地址存放高位字节.   

        因此,如果在程序中涉及采用联合体或是依次访问内存地址的方法对长字节数据分离的话,就要注意低地址里读取的是高字节还是低字节了.

 

顺便提一下51单片机(包括STC的)程序移植到AVR平台上需要注意的地方:

1) 头文件, 寄存器名,寄存器设置代码都是要相应修改的.

2) IO端口的位操作要做相应的调整.

3) 中断服务函数的格式也有不同,需做相应调整

4)  51单片机的端口寄存器复位值为1,因此作为输出端口时,即使程序中不作设置,也会输出高电平, 而AVR单片机中端口寄存  器PORTX 复位值为0,  因此51单片机的程序移植到avr单片机中时一定要注意端口初始化代码, 假设51程序中没有进行初始化,那么端口默认为高, 到了avr中,如果照搬原来的程序,端口就变成低电平,可能导致系统不能正常运行,而且不好查出来问题.

5) 由于两者对于长字节数据存放的方式不同,从地址到高地址, 51平台上依次存放高字节和低字节, AVR上依次存低字节和高字节, 所以如果程序中涉及到采用联合体或是依次访问内存地址的方法对长字节数据进行分离的话,就要注意低地址里读取的是高字节还是低字节了.

    比如:

union UNI_2BYTE
{
 uint   dat;
 uchar tab[2];
}wdat;

在这个联合体wdat中, 成员dat是个占2个字节长度的整形数,  那么wdat.tab[0]表示dat的低地址的那一个字节,  

 如果是在keil c中, 由于规定低地址存放高字节, 那么wdat.tab[0]就是dat的高字节. 

如果是在IARAVR或者ICCAVR中,由于低地址存放低字节, 那么wdat.tab[0]就是dat的低字节