gned 类型,如果为“UL”,则为 unsigned long。
浮点常量将有两种类型,除非有明确的后缀“L”或者“l”表示其为 double 类型,“F”或者“f”表示其为 FLOAT 类型。
字符串常量或者字符串数据都用双引号来表示比如用“Hello world”。
用 const char 来定义一个字符串常量,并把这些数据存储在程序区。
把一串字符串常量分派给一个非常数字符指针,编译器会产生警告,比如:char cp quotonequot // quotonequot in ROM 产生警告const char ccp quottwoquot // quottwoquot in ROM 正确定义一个非常量的字符数组可以采用如下方式:char ca quottwoquot // quottwoquot different to the above则将在 RAM 中初使化 two,two 从程序中拷贝而来。
两段分离开的常数则由编译器自动链接。
比如中间只空一格的如下表达:const char cp quothello quot quotworldquot将把quothello worldquot分配给 cp。
3.4.2 位数据类型和变量PICC18 用关键字 bit 来声明一个位变量,只存储 0 或者 1。
如果加上 static,且在函数内声明,则只可在函数内部使用,例如:static bit init_flag如果在函数外声明,例如,bit init_flag则为全局函数。
位变量不能定义为一个局部变量,“auto”。
所以当在函数内部定义一个位变量,包括 main 函数,一定要加上 static 声明其为局部静态变量,如上所示范。
位变量也不能做为一个函数的参数。
但是,一个函数可以定义为 bit 类型来返回一个位的值。
这个位变量值将放在 STATUS 寄存器的 C 位返回。
位变量在很多时候表现得和无符号字符型变量很相似,但他储存 0 和 1,所以这提供了一个方便高效的方法来存储布尔符号而不需要消耗大量的 RAM 空间。
尽管如此,不存在指向一个位变量的指针,也不能静态初使化位变量。
把一个整形变量整体赋值给一个位变量,则最后一位将赋值给该位变量,这和 ANSI C 对布尔类型的转换是不一样的。
比如:int data 0x54bit bitvarbitvar data由于 data 的最低位为 0,所以 bitvar 将为 0。
如果你想用类似 ANSI C 对布尔变量类型转换时候的操作,即把整形数赋值给位变量,位变量为 0 还是 1,取决于原始的整形数据是否为 0,则可以采用如下语法:bitvar data 0位变量在启动代码会被强制清 0,如果你想对一个单独的位变量给非 0 的初值,请在自己的用户代码中处理。
而不能指望在定义的时候给初值就可。
如果使用了——strict 编译选项,则位变量不可用。
3.4.3 Using Bit-Addressable Registers本章节介绍如何强制定位一个位变量到某个地址,一般这只对特殊寄存器有用,不建议对变量做这样的操作,具体形式可以参考 MCU 的头文件中对特殊功能寄存器各个位的定义,比如static unsigned char RCON 0xFD0static near bit PD unsignedampRCON823.4.4 8 位整形数据类型和变量PICC18 同时支持有符号和无符号字符型(signed char and unsigned char),如果关键字 signed 和 unsigned 没有标明, char 默认状态下为 unsigned char。
则 但如果使用了--CHARsigned,则 char 表示 signed char。
后续的英文原始文档不过再次强调一个观点,所谓的字符型,实际上应该完全看作一个 8 位的整形,对字符型的操作和对 8 位整形的操作没有什么区别,就是符号型和整形之间是有天然的转换关系。
比如你可以写 char XXX’A’也可以写 char XXX0X41。
这两者都是等效的。
XXX 在内存中的表示形式都是 0X41。
对这点如果有不太熟悉的,可以参考潭浩强的 C 语言教材。
3.4.5 16 位整形数据类型和变量翻译略。
编程无特殊注意事项。
3.4.6 32 位整形数据类型和变量翻译略。
编程无特殊注意事项。
3.4.7 Floating Point Types and Variables数据的存储遵照如下格式。
浮点类型一般为有符号型,所以采用无符号声明一个浮点数是非法的。
通过编译选项--doublefast32 可以有效提高浮点计算的速度,但以程序区的空间增大为代价。
在 MPLAB IDE 下,需要注意设置观察变量的属性,才能正确观察浮点数。
具体方法如下:以定义了一个 double vat10000;的浮点数(不是整形)的观察为例子。
首先,HI-TECH 的编译器支持 32 位,但是为了节约空间提高运算效率,在不对编译器选项做设置的情况下,即使是 double,不过是 24 位。
另外 HI-TECH 采取的是IEEE754 规范。
由于各个编译器厂家采取的浮点规范略有不同,就导致了我们在观察的时候需要注意观察属性的设置。
现在见附图。
使用 MPLAB IDE 英文版用户,可参造找到适当的位置。
3.4.8 结构体和成员体结构体和联合体,除了单独的位变量不能做为其成员,使用上和标准 C 没什么区别。
3.4.8.1 位结构体在汇编语言的情况下,我们会把几个位变量放在一个字节内。
以方便管理。
PICC18 提供了更方便的位结构体类型。
在位结构体中,你可以在任意位定义单独的变量,并定义多个位的位段。
这和标准 C 也是类似的。
例如:struct unsigned lo : 1unsigned dummy : 6unsigned hi : 1 foolo 定义在 bit0(最低位),hi 定义在 bit7(最高位)。
如果你只想在 bit0 和 bit7 定义,中间六位暂时不想使用,可简化定义为:struct unsigned lo : 1unsigned : 6unsigned hi : 1 foo而初使化则可以这样:struct unsigned lo : 1unsigned mid : 6unsigned hi : 1 foo 1 8 0则 foo 在的单元实际上为实际上为 0 001000 1 ,即 0x11。
3.4.8.2 结构体和联合体的限制如果整个结构体为常量,则全部数据将仿在程序区,显然,将只能读出。
如果这样,所有的成员必须被初使化。
例如:const struct int numberint ptr record 0x55 ampi如果某个结构体的内部成员为常量,但结构体不是常量,则整个结构体将放在 RAM 中,但每个成员都变成只读。
比如:struct const int numberint const ptr record 0x55 ampi3.4.9 标准类型限制PICC18 支持 ANSI C 的限制以及为嵌入式专门设置的一些关键字。
3.4.9.1 Const and Volatile Type Qualifiersconst 会告诉编译器,该变量为只读,无法修改。
常量被定义的时候就必须初使化。
volatile 用来告诉编译器一个参量成功访问后也未必能获得值,这能避免启动代码去错误操作它。
一般用于特殊寄存器的定义。
3.4.10 特殊类型限定PICC18 提供了一些特殊的限定字来把变量分配到特定的 RAM 空间。
包括 persisten, near , far。
这些限定也可以用在指针上。
但是不能用在局部自动变量上。
如果一定要用在局部变量上,只能用在局部静态变量上。
如:static persistent int intvarPICC18 依然支持关键字 bank1bank2bank3,这些关键字的存在是为了让代码能无缝地从 PICC(支持 PIC12/16/17 系列的编译器)移植到 PICC18。
PICC18 允许这些限定字,但这些限定不会对变量的定位发生任何影响。
3.4.10.1 Persistent 类型限定该类型告诉编译器,在上电复位的时候这些变量不应该被自动清 0。
比如特殊功能寄存器,都加了此限定字。
如果要实现某些功能,需要某些特殊变量在上电的时候不被清 0,则可加此关键字进行限定。
3.4.10.2 Near 类型限定near 类型用来把局部静态变量指定到 PIC18 的
ACCESS BANK。
如:static near unsigned char fred3.4.10.3 Far 类型限定FAR 是为了把变量定义在外扩的 ROM。
不推荐使用。
只有支持外扩的 MCU 才支持FAR 类型。
3.4.11 Bdata 类型限定该关键字只在程序采用 small mode 编译时有意义。
在这样的模式下,所有的局部静态和全局变量都放在
ACCESS BANK,bdata 则能限制这些变量放在非
ACCESS区。
然后这些变量就表现得和在 large mode 下一样。
这些能防止
ACCESS BANK在 small mode 下溢出,以免更换到 large mode 模式编译。
3.4.12 指针类型PICC18 支持两种基本指针,数据指针,函数指针。
数据指针存储变量的地址,以使变量可以为程序读写修改。
函数指针存储可执行子函数的入口,以便通过指针间接调用。
3.4.12.1 RAM 指针RAM 指针为 16 位,可以寻址 PIC18 全空间的 RAM。
指向 near 的指针只有 8 位,只能访问 near 变量(存储在
ACCESS RAM 的变量)。
3.4.12.2 Const and Far Pointers常量和 FAR 指针,可为 16 位或者 24 位,这由编译选项--CP24 或者 --CP16 决定。
项目中的所有模块必须采用同样宽度的指针。
指针指向 FAR 变量和常量是基本一样,只有一点不同,指向 FAR 变量的,可能用来改变所指向的内容,指向常量的是绝对不行的。
16 位的常量和 FAR 指针可以访问全部的 RAM 空间和大部分的程序空间(64K 字节以内)。
在运行时,指针的内容将被检查。
地址范围超过 RAM 区上限的,将采用表读表写指令访问程序区,小于 RAM 区上限的则访问 RAM 区。
如果常量指针保存的地址在 RAM 区,RAM 的该地址的内容不应当变化。
默认情况下,链接选项会把常量放在 RAM 的地址上限,以保证访问正确的存储空间。
当目标 MCU 的程序区超过 64K 字节,只有低 64K 字节能用 16 位指针访问。
后续内容为 24 位指针,牵涉到 CONFIG 区操作,翻译暂缓。
3.4.12.3 函数指针翻译暂略,内容与上面基本一致,讲述了 16 位指针与 24 位指针的不同,但没有给出具体的使用例程。
3.4.12.4 联合类型限定与指针类型限定可用来限定指针本身的类型以及指针指向的变量的类型。
举例如下:near int nip int near inp near int near ninp nip 是指所指向的变量为 near int,即存储在
ACCESS RAM,则指针本身为 8 位,但是会存在全部 RAM BANK 的某些地方。
inp 是指指向的变量为 int,则可能在 RAM 的任何一个角落,则指针需要为 16 位,但加了 near 限定后,指针变量将放在
ACCESS RAM。
ninp 则指用存储在
ACCESS RAM 的 8 位指针,指向存储在
ACCESS RAM 的变量。
其他限定词带来的变量存储,指示,如上所示范。
为了兼容 PICC,PICC18 允许 BANK1,BANK2,BANK3 这些关键字的存在,但是这些关键字不影响 PICC18 的代码。
3.5 存储类型和参数分配与标准 C 基本相同,无重要信息,暂时不翻译,请查看英文文档。
3.6 函数与编程操作基本无关,无重要信息,暂时不翻译,请查看英文文档。
3.7与编程操作基本无关,无重要信息,暂时不翻译,请查看英文文档。
3.8 操作数3.8.1 整形提升整形提升是值得认真学习的。
C不比汇编,编译器有时会自动扩充变量长度,以做中间计算使用,每款单片机的C编译器,都必须充分学习其整形提升的语法规则。
否则则请大量使用中间变量,或者手动控制整形提升。
笔者初次独立编写PID和一些数学处理函数,就死在了对整形提升没有认真体会上。
当数学算式中存在不只一个操作数时,典型情况下它们的类型应当严格一致,否则编译器会自动进行类型转换。
转换的原则是向“大”的方向转。
即使操作数都是同样的类型,但在某些情况下,也会发生整型提升。
如果你不注意的话,那么异常的结果就发生了。
整形提升会在枚举类型,有符号无符号字符型,有符号无符号整形的变量下发生。
例如:unsigned char count a0 b50ifa - b lt 10counta-b 的结果是 206(这个结果不是比 10 小),因为 ab 在进行减法前都被转化成 signed int 类型了。
然后再从-50 转换成了 unsigned int。
实际上,很多情况下,一个变量的范围都是受限制的,并不会达到其类型的上下限。
按笔者的经验,这段代码可以改造为如下。
unsigned int temp_bbtemp_b10ifalttemp_bcount因为 ab 本身就为 8 位,所以转换一个就够了。
为了避免下溢(出现负号,出现负号则需要进行有符号计算,比较浪费代码),强烈建议采用这样的无符号提升,并做加法处理。
再看一个例子:unsigned char count cc 0x55if c 0xAAcount似乎理论上对 c 取反,8 位下,55 取反应该就是 0XAA,但是编译器做了整形提升,结果为 0XFFAA,出错了。
那么其实可以用变通的写法。
unsigned char count cc 0x55ccif c 0xAAcount由于 C 取反又给了 C,所以没有整形提升,则判断不出错。
我的观点是,在不是很了解编译器什么时候进行整形提升时,我们尽量避免在判断语句中进行计算后的比较判定。
而只做简单的判定。
另外,用对 0XFF 的异或,来取代求反。
或者用类似的宏汇编来完成求反。
3.8.2 移位过程中的提升这里的关键是对有符号数进行移位的时候会发生什么。
无符号数则与 ANSI C 是一致的。
如果需要直接和汇编指令挂钩的操作,可以采用系统定义的宏或者自己用嵌入式汇编。
ANSI C,对于有符号数右移时,符号位可能被清 0,或者保持。
(应该是取决于 C编译器的版本)。
右移动有符号数,PICC18 按上述的后者进行,即先整体移动,然后保持符号位。
右移动无符号数,最高位清 0。
左移动无符号或者有符号数,最低为清 0。
3.8.3 除以一个整数和对一个整数求模(取余数)除 0 将导致结果为 0。
3.9 PSECT 用法没研究清楚,暂时不翻译。
3.10 中断的处理高中断的声明和 PICC 一致,用关键字 interrupt。
低.
上一篇:
【精品】用VB绘制自己的矢量地图
下一篇:
幻象符号的政治经济学