C51语言
C51语言与标准C语言间有许多相同地方,但也有自身特点。不同的嵌入式C语言编译系统之所以与标准C语言有不同的地方,主要是由于它们所针对的硬件系统不同。对于8051单片机,目前广泛使用的是C51语言。
C51语言基本语法与标准C相同,是在标准C的基础上进行适合8051内核单片机硬件的扩展,但与标准c又有不同之处:
- 库函数不同:
例如,在标准C中,库函数printf和scanf,常用于屏幕打印和接收字符,而在C51语言中,主要用于串行口数据的收发。
- 数据类型有一定区别:
例如,8051单片机包含位 *** 作空间和丰富的位 *** 作指令,因此,C51语言与标准C语言相比增加了位类型。
- C51语言变量存储模式与标准C语言中变量存储模式数据不同:
标准C最初是为通用计算机设计的,在通用计算机中只有一个程序和数据统一寻址的内存空间,而C51语言中变量的存储模式与8051单片机的各种存储器区紧密相关。
- 数据存储类型不同:
8051存储区可分为内部数据存储区、外部数据存储区以及程序存储区。
- 其他不同:
中断。标准C语言没有处理单片机中断的定义,而C51语言中有专门的中断函数。
头文件。C51语言头文件必须把8051单片机内部的外设硬件资源(如定时器、中断、I/O等)相应的特殊功能寄存器写入到头文件内,而标准C不用。
程序结构。由于8051单片机的硬件资源有限,它的编译系统不允许太多的程序嵌套。其次,标准C语言所具备的递归特性不被C51语言支持。
C51支持的基本数据
- 定义:临时变量只能定义在代码块的最开始,即”{“后面,且变量定义前不能有非定义语句。因为Keil能够在编译时就比较好确定栈内存,如果超过限定内存会报编译错误。(此处基于C89规范,C99没有此限制。)
- 申明:如果外部文件需要使用全局变量,使用extern来限定。
- 初始化:全局变量和局部变量,如果没有指定初始化值,默认为0。
- bit:位类型,bit指定的变量可以直接按拉寻址,所以需要特殊的内存匹配,即位寻址区(0x20—0x2F),可申明最多128个bit类型的变量。
- sfr:特殊功能寄存器(special function register),只能定义在函数体外,且必须指定特殊功能寄存器地址。
- sfr16:16位的特殊功能寄存器,可以完成一些需要16位的特殊功能。
- sbit:特殊功能寄存器位变量,是针对sfr的。但是因为位寻址效率的问题,所以只有地址为8倍数的sfr才可以被位寻址。sbit也只能定义在函数体外。
C51的注释写法有两种:
(1) //…… ,两个斜杠后面跟着的为注释语句,本写法只能注释一行,当换行时,必须在新行上重新写两个斜杠。
(2) ,一个斜杠与星号结合使用,本写法可注释任一行,即斜杠星号与星号斜杠之间的所有文字都作为注释,即注释有多行时,只需在注释的开始处,加斜杠星号,在注释的结尾处,加上星号斜杠即可。
加注释的目的是为了便于读懂程序,所有注释都不参与程序编译,编译器在编译过程中会自动删去注释。
C51语言允许通过使用关键字sfr、sbit或直接引用编译器提供的头文件来对特殊功能寄存器(SFR)进行访问,特殊功能寄存器分布在片内RAM高128字节中,只能采用直接寻址方式。
关键字定义sfr,使用很少一般都在头文件中定义了
C51中的运算符
C51中的运算符与通用C语言基本一致,常用的主要是位运算符、算术运算符、关系运算符、逻辑运算符和赋值运算符等,下面分别介绍这些运算符。
(1)位运算符
汇编语言对位的处理能力是很强的,但是C语言也能对运算对象进行按位 *** 作,从而使C语言也能具有一定的对硬件直接进行 *** 作的能力。位运算符的作用是按位对变量进行运算,但是并不改变参与运算的变量的值。如果要求按位改变变量的值,则要利用相应的赋值运算。还有就是位运算符是不能用来对浮点型数据进行 *** 作的。C51中有6种位运算符。
运算符
功能
&
按位与
|
按位或
^
按位异或
~
按位取反
>>
右移高位补零、低位丢弃
<<
左移低位补零、高位丢弃
(2)算术运算符
C51算术运算符与通用C语言完全一致,就是对数值进行算术运算,其中加、减、乘、除、求余运算是双目运算,其结果可以是字符型数、整数和实数(注意求余运算符结果是整数)。自增、自减运算是单目运算,其 *** 作对象只能是整型变量,不能是常量或表达式等其他形式。C51中有7种算术运算符。
运算符
功能
+
加法
-
减法
*
乘法
/
除法
%
求余运算
++
自加
--
自减
(3)关系运算符
C51关系运算符与通用C语言完全一致,用于对两个 *** 作数的比较。关系运算符中的“关系”二字的含义是指一个数据与另一个数据之间的关系,这种关系只有成立与不成立两种可能情况,在C51中用逻辑值来表示,逻辑上的真与假是用数字“1”与“0”来表示的。关系成立时结果为真(1),否则结果为假(0)。C51中有6种关系运算符。
运算符
功能
>
大于
>=
大于等于
<
小于
<=
小于等于
==
测试相等
!=
测试不等
(4)逻辑运算符
C51逻辑运算符与通用C语言完全一致,用于进行逻辑运算。优先级:!运算级别最高、&&运算与||运算同级。!运算的优先级高于算术运算符,而&&和||运算则低于关系运算符。结合方向:逻辑非(单目运算符)具有右结合性;逻辑与和逻辑或(双目运算符)具有左结合性。C51中有3种逻辑运算符。
运算符
功能
&&
逻辑与
||
逻辑或
!
逻辑非
(5)赋值运算符
C51逻辑运算符与通用C语言完全一致,赋值运算符(=)用于连接表达式(右侧)和变量(左侧),即将赋值运算符右侧的表达式的结果赋予赋值运算符左侧的变量,右侧的表达式可以是常量、变量、表达式或另外一个赋值表达式。C51中有12种逻辑运算符,其中第1种是基本赋值运算,其他11种是复合赋值运算。
运算符
功能
=
基本赋值
+=
加法赋值
-=
减法赋值
*=
乘法赋值
/=
除法赋值
%=
求余赋值
>>=
右移赋值
<<=
左移赋值
&=
按位与赋值
|=
按位或赋值
^=
按位异或赋值
~=
按位取反赋值
(6)指针和取运算地址运算符
C51控制语句
- 分支控制语句
(1)if语句用来判定所给定的条件是否满足,根据判定结果决定执行两种 *** 作之一。
if语句的基本结构1如下:
if (表达式) {语句}
括号中的表达式成立时,程序执行大括号内的语句,否则程序跳过大括号中的语句部分,而直接执行下面的其他语句。例如:
if (x>y) {max=x; min=y;} //如果x>y,则x赋给max,y赋给min。如果x>y不成立,则不执行大括号中的赋值运算。
if语句的基本结构2如下:
if (表达式) {语句1;} else {语句2;}
括号中的表达式成立时,程序执行大括号内的语句1,否则程序跳过大括号中的语句1部分,而直接执行else部分大括号内的语句2。例如:
if (x>y){max=x; } //如果x>y,则max赋值为x
else {max=y;} //否则max赋值为y
if语句的基本结构3如下:
if (表达式1) {语句1;}
else if (表达式2) {语句2;}
else if (表达式3) {语句3;}
……
else {语句n;}
if 和 else if 本质上是互斥的,当if(表达式1) {语句1;}执行后直接跳过else if(表达式) {语句;},若执行else if (表达式2) {语句2;}时,表示if(表达式1)为假,语句1没有被执行 。
(2)switch语句。if语句只有两个分支可选择,而switch语句是多分支选择语句。switch语句的一般形式如下:
switch (表达式1)
{
case 常量表达式1:{语句1;}break;
case 常量表达式2:{语句2;}break;
……
case 常量表达式n:{语句n;}break;
default:{语句n+1;}
}
switch语句说明:
每一case常量表达式须互不相同,否则将混乱。
各个case和default出现次序,不影响程序执行的结果。
switch括号内表达式的值与某case后面的常量表达式的值相同时,就执行它后面的语句,遇到break语句则退出switch语句。
若所有的case中的常量表达式的值都没有与switch语句表达式的值相匹配时,就执行default后面的语句。
如果在case语句中遗忘了break语句,则程序执行了本行之后,不会按规定退出switch语句,而是将执行后续的case语句。
switch语句的最后一个分支可以不加break语句,结束后直接退出switch结构。
2.循环控制语句
实现循环结构的语句有以下3种:while语句、do-while语句和for语句。
(1)while语句。语法形式为:
while(表达式)
{
循环体语句;
}
先判断表达式是否为真,如果表达式为真,就重复执行循环体语句;反之,则终止循环体内的语句。
(2)do-while语句。语法形式为:
do
{
循环体语句;
}
while(表达式);
先执行循环体语句,然后判断表达式是否为真,如果表达式为真,就重复执行循环体语句;反之,则终止循环体内的语句。
(3)for语句。for语句不仅可用于循环次数已知的情况,也可用于循环次数不确定而只给出循环条件情况。语法形式为:
for(表达式1;表达式2;表达式3)
{
循环体语句;
}
表达式可为空,但;不能省略,若for(;;),小括号内只有两分号,无表达式,这意味着没有设初值,无判断条件,循环变量为增值,它的作用相当于while(1),为无限循环。若for语句的3个表达式中,表达式1缺省,即不对i设初值(可在循环之前设置初值)。或表达式2缺省,即不判断循环条件。或表达式3缺省,即每次循环后变量i不变化,那么判断条件2会一直为真(或一直为假,不执行循环。表达式2变量可在循环语句中手动添加),则认为表达式始终为真,循环将无休止地进行下去,相当于while(1),为无限循环。
表达式1是进入第一次for循环之前运行了,并且只会执行一次
表示式2是for循环的执行条件,满足这个条件后才能进知入循环里面的语句
表达式3是在执行一次循环后执行的语句
(1)break语句
循环结构中,可使用break语句跳出本层循环体,马上结束本层循环。
(2)continue语句
循环结构中,可使用continue语句跳出本层循环体,停止当前这一层循环,然后直接尝试下一层循环。
(3)goto语句
无条件转移语句,当执行goto语句时,将程序指针跳转到goto给出的下一条代码。
3.数组
(1)一维数组
类型说明符 数组名[元素个数];
可对数组进行整体初始化,即对数组中每个元素都进行赋值(可以不定义元素个数);也可定义元素个数,对其中一些元素进行赋值,未赋值的默认为0。可以在定义时进行整体初始化,也可在定义后单个地进行赋值。
例:int a[3]={2,4,6};
(2)多维数组
类型说明符 数组名[元素行数][元素列数];
可对数组进行整体初始化,即对数组中每个元素都进行赋值(可以不定义元素行数列数);也可定义元素行数列数,对其中一些元素进行赋值,未赋值的默认为0。可以在定义时进行整体初始化,也可在定义后单个地进行赋值。
例:int a[3][4]={1,2,3,4},{5,6,7,8},{9,10,11,12};
(3)字符数组
若一个数组的元素是字符型的,则该数组就是一个字符数组。
例:char a[7]= {‘B’,‘E’,‘I’,‘J’,‘I’,‘N’,‘G’};
还允许用字符串直接给字符数组置初值,数组的元素数目一定要比字符多一个,以便C51编译器自动在其后面加入结束符‘’。
例:char a[10]= {“BEI JING”};
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)