picc使用注意事项

上传人:第*** 文档编号:37707247 上传时间:2018-04-21 格式:DOC 页数:8 大小:23.40KB
返回 下载 相关 举报
picc使用注意事项_第1页
第1页 / 共8页
picc使用注意事项_第2页
第2页 / 共8页
picc使用注意事项_第3页
第3页 / 共8页
picc使用注意事项_第4页
第4页 / 共8页
picc使用注意事项_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《picc使用注意事项》由会员分享,可在线阅读,更多相关《picc使用注意事项(8页珍藏版)》请在金锄头文库上搜索。

1、介绍 PIC 系列单片机 C 语言的发展,并以 HI-TECH Software 公司的 HI-TECH PICC 为例介绍了 PICC 编译器的特点和用其开发 PIC 系列单片机时的应注意的一些问题。目前在市场上应用最广泛的应该属于 8 位单片机,Microchip Technoloogy 公司推出的 8 位 PIC 系列单片机目前在国内市场上深受用户欢迎,已经逐渐成为单片机应用的新潮流, 但遗憾的是,目前国内介绍它的 C 语言开发工具的书籍和文章却比较少,而且用的人也不 多,广大的程序员在用其开发的过程中都在慢慢摸索,可能会走一些弯路,笔者最近在用 PIC 的 C 语言时就遇到了好些问题,

2、在这里笔者想就最近一段时间用 PIC 的 C 语言的一些经 验和广大的底层软件程序员做一下交流和介绍,希望本文对用 PICC 开发 PIC 系列单片机的 人有所帮助。 目前在国内用的比较多的是 Hi-Tech 的 HI-TECH PICC 编译器,而且目前市场上一些国内的 PIC 单片机仿真器也开始支持 HI-TECH PICC 编译格式,因此本文主要以 Hi-Tech 的 PICC 为基 础介绍一下 PIC 的 C 语言的基本特点。HI-TECH PICC 的 C 语言开发工具的语言特点PICC 的 C 语言按 ANSI C 来定义,并进行了 C 语言的扩展,PICC 和 ANSI C 有一

3、个根本 的区别就是 PICC 不支持函数的递归调用,这是因为 PIC 单片机内的堆栈大小是由硬件决定 的,资源有限,所以不支持递归调用。它的数据也遵从标准 C 的数据结构,PICC 的数据结 构是以数据类型的形式出现的。PICC 编译器支持的数据类型有位类型(bit) 、无符号字符 (unsigned char) 、有符号字符(signed char) 、无符号整形(unsigned int) 、有符号整形 (signed int) 、无符号长整型(unsigned long) 、有符号长整型(signed long) 、浮点 (float)和指针类型等,需要注意的是,PICC 支持的多字节数

4、据都采用低字节在前,高字 节在后的原则,即一个多字节数,比如 int 型,在内存单元中存储顺序为低位字节存储在 地址低的存储单元中,高位字节存储在地址高的存储单元中,程序员在用 union 定义变量 时一定要注意这一特点。PIC 的 C 语言变量分为局部变量和全局变量,所有变量在使用前必须先定义后使用。 全局变量是在任何函数之外说明的、可被任意模块使用的、在整个程序执行期间都保持有 效的变量;局部变量在函数内部说明,局部变量有两种:自动变量和静态变量,缺省类型 为自动变量,除非明确将其声明为静态变量,而且,所有的自动变量都被分配在寄存器页 0,所以 bank 限定词不能用于自动变量,但可以用于

5、静态的局部变量,当程序退出时,自 动变量占用的空间释放,自动变量也就失去意义;静态变量是一种局部变量,因此只在声 明他的函数内部有效,但它占用固定的存储单元,而这个存储单元不会被别的函数使用, 因此其它函数可以通过指针访问或修改静态变量的值;静态变量在程序开始只初始化一次, 因此若需只在某函数内部使用一变量,而又希望其值在 2 次函数调用期间保持不变,为实 现程序模块化,则可将其声明为静态变量。例如以下声明中,有些为合法,有些为非法: void max(void) unsigned char var1; /合法声明 unsigned char bank1 var2; /非法声明 static

6、unsigned char bank1 var3; /合法声明 unsigned char var4 = 0x02; /合法声明,每次调用都初始化 static unsigned char bank1 var5 = 0x02; /合法声明,但只初始化一次PICC 编译器对局部变量及传递参数使用 RAM 覆盖技术,编译时,连接器会自动把一 些不可能被同时调用的函数的自动变量区重叠在一起,以达到内存的高效利用,因此其内 部 RAM 的利用效率非常高。1、位变量的使用 需要说明的是虽然 PICC 允许利用 bit 定义位变量,比如: static bit init_flag;但位变量不能定义为自变量

7、,也能不能作为函数参数,但可以作为函数的返回值。而且位 变量也不能被静态初始化。比如若只想在某一个函数中使用位变量 flag,用如下两种方法 都是错误的:void max(void) bit flag; /非法,位变量不能定义为局部自变量 void max(void) static bit flag = 1; /非法,位变量不能被静态初始化 PICC 支持在结构中定义位成员,位成员按最低有效位在前的方式存储,位成员总是以 8bit 为单位进行分配,当当前字节分配满后再分配下一个字节,但位成员不会跨字节存放.,例 如定义:struct unsigned lo: 1; unsigned mid:

8、1; unsigned hi: 7; flag 0x60;结构 flag 占用两个单元 0x60 和 0x61, lo 分配到 0x60 单元的第 0 位, mid 分配到 0x60 单元的 第 1 位, 由于位成员不会跨字节存放,故 hi 分配到 0x61 单元的 0-6 位(第 6 位为最高有效 位),而 0x60 单元的 2-7 位则跳过。 当然,上述的结构定义也可不使用绝对地址定义: struct unsigned lo: 1; unsigned mid: 1; unsigned hi: 7; flag;另外,不使用的位可用未命名的位成员来定义, 如果我们不使用 mid, 就可定义为:

9、struct unsigned lo: 1; unsigned : 1; unsigned hi: 7; flag;如果将一个整型数赋给位变量,只是将最低位赋给位变量,如果你是想要将一个整型 变量是否为 0 赋值给一个位变量,必须用: bitvar = (char_var != 0);而不能象有些编译器那样可以用:bitvar = char_var; 也不能用类型强制转换:bitvar = (bit)char_var;2、绝对地址变量的定义在某些特殊情况下,程序员可能不需要 PICC 动态分配某些特殊的全局或静态的局部变 量,而使用address 结构定义全局或静态的局部变量,例如: stat

10、ic unsigned char var1 0x60;定义了一个称为 var1 的变量,使其定位于单元 0x60,但是需要程序员注意的是,编译 器并不保留任何存储空间,而只是将此变量分配到此地址,在编译时,编译器也不能给出 任何的警告或错误提示,因此程序员在用绝对地址定义变量时,应该自己查看编译器产生 的映象文件或符号表,必须保证绝对变量被分配了唯一的地址,尤其是当此绝对地址正好 落在了 PICC 分配的自动变量区时,查错是很困难的。当然简单的方法就是程序员自己使用 高端的一块寄存器区定义绝对变量,因为,PICC 的变量先从低端分配的。3、使用可位寻址绝对地址变量 在某些特殊情况下,为编程方便

11、,程序员可能需要定义如下变量: static unsigned char flag_var; /非法 static bit flag0 (unsigned) static bit flag1 (unsigned) static bit flag2 (unsigned) static bit flag3 (unsigned) static bit flag4 (unsigned)程序员希望这个变量(假设是故障标志)既可以按字节访问,也可按位访问,这在有些编 译器中是可以的,但是在 PICC 中这样定义是不合法的,而只有将 flag_var 按如下绝对地址 变量定义才可以定义可位寻址位: stat

12、ic unsigned char flag_var 0x7f; static bit flag0 (unsigned) 但这样定义以后 flag_var 就成为绝对地址变量,就要程序员自己来保证此地址不会和 PICC 自己分配的变量冲突,这又带来一定的麻烦,经笔者测试,要解决此问题,还有一种方法, 那就是使用联合和结构位成员的方法,例如上例可如下定义: union struct unsigned flag0:1; unsigned flag1:1;unsigned flag2:1; unsigned flag3:1; unsigned flag4:1; bit_type; unsigned c

13、har byte_type;flag_var;这样定义以后,程序员既可以按照字节访问此故障标志,也可按位访问某一类型故障。例 如: flag_var.bit_type.flag0 = 1; /按位访问 if(flag_var.byte_type) /按字节访问 这两种访问都是合法的,而且程序员也不用在担心绝对地址是否有冲突的问题。 4、const 类型限定符 const 类型限定符用来通知编译器一个目标具有常数值,不能被改变,被 const 定义的常量 被放在 ROM 中,例如: unsigned char const var1 =“Microchip“; unsigned char cons

14、t var2 =0x00,0x01,0x02,0x03;这两种定义都是合法的,但若通过指针访问这些数组变量,必须将指针定义为常数字符指 针才能访问。例如某函数声明为: void func1(const unsigned char *ptr);则调用常数数组的方法为: void func2(void) func1(const unsigned char *)var1); 这一点程序员一定要认真对待,以免编译运行错误很难查找故障。5、可变型变量 volatile 类型限定符可变型变量 volatile 类型限定符用来通知编译器某一变量不能保证在连续访问的条件下, 其值不被改变,例如所有的与 I/O

15、 口有关的变量在编译器自带的头文件中都是被声明为 volatile 类型,如下所示: static volatile unsigned char PORTA 0x05;需要程序员注意的是有可能在中断时被改变的变量应该被定义为 volatile 类型,尤其是 编译时选择全局优化级别较高时,定义为 volatile 可以禁止编译器对此变量进行优化,这能 够防止编译器进行程序优化时,将认为明显多余的可变型变量删除,我们可以查看一下编 译后生成的编译列表文件就会发现,编译器对 volatile 目标的访问与对 non-volatile 的访问 是不同的, 如对 non-volatile 目标置 1 是

16、先将该变量清 0 后加 1, 而对 volatile 目标置 1 是先 将 1 放在 W 中后再将 W 赋值给可变型变量。6、persistent 类型限定符按 C 的标准, PICC 在编译时,所有的 C 变量在启动时都会调用 clear_ram 模块将其清为 0,但在某些情况下,程序员希望在处理器复位后仍保持一些变量的值,比如在做抗干扰处 理时,希望若是由于看门狗溢出造成的复位则保留变量的值,若还按照缺省定义,则 C 程 序无法实现,此时则可使用 persistent 类型限定符使被其限定的变量在启动时不被清 0,而 保留原有的值,程序员可在程序中根据看门狗的情况自己判断是否清零,例如可用如下方 法: persistent unsigned char var1;/定义为变量 var1 为 persistent 类型void initialization(void) /初始

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 其它办公文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号