第十一节 单片机C语言程序设计导入一C51对ANSIC的扩展C51扩展的关键字 C51有以下19个扩展关键字:at、sbit、sfr、bit、sfr16、idata.bdata、xdata、pdata、data、code、alien、small、compact、 large、usingreentrant、interrupt、 task 变量或数据类型[td]
数据类型 | 含 义 | 位数/bit | 字节数/B | 取值范围 | bit* | 位型 | 1 | 1/8 | 0或1 | signed char | 带符号字符型 | 8 | 1 | -128~127 | unsigned char | 无符号字符型 | 8 | 1 | 0~255 | enum | 枚举 | 8/16 | 1或2 | -128~127或-32768~32,767 | signed short | 带符号短型 | 16 | 2 | -32,768~32,767 | unsigned short | 无符号短型 | 16 | 2 | 0~65,535 | signed int | 带符号整型 | 16 | 2 | -32,768~32,767 | unsigned int | 无符号整型 | 16 | 2 | 0~65,535 | signed long | 带符号长整型 | 32 | 4 | -2,147,483,648~2,147,483,647 | unsigned long | 无符号长整型 | 32 | 4 | 0~429,4967.295 | float | 浮点型 | 32 | 4 | +1.175,494,E38~3.402,823,E+38 | sbit* |
| 1 | 1/8 | 0~1 | sfr* |
| 8 | 1 | 0x80~0xff | sfr16* |
| 16 | 2 | 0x80~0xff |
注:带*部分为C51所特别支持的变量类型(扩展的数据类型),它们不属于ANSIC,不能用指针对它们存取。包括: - bit:位变量,值为0或1。
- sbit:从字节中定义的位变量(0或1)。
- sfr:sfr字节地址(0x80~0xff)
- sfr16:sfr字地址(0x80~0xff,其实是占用两个连续的地址)。
其余的数据类型如char、enum、short、int、long、float等与ANSI C相同. bit型变量bit型变量可用于变量类型和函数声明、函数返回值等,存储于内部RAM的20H~2FH单元中。需要注意: - 位不能声明为一个指针。如bit *bit poiter;是错误的。
- 不能有bit数组如bit arr[5];是错误的。
可位寻址区说明使用sbit声明可独立访问可位寻址对象的位。sbit声明要求基址对象的存储器类型为“bdata”,否则只有绝对的位声明方法是合法的。
位的位置(“^”操作符号后的数字)的最大值依赖于指定的基类型
对char/unsigned char 而言是0~7
对于intunsignedint/short/unsigned short而言是0~15
对于long/unsigned long而言是0~31。 特殊功能寄存器(SFR)STC8H8K64U单片机的特殊功能寄存器(SFR)寻址区,用来控制定时1计数器、串口、I/0及其他部件。为了支持SFR及其可寻址位的声明,引入了sfr、sbit等关键词 内存区域的指定- 程序存储器
code关键字表示将变量保存到程序存储区。可以使用code定义表格常数,这样可以节省内部RAM的使用。例如,可以使用下面的代码保存共阴极数码LED的显示字模:
- unsigned char code
- led buf[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
复制代码
- 内部RAM
内部数据存储器用以下关键字说明:
- data:直接寻址区,内部RAM的低128字节,地址范围为00H~7FH。在用户程序中声明变量时,默认都保存在该区域。
- idata: 间接寻址区,包括整个内部RAM区256字节,地址范围为00H~0FFH。
- bdata:可位寻址区,地址范围为20H~2FH。
- 外部数据存储器
外部RAM视使用情况可由以下关键字标识:
- xdata:可指定多达64KB的外部直接寻址区,地址范围0000HOFFFFH。在用户程序中,需要声明较大的数组时,可以使用xdata关键字将变量数组保存到扩展RAM中。
- pdata:能访问1页(256B)的外部RAM(很少用)
Keil C51指针Keil C51支持一般指针(Generic Pointer)和存储器指针(Memory Specific Pointer)。一般指针的声明和使用均与标准C相同,同时还可以说明指针的存储类型。例如,下面的语句都声明pt为指向保存在外部RAM中unsigned char数据的指针,但pt本身的保存位置却不同: - unsigned char xdata *pt; //pt本身依存储模式存放
- unsigned charxdatadata pt; //pt被保存在内部RAM中
- unsigned char xdata *xdata pt; //pt被保存在外部RAM中
复制代码
基于存储器的指针,说明时即指定了存储类型,例如: - char data * str; //str指向data区中char型数据
- int xdata *pow; //pow指向外部RAM的int型整数
复制代码
除了和标准C语言一样使用指针外,指针还可以用来访问外部并行扩展的器件。例如,为了方便地访问外部存储器及I/0端口,在C51中的absacc.h头文件做了如下定义,利用这些定义可以方便地访问外部I/O端口。 - #define CBYTE ((unsigned char volatile code *) 0)
- #define DBYTE ((unsigned char volatile code *) 0)
- #define PBYTE ((unsigned char volatile code *) 0)
- #define XBYTE ((unsigned char volatile code *) 0)
复制代码
其中,volatile影响编译器编译的结果,volatile告诉编译器变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错。这样,如果变量是一个寄存器变量或者表示一个端口,使用volatile可以保证对特殊地址的稳定访问,不会出错。在stc8h.h文件中,对于位于扩展RAM区域的特殊功能寄存器的声明就使用了这样的方法。
例如P0口上拉电阻控制寄存器的声明如下: - #define P0PU (*(unsigned char volatile xdata *)0xfe10)
复制代码
单片机C语言程序中的常用运算关系运算符关系运算符用于比较两个常数或者表达式的大小。关系运算的结果只能是0或1。
关系运算符的值为真时,结果值为1:关系运算符的值为假时,结果值为0。 [td]
运算符 | 名称 | 功能 | 功能 | < | 小于 | a | 大于 | >= | 大于等于 | a>=b | a大于等于b时返回真;否则返回假 | == | 等于 | a==b | a等于b时返回真;否则返回假 | != | 不等于 | a!=b | a不等于b时返回真;否则返回假 |
特别注意,判断两个常数或者表达式相等时,使用“==”,不要使用单个的“=”否则,判断两个数是否相等就变成了赋值语句,编译时不会提示错误或警告,但执行结果般是不正确的。 逻辑运算符逻辑运算符包括与(&&)、或()、非(!)三种,用于对包含关系运算符的表达式进行合并或取非。对于使用逻辑运算符的表达式,返回0表示“假”,返回1表示“真” 位运算符很多应用程序常要求在位(bit)一级进行运算或处理。C语言提供了位运算的功能,这使得C语言也能像汇编语言一样用来编写系统程序。C语言提供了六种位运算符,分别为按位与(&)、按位或(|)、按位异或(^)、取反(~)、左移(<<)和右移(>>)。按位运算的数据长度与参与运算的变量类型有关。 - 按位与运算
按位与运算符“&”是双目运算符。其功能是参与运算的两个数或变量对应的二进位相只有对应的两个二进位均为1时,结果位才为1,否则为0。 - 按位或运算
按位或运算符“|”是双目运算符。应的两个二进位有一个为1时,结果为1,否则为0。 - 按位异或运算
按位异或运算符“^”是双目运算两个对应的二进位相异时,结果为1,否则为0。 - 求反运算
求反运算符“~”为单目运算符。其功能是对参与运算的数的各二进位按位求反 - 左移运算
左移运算符“<<”是双目运算符。其功能是把“<<”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0。 - 右移运算
右移运算符“>>”是双目运算符。其功能是把“>>”左边的运算数的各二进位全部右移若“>>”右边的数指定移动的位数。对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为1。## STC8H8K64U单片机C51程序框架
|