PIC单片机C语言编程教程

上传人:hjk****65 文档编号:178020631 上传时间:2022-12-27 格式:DOC 页数:64 大小:245KB
收藏 版权申诉 举报 下载
PIC单片机C语言编程教程_第1页
第1页 / 共64页
PIC单片机C语言编程教程_第2页
第2页 / 共64页
PIC单片机C语言编程教程_第3页
第3页 / 共64页
资源描述:

《PIC单片机C语言编程教程》由会员分享,可在线阅读,更多相关《PIC单片机C语言编程教程(64页珍藏版)》请在装配图网上搜索。

1、PIC 单片机 C 语言编程简介用 C 语言来开发单片机系统软件最大的好处是编写代码效率高、软件调试直观、维护升级方便、代码的重复利用率高、便于跨平台的代码移植等等,因此 C 语言编程在单片机系统设计中已得到越来越广泛的运用。针对 PIC 单片机的软件开发,同样可以用 C 语言实现。但在单片机上用 C 语言写程序和在 PC 机上写程序绝对不能简单等同。现在的 PC 机资源十分丰富,运算能力强大,因此程序员在写 PC 机的应用程序时几乎不用关心编译后的可执行代码在运行过程中需要占用多少系统资源,也基本不用担心运行效率有多高。写单片机的 C 程序最关键的一点是单片机内的资源非常有限,控制的实时性要

2、求又很高,因此,如果没有对单片机体系结构和硬件资源作详尽的了解,以笔者的愚见认为是无法写出高质量实用的 C 语言程序。这就是为什么前面所有章节中的的示范代码全部用基础的汇编指令实现的原因,希望籍此能使读者对 PIC 单片机的指令体系和硬件资源有深入了解,在这基础之上再来讨论 C 语言编程,就有水到渠成的感觉。本书围绕中档系列 PIC 单片机来展开讨论,Microchip 公司自己没有针对中低档系列 PIC单片机的 C 语言编译器,但很多专业的第三方公司有众多支持 PIC 单片机的 C 语言编译器提供,常见的有 Hitech、CCS、IAR、Bytecraft 等公司。其中笔者最常用的是 Hit

3、ech 公司的PICC 编译器,它稳定可靠,编译生成的代码效率高,在用 PIC 单片机进行系统设计和开发的工程师群体中得到广泛认可。其正式完全版软件需要购置,但在其网站上有限时的试用版供用户评估。另外,Hitech 公司针对广大 PIC 的业余爱好者和初学者还提供了完全免费的学习版 PICC-Lite 编译器套件,它的使用方式和完全版相同,只是支持的 PIC 单片机型号限制在 PIC16F84、PIC16F877 和 PIC16F628 等几款。这几款 Flash 型的单片机因其所具备的丰富的片上资源而最适用于单片机学习入门,因此笔者建议感兴趣的读者可从 PICC-Lite 入手掌握 PIC

4、单片机的 C 语言编程。在此列出几个主要的针对 PIC 单片机的 C 编译器相关连接网址,供读者参考:Hitech-PICC: IAR:CCS:ByteCraft:本章将介绍 Hitech-PICC 编译器的一些基本概念,由于篇幅所限将不涉及 C 语言的标准语法和基础知识介绍,因为在这些方面都有大量的书籍可以参考。重点突出针对 PIC 单片机的特点而所需要特别注意的地方。11.2Hitech-PICC 编译器PICC 基本上符合 ANSI 标准,除了一点:它不支持函数的递归调用。其主要原因是因为 PIC 单片机特殊的堆栈结构。在前面介绍 PIC 单片机架构时已经详细说明了 PIC 单片机中的堆

5、栈是硬件实现的,其深度已随芯片而固定,无法实现需要大量堆栈操作的递归算法;另外在 PIC 单片机中实现软件堆栈的效率也不是很高,为此,PICC 编译器采用一种叫做“静态覆盖”的技术以实现对 C 语言函数中的局部变量分配固定的地址空间。经这样处理后产生出的机器代码效率很高,按笔者实际使用的体会,当代码量超过 4K 字后,C 语言编译出的代码长度和全部用汇编代码实现时的差别已经不是很大( bsf= bcf0x20,70x20,3if (tmp&0xfe)= btfsc 0x20,0即所有只对变量中某一位操作的 C 语句代码将被直接编译成汇编的位操作指令。虽然编程时可以不用太关心,但如果能了解编译器

6、是如何工作的,那将有助于引导我们写出高效简介的 C 语言原程序。在有些应用中需要将一组位变量放在同一个字节中以便需要时一次性地进行读写,这一功能可以通过定义一个位域结构和一个字节变量的联合来实现,例如:union struct unsigned b0: 1; unsigned b1: 1; unsigned b2: 1; unsigned b3: 1; unsigned b4: 1; unsigned b5: 1; unsigned : 2; /最高两位保留 oneBit; unsigned char allBits; myFlag;例 11-3 定义位变量于同一字节需要存取其中某一位时可以m

7、yFlag.oneBit.b3=1; /b3 位置 1一次性将全部位清零时可以myFlag.allBits=0; /全部位变量清 0当程序中把非位变量进行强制类型转换成位变量时,要注意编译器只对普通变量的最低位做判别:如果最低位是 0,则转换成位变量 0;如果最低位是 1,则转换成位变量 1。而标准的 ANSI-C 做法是判整个变量值是否为 0。另外,函数可以返回一个位变量,实际上此返回的位变量将存放于单片机的进位位中带出返回。11.5.6 PICC 中的浮点数PICC 中描述浮点数是以 IEEE-754 标准格式实现的。此标准下定义的浮点数为 32 位长,在单片机中要用 4 个字节存储。为了

8、节约单片机的数据空间和程序空间,PICC 专门提供了一种长度为 24 位的截短型浮点数,它损失了浮点数的一点精度,但浮点运算的效率得以提高。在程序中定义的 float 型标准浮点数的长度固定为 24 位,双精度 double 型浮点数一般也是 24 位长,但可以在程序编译选项中选择 double 型浮点数为 32 位,以提高计算的精度。一般控制系统中关心的是单片机的运行效率,因此在精度能够满足的前提下尽量选择24 位的浮点数运算。11.5.7 PICC 中变量的绝对定位首先必须强调,在用 C 语言写程序时变量一般由编译器和连接器最后定位,在写程序之时无需知道所定义的变量具体被放在哪个地址(除了

9、 bank 必须声明)。真正需要绝对定位的只是单片机中的那些特殊功能寄存器,而这些寄存器的地址定位在PICC 编译环境所提供的头文件中已经实现,无需用户操心。编程员所要了解的也就是 PICC是如何定义这些特殊功能寄存器和其中的相关控制位的名称。好在 PICC 的定义标准基本上按照芯片的数据手册中的名称描述进行,这样就秉承了变量命名的一贯性。一个变量绝对定位的例子如下:unsigned char tmpData 0x20; /tmpData 定位在地址 0x20千万注意,PICC 对绝对定位的变量不保留地址空间。换句话说,上面变量 tmpData 的地址是 0x20,但最后 0x20 处完全有可

10、能又被分配给了其它变量使用,这样就发生了地址冲突。因此针对变量的绝对定位要特别小心。从笔者的应用经验看,在一般的程序设计中用户自定义的变量实在是没有绝对定位的必要。如果需要,位变量也可以绝对定位。但必须遵循上面介绍的位变量编址的方式。如果一个普通变量已经被绝对定位,那么此变量中的每个数据位就可以用下面的计算方式实现位变量指派:unsigned char tmpData 0x20; /tmpData 定位在地址 0x20bit tmpBit0 tmpData*8+0; /tmpBit0 对应于 tmpData 第 0 位bit tmpBit1 tmpData*8+1; /tmpBit0 对应于

11、tmpData 第 1 位bit tmpBit2 tmpData*8+2; /tmpBit0 对应于 tmpData 第 2 位如果 tmpData 事先没有被绝对定位,那就不能用上面的位变量定位方式。11.5.8 PICC 的其它变量修饰关键词&O1540; extern 外部变量声明如果在一个 C 程序文件中要使用一些变量但其原型定义写在另外的文件中,那么在本文件中必须将这些变量声明成“extern”外部类型。例如程序文件 code1.c 中有如下定义:bank1 unsigned char var1, var2; /定义了 bank1 中的两个变量在另外一个程序文件 code2.c 中要

12、对上面定义的变量进行操作,则必须在程序的开头定义:extern bank1 unsigned char var1, var2; /声明位于 bank1 的外部变量&O1540; volatile 易变型变量声明PICC 中还有一个变量修饰词在普通的 C 语言介绍中一般是看不到的,这就是关键词“volatile”。顾名思义,它说明了一个变量的值是会随机变化的,即使程序没有刻意对它进行任何赋值操作。在单片机中,作为输入的 IO 端口其内容将是随意变化的;在中断内被修改的变量相对主程序流程来讲也是随意变化的;很多特殊功能寄存器的值也将随着指令的运行而动态改变。所有这种类型的变量必须将它们明确定义成“

13、volatile”类型,例如:volatile unsigned char STATUS 0x03;volatile bit commFlag;“volatile”类型定义在单片机的 C 语言编程中是如此的重要,是因为它可以告诉编译器的优化处理器这些变量是实实在在存在的,在优化过程中不能无故消除。假定你的程序定义了一个变量并对其作了一次赋值,但随后就再也没有对其进行任何读写操作,如果是非volatile 型变量,优化后的结果是这个变量将有可能被彻底删除以节约存储空间。另外一种情形是在使用某一个变量进行连续的运算操作时,这个变量的值将在第一次操作时被复制到中间临时变量中,如果它是非 volati

14、le 型变量,则紧接其后的其它操作将有可能直接从临时变量中取数以提高运行效率,显然这样做后对于那些随机变化的参数就会出问题。只要将其定义成 volatile 类型后,编译后的代码就可以保证每次操作时直接从变量地址处取数。&O1540; const 常数型变量声明如果变量定义前冠以“const”类型修饰,那么所有这些变量就成为常数,程序运行过程中不能对其修改。除了位变量,其它所有基本类型的变量或高级组合变量都将被存放在程序空间(ROM 区)以节约数据存储空间。显然,被定义在 ROM 区的变量是不能再在程序中对其进行赋值修改的,这也是“const”的本来意义。实际上这些数据最终都将以“retlw”

15、的指令形式存放在程序空间,但 PICC 会自动编译生成相关的附加代码从程序空间读取这些常数,编程员无需太多操心。例如:const unsigned char name=”This is a demo”; /定义一个常量字符串如果定义了 “const”类型的位变量,那么这些位变量还是被放置在 RAM 中,但程序不能对其赋值修改。本来,不能修改的位变量没有什么太多的实际意义,相信大家在实际编程时不会大量用到。&O1540; persistent 非初始化变量声明按照标准 C 语言的做法,程序在开始运行前首先要把所有定义的但没有预置初值的变量全部清零。PICC 会在最后生成的机器码中加入一小段初始化

16、代码来实现这一变量清零操作,且这一操作将在 main 函数被调用之前执行。问题是作为一个单片机的控制系统有很多变量是不允许在程序复位后被清零的。为了达到这一目的,PICC 提供了“persistent”修饰词以声明此类变量无需在复位时自动清零,编程员应该自己决定程序中的那些变量是必须声明成“persisten”类型,而且须自己判断什么时候需要对其进行初始化赋值。例如:persistent unsigned char hour,minute,second; /定义时分秒变量经常用到的是如果程序经上电复位后开始运行,那么需要将 persistent 型的变量初始化,如果是其它形式的复位,例如看门狗

17、引发的复位,则无需对 persistent 型变量作任何修改。PIC 单片机内提供了各种复位的判别标志,用户程序可依具体设计灵活处理不同的复位情形。11.5.9 PICC 中的指针PICC 中指针的基本概念和标准 C 语法没有太多的差别。但是在 PIC 单片机这一特定的架构上,指针的定义方式还是有几点需要特别注意。&O1540; 指向 RAM 的指针如果是汇编语言编程,实现指针寻址的方法肯定就是用 FSR 寄存器,PICC 也不例外。为了生成高效的代码,PICC 在编译 C 原程序时将指向 RAM 的指针操作最终用 FSR 来实现间接寻址。这样就势必产生一个问题:FSR 能够直接连续寻址的范围

18、是 256 字节(bank0/1或 bank2/3),要覆盖最大 512 字节的内部数据存储空间,又该如何让定义指针?PICC 还是将这一问题留给编程员自己解决:在定义指针时必须明确指定该指针所适用的寻址区域,例如:unsigned char *ptr0; /定义覆盖 bank0/1 的指针bank2 unsigned char *ptr1; /定义覆盖 bank2/3 的指针bank3 unsigned char *ptr2; /定义覆盖 bank2/3 的指针上面定义了三个指针变量,其中指针没有任何 bank 限定,缺省就是指向 bank0 和 bank1;和一个指明了 bank2,另一个

19、指明了 bank3,但实际上两者是一样的,因为一个指针可以同时覆盖两个 bank 的存储区域。另外,上面三个指针变量自身都存放在 bank0 中。我们将在稍后介绍如何在其它 bank 中存放指针变量。既然定义的指针有明确的 bank 适用区域,在对指针变量赋值时就必须实现类型匹配,下面的指针赋值将产生一个致命错误:unsigned char *ptr0; bank2 unsigned char buff8; 程序语句:/定义指向 bank0/1 的指针/定义 bank2 中的一个缓冲区ptr0 = buff; /错误!试图将 bank2 内的变量地址赋给指向 bank0/1 的指针若出现此类错

20、误的指针操作,PICC 在最后连接时会告知类似于下面的信息:Fixup overflow in expression (.)同样的道理,若函数调用时用了指针作为传递参数,也必须注意 bank 作用域的匹配,而这点往往容易被忽视。假定有下面的函数实现发送一个字符串的功能:void SendMessage(unsigned char *);那么被发送的字符串必须位于 bank0 或 bank1 中。如果你还要发送位于 bank2 或 bank3 内的字符串,必须再另外单独写一个函数:void SendMessage_2(bank2 unsigned char *);这两个函数从内部代码的实现来看可

21、以一模一样,但传递的参数类型不同。按笔者的应用经验体会,如果你看到了“Fixup overflow”的错误指示,几乎可以肯定是指针类型不匹配的赋值所至。请重点检查程序中有关指针的操作。&O1540; 指向 ROM 常数的指针如果一组变量是已经被定义在 ROM 区的常数,那么指向它的指针可以这样定义:const unsigned char company=”Microchip”; const unsigned char *romPtr;程序中可以对上面的指针变量赋值和实现取数操作:romPtr company; /指针赋初值data = *romPtr+; /取指针指向的一个数,然后指针加 1/

22、定义 ROM 中的常数/定义指向 ROM 的指针反过来,下面的操作将是一个错误,因为该指针指向的是常数型变量,不能赋值。*romPtr data; /往指针指向的地址写一个数&O1540; 指向函数的指针单片机编程时函数指针的应用相对较少,但作为标准 C 语法的一部分,PICC 同样支持函数指针调用。如果你对编译原理有一定的了解,就应该明白在 PIC 单片机这一特定的架构上实现函数指针调用的效率是不高的:PICC 将在 RAM 中建立一个调用返回表,真正的调用和返回过程是靠直接修改 PC 指针来实现的。因此,除非特殊算法的需要,建议大家尽量不要使用函数指针。&O1540; 指针的类型修饰前面介

23、绍的指针定义都是最基本的形式。和普通变量一样,指针定义也可以在前面加上特殊类型的修饰关键词,例如“persistent”、“volatile”等。考虑指针本身还要限定其作用域,因此 PICC 中的指针定义初看起来显得有点复杂,但只要了解各部分的具体含义,理解一个指针的实际用图就变得很直接。 bank 修饰词的位置含义前面介绍的一些指针有的作用于 bank0/1,有的作用于 bank2/3,但它们本身的存放位置全部在 bank0。显然,在一个程序设计中指针变量将有可能被定位在任何可用的地址空间,这时,bank 修饰词出现的位置就是一个关键,看下面的例子:/定义指向 bank0/1 的指针,指针变

24、量为于 bank0 中unsigned char *ptr0;/定义指向 bank2/3 的指针,指针变量为于 bank0 中bank2 unsigned char *ptr0; /定义指向 bank2/3 的指针,指针变量为于 bank1 中bank2 unsigned char * bank1 ptr0; 从中可以看出规律:前面的 bank 修饰词指明了此指针的作用域;后面的 bank 修饰词定义了此指针变量自身的存放位置。只要掌握了这一法则,你就可以定义任何作用域的指针且可以将指针变量放于任何 bank 中。 volatile、persistent 和 const 修饰词的位置含义如果能

25、理解上面介绍的 bank 修饰词的位置含义,实际上 volatile、persistent 和 const 这些关键词出现在前后不同位置上的含义规律是和 bank 一词相一致的。例如:/定义指向 bank0/1 易变型字符变量的指针,指针变量位于 bank0 中且自身为非易变型volatile unsigned char *ptr0;/定义指向 bank2/3 非易变型字符变量的指针,指针变量位于 bank1 中且自身为易变型bank2 unsigned char * volatile bank1 ptr0;/定义指向 ROM 区的指针,指针变量本身也是存放于 ROM 区的常数const un

26、signed char * const ptr0;亦即出现在前面的修饰词其作用对象是指针所指处的变量;出现在后面的修饰词其作用对象就是指针变量自己。11.6PICC 中的子程序和函数中档系列的 PIC 单片机程序空间有分页的概念,但用 C 语言编程时基本不用太多关心代码的分页问题。因为所有函数或子程序调用时的页面设定(如果代码超过一个页面)都由编译器自动生成的指令实现。11.6.1 函数的代码长度限制PICC 决定了 C 原程序中的一个函数经编译后生成的机器码一定会放在同一个程序页面内。中档系列的 PIC 单片机其一个程序页面的长度是 2K 字,换句话说,用 C 语言编写的任何一个函数最后生成

27、的代码不能超过 2K 字。一个良好的程序设计应该有一个清晰的组织结构,把不同的功能用不同的函数实现是最好的方法,因此一个函数 2K 字长的限制一般不会对程序代码的编写产生太多影响。如果为实现特定的功能确实要连续编写很长的程序,这时就必须把这些连续的代码拆分成若干函数,以保证每个函数最后编译出的代码不超过一个页面空间。11.6.2 调用层次的控制中档系列 PIC 单片机的硬件堆栈深度为 8 级,考虑中断响应需占用一级堆栈,所有函数调用嵌套的最大深度不要超过 7 级。编程员必须自己控制子程序调用时的嵌套深度以符合这一限制要求。PICC 在最后编译连接成功后可以生成一个连接定位映射文件(*.map)

28、,在此文件中有详细的函数调用嵌套指示图“call graph”,建议大家要留意一下。其信息大致如下(取自于一示范程序的编译结果):Call graph:*_main size 0,0 offset 0 _RightShift_C* _Task size 0,1 offset 0 lwtoft ftmul size 0,0 offset 0 ftunpack1 ftunpack2 ftadd size 0,0 offset 0 ftunpack1 ftunpack2 ftdenorm例 11-4 C 函数调用层次图上面所举的信息表明整个程序在正常调用子程序时嵌套最多为两级(没有考虑中断)。因为m

29、ain 函数不可能返回,故其不用计算在嵌套级数中。其中有些函数调用是编译代码时自动加入的库函数,这些函数调用从 C 原程序中无法直接看出,但在此嵌套指示图上则一目了然。11.6.3 函数类型声明PICC 在编译时将严格进行函数调用时的类型检查。一个良好的习惯是在编写程序代码前先声明所有用到的函数类型。例如:void Task(void);unsigned char Temperature(void);void BIN2BCD(unsigned char);void TimeDisplay(unsigned char, unsigned char);这些类型声明确定了函数的入口参数和返回值类型,

30、这样编译器在编译代码时就能保证生成正确的机器码。笔者在实际工作中有时碰到一些用户声称发现 C 编译器生成了错误的代码,最后究其原因就是因为没有事先声明函数类型所致。建议大家在编写一个函数的原代码时,立即将此函数的类型声明复制到原文件的起始处,见例 11-1;或是复制到专门的包含头文件中,再在每个原程序模块中引用。11.6.4 中断函数的实现PICC 可以实现 C 语言的中断服务程序。中断服务程序有一个特殊的定义方法:void interrupt ISR(void); 其中的函数名“ISR”可以改成任意合法的字母或数字组合,但其入口参数和返回参数类型必须是“void”型,亦即没有入口参数和返回参

31、数,且中间必须有一个关键词“interrupt”。中断函数可以被放置在原程序的任意位置。因为已有关键词“interrupt”声明,PICC 在最后进行代码连接时会自动将其定位到 0x0004 中断入口处,实现中断服务响应。编译器也会实现中断函数的返回指令“retfie”。一个简单的中断服务示范函数如下:void interrupt ISR(void) /中断服务程序 if (T0IE & T0IF) T0IF = 0; /在此加入 TMR0 中断服务 /判 TMR0 中断/清除 TMR0 中断标志 if (TMR1IE & TMR1IF) /判 TMR1 中断 TMR1IF0; /在此加入 T

32、MR1 中断服务 /清除 TMR1 中断标志/中断结束并返回例 11-5 C 语言中断函数举例PICC 会自动加入代码实现中断现场的保护,并在中断结束时自动恢复现场,所以编程员无需象编写汇编程序那样加入中断现场保护和恢复的额外指令语句。但如果在中断服务程序中需要修改某些全局变量时,是否需要保护这些变量的初值将由编程员自己决定和实施。用 C 语言编写中断服务程序必须遵循高效的原则:&O1540; 代码尽量简短,中断服务强调的是一个“快”字。&O1540; 避免在中断内使用函数调用。虽然 PICC 允许在中断里调用其它函数,但为了解决递归调用的问题,此函数必须为中断服务独家专用。既如此,不妨把原本

33、要写在其它函数内的代码直接写在中断服务程序中。&O1540; 避免在中断内进行数学运算。数学运算将很有可能用到库函数和许多中间变量,就算不出现递归调用的问题,光在中断入口和出口处为了保护和恢复这些中间临时变量就需要大量的开销,严重影响中断服务的效率。中档系列 PIC 单片机的中断入口只有一个,因此整个程序中只能有一个中断服务函数。11.6.5 标准库函数PICC 提供了较完整的 C 标准库函数支持,其中包括数学运算函数和字符串操作函数。在程序中使用这些现成的库函数时需要注意的是入口参数必须在 bank0 中。如果需要用到数学函数,则应在程序前 “#include ” 包含头文件;如果要使用字符

34、串操作函数,就需要包含“#include ”头文件。在这些头文件中提供了函数类型的声明。通过直接查看这些头文件就可以知道 PICC 提供了哪些标准库函数。C 语言中常用的格式化打印函数“printf/sprintf”用在单片机的程序中时要特别谨慎。printf/sprintf 是一个非常大的函数,一旦使用,你的程序代码长度就会增加很多。除非是在编写试验性质的代码,可以考虑使用格式化打印函数以简化测试程序;一般的最终产品设计都是自己编写最精简的代码实现特定格式的数据显示和输出。本来,在单片机应用中输出的数据格式都相对简单而且固定,实现起来应该很容易。对于标准 C 语言的控制台输入(scanf)输

35、出(printf)函数,PICC 需要用户自己编写其底层函数 getch()和 putch()。在单片机系统中实现 scanf/printf 本来就没什么太多意义,如果一定要实现,只要编写好特定的 getch()和 putch()函数,你就可以通过任何接口输入或输出格式化的数据。11.7PICC 定义特殊区域值PICC 提供了相关的预处理指令以实现在原程序中定义单片机的配置字和标记单元。11.7.1 定义工作配置字在原程序中定义 PIC 单片机工作配置字的重要性在前面章节中已经阐述。在用 PICC 写程序时同样可以在 C 原程序中定义,具体方式如下:_CONFIG (HS & UNPROTEC

36、T & PWRTEN & BORDIS & WDTEN); 上面的关键词“_CONFIG”(注意前面有两个下划线符)专门用于是芯片配置字的设定,后面括号中的各项配置位符号在特定型号单片机的头文件中已经定义(注意不是 pic.h头文件),相互之间用逻辑“与”操作符组合在一起。这样定义的配置字信息最后将和程序代码一起放入同一个 HEX 文件。在这里列出了适用于 16F7x 系列单片机配置位符号预定义,其它型号或系列的单片机配置字定义方式类似,使用前查阅一下对应的头文件即可。/*振荡器配置*/ #define RC #define HS 0x3FFF / RC 振荡0x3FFE / HS 模式#de

37、fine XT #define LP /*看门狗配置*/ 0x3FFD / XT 模式0x3FFC / LP 模式#define WDTEN 0x3FFF / 看门狗打开#define WDTDIS/*上电延时定时器配置*/#define PWRTEN0x3FFB / 看门狗关闭0x3FF7 / 上电延时定时器打开#define PWRTDIS 0x3FFF / 上电延时定时器关闭/*低电压复位配置*/#define BOREN 0x3FFF / 低电压复位允许#define BORDIS/*代码保护配置*/ 0x3FBF / 低电压复位禁止#define UNPROTECT 0x3FFF /

38、 没有代码保护#define PROTECT 0x3FEF / 程序代码保护例 11-6 头文件预定义的配置信息符号11.7.2 定义芯片标记单元PIC 单片机中的标记单元定义可以用下面的_IDLOC(注意前面有两个下划线符)预处理指令实现,方法如下:_IDLOC (1234);其特殊之处是括号内的值全部为 16 进制数,不需要用“0x”引导。这样上面的定义就设定了标记单元内容为 01020304。11.8MPLAB-IDE 中实现 PICC 的编译选项设置在 11.3 节中已经介绍了如何实现 PICC 和 MPLAB-IDE 开发平台的挂接。一旦项目建立成功、程序编写完成后即可以通过 MPL

39、AB 环境下的项目管理工具实现程序的编译、连接和调试。它们的含义分别是:项目维护(Make):MPLAB 检查项目中的原程序文件,只编译那些在上次编译后又被修改过的原程序,最后进行连接;项目重建(Build All):项目中的所有原程序文件,不管是否有修改,都将被重新编译一次,最后进行连接。也可以通过 Project 菜单选择“Make”或“Build All”实现项目编译。不管采用何种方式,在启动编译过程前一般都要设定一些编译选项。11.8.1 选择单片机型号在选择 PICC 作为语言工具并建立了项目后,同样通过菜单项 Configure&O1616;Select Device在 MPLAB

40、 环境中选择具体单片机型号。请回顾一下例 11-1 的代码,我们在原程序一开始使用了“#include ”实现了相关单片机的一些预定义符号的直接引用,但没有具体指明是哪一个型号。实际上,“pic.h”头文件只是一个简单的管理工具(条件判别),它会按照MPLAB 所选择的特定型号的单片机,把真正对应的头文件包含进来。有兴趣者可以直接用文本编辑工具打开 pic.h 文件查看其是如何根据不同的单片机型号包含对应的头文件。这样对编程员而言,程序中只需加上一句“#include ”即可。11.8.2 PICC 普通编译选项(General)设定参考第三章 3.2.7 节的内容和图 3-20 的指示说明,

41、启动编译选项设定对话框。在使用PICC 语言工具时对话框的内容和用 MPAMS 汇编工具相比完全不同。图 11-3 为 PICC 编译环境下普通选项设定的界面。在此界面中用户唯一能改变的是编译器查找头文件时的指定路径(Include Path),实际上如果编译器安装没有问题,在此界面中这些普通选项的设定无需任何改动,编译器会自动到缺省认定的路径中(编译器安装后的相关路径)查找编译所需的各类文件。 图 11-3 PICC 普通选项设定图 11-4 PICC 全局选项设定11.8.3 PICC 全局选项设定(PICC Global)全局选项将影响项目中所有 C 和汇编原程序的编译,详细的设定内容见

42、图 11-4。其中必须关注的有:&O1540; Compile for MPLAB ICD:如果你准备用 ICD 调试 C 语言编译后的代码,那么此项就必须打钩选中。这样编译后的结果就能保证 ICD 本身使用的芯片资源(一小部分的程序和数据空间)不被应用程序所占用。&O1540; Treat char as signed:为了提高编译后的代码效率,PICC 缺省认定char型变量也是无符号数。如果在设计中需要使用带符号的char型变量,此项就应该被选中。&O1540; Floating point double width:同样为了提高编译后的代码效率,PICC 缺省认定double型的双精度

43、浮点数变量的实现长度为 24 位(等同于普通 float 型浮点数)。在这里可以选择使其长度达 32 位。这样数值计算的精度将得到提高,但代码长度将增加,计算速度也会降低,所以请在权衡利弊后作出你自己的决定。11.8.4 C 编译器选项设定(PICC Compiler)项目中所有的 C 原程序都将通过 C 编译器编译成机器码,这些选项决定了 C 编译器是如何工作的。所有选项又分为两组:普通选项(General)和高级选项(Advanced),分别见图 11-5A 和 11-5B。C 编译器的普通选项最重要的就是针对代码优化的设定。如果没有特殊原因,应该设定全局优化级别为 9 级(最高级别优化)

44、,同时使用汇编级优化,这样最终得到的代码效率最高(长度和执行速度两方面)。按笔者的使用经验,仅从代码长度去比较,使用最高级别优化后代码长度至少可以减少 20%(2K 字以上的程序)。而且 PICC 的优化器相当可靠,一般 (A) 常用选项 (B) 高级选项 图 11-5 C 编译器选项设定不会因为使用优化从而使生成的程序出现错误。碰到的一些问题也基本都是用户编写的原程序有漏洞所导致,例如一些变量应该是 volatile 型但编程员没有明确定义,在优化前程序可以正常运行,一旦使用优化,程序运行就出现异常。显然,把出现的这些问题归罪到编译器是毫无道理的。使用优化后可能对原程序级的调试带来一些不便之处。因 PICC 可能会重组编译后的代码,例如多处重复的代码可能会改成同一个子程序调用以节约程序空间,这样在调试

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!