单片机C51基础知识的汇总.docx
- 文档编号:4540438
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:22
- 大小:29.14KB
单片机C51基础知识的汇总.docx
《单片机C51基础知识的汇总.docx》由会员分享,可在线阅读,更多相关《单片机C51基础知识的汇总.docx(22页珍藏版)》请在冰豆网上搜索。
单片机C51基础知识的汇总
单片机C51基础知识汇总
1、标识符
2、数据类型
3、变量
4、常量
5、二进制、八进制、十进制、十六进制
6、运算符
7、语句
8、注释
9、if语句
10、switch--case语句
11、for循环
12、while循环
13、do—while循环
14、循环控制
15、一维数组
16、二维数组
17、字符数组与字符串数组
18、函数
19、函数重入与递归
20、预处理
21、宏
22、条件编译指令
23、指针(*)
24、结构(struct)
25、联合(union)
26、枚举(enum)
主要内容
1.标识符
标识符就是编程时使用的表示某个事情名称的符号,如函数名、变量名、引脚名、特殊功能寄存器名等。
标识符有系统标识符和用户自定义标识符之分。
标识符的命名规则:
(1)标识符第一个字符必须是字母或下划线。
(2)标识符只能由字母、数字和下划线三类字符组成。
(3)标识符是区分大小写的。
如A和a是两个不同的标识符。
(4)标识符有效长度不超过32个字符。
(5)标识符不能是C51的关键字。
2.数据类型
char有符号字符型,一字节,值域-128~127。
int有符号整型,两字节,值域-32768~32767。
long有符号长整型,四字节,值域-2147483648~2147483647
unsignedchar无符号字符型,一字节,值域0~255
unsignedint无符号整型,两字节,值域0~65535
unsignedlong无符号长整型,四字节,值域0~4294967295
float浮点型(都是有符号的),四字节,±1.175494E-38~±3.402823E+38
bit位变量,一个二进制位,值域0~1。
sbit51单片机特殊功能寄存器位,值域0~1。
Sfr51单片机特殊功能寄存器,值域0~255。
sfr1651单片机特殊功能寄存器,如DPTR,值域0~65535。
bit,sbit,sfr,sfr16不是标准C的内容,是51单片机及C51编译器特有的,不能用指针对它们进行操作。
3.变量
C51规定所有变量在使用前都必须加以说明。
变量说明语句由数据类型、可选的存储类型和其后的一个或多个变量名组成,形式如下:
数据类型[存放类型]变量表;
变量的作用范围:
在花括号内说明(也称声明或定义)的变量,其作用范围仅限该花括号内,称为局部变量;在所有函数外面定义的变量,其作用范是整个程序,称为全局变量。
静态变量:
在类型前加关键词static说明的变量,称静态变量。
在函数内部定义的静态变量也是局部变量,但它在函数下次调用时,能保存上次调用的值。
在函数外面定义的静态变量,是全局变量,但它只在当前C文件中有效。
这可以防止多个C文件中同名冲突。
(函数加了关键词static,可以定义成静态函数,静态函数只能被同一个C文件的程序调用。
)
4.常量
常量的意思就是不可改变的量,是一个常数。
同变量一样,常量也可以有各种数据类型。
常量可以用以下几种方式定义:
(1)宏定义
#defineOFF1/*定义常量标识符OFF,其值为1*/
(2)使用CODE空间
charcodearray[]={1,2,3,4};
/*定义一个常数表,存放在程序存储器中*/
(3)常量定义关键词const
ConstintMAX=60;
(4)enum枚举常量
enumswitchENUM{ON,OFF};/*ON值为0,OFF值为1*/
5.二进制,十进制,八进制,十六进制
(1)C语言中没有二进制的直接表示方法。
(2)以数字“0”开头的数为八进制,如067。
(3)以“0x”或“0X”开头的数为十六进制,如0x3F。
(4)八进制及十六进制与二进制都可以直接转换,八进制每1位数对应3位二进制数。
十六进制的每1位对应4位二进制数。
(5)用四位二进制数来表示的十进制数称BCD码。
6.运算符
(1)赋值运算符(=)
‘=’赋值语句的作用是把某个常量或变量或表达式的值赋值给另一个变量。
注意:
这里并不是等于的意思,只是赋值,等于用‘==’表示。
例如:
count=5;
total1=total2=0;//同时赋值给两个变量
(2)算术运算符(+,-,*,/,%,++,--)
+加,单目正;-减,单目负;*乘法;/除法;%取模;
++自加1(++a,先自加,再赋值;a++,先赋值,再自加)
--自减1(--a,先自减,再赋值;a--,先赋值,再自减)
(3)逻辑运算符(&&,||,!
)
逻辑运算符是根据表达式的值来返回“真”或“假”。
非0为真值,0为假值。
&&逻辑与;||逻辑或;!
逻辑非
(4)关系运算符(>,<,>=,<=,==,!
=)
关系运算符是对两个表达式进行比较,返回一个真、假值。
>大于,如(4>5)的值为0,(4>2)的值为1。
<小于
>=大于等于
<=小于等于
==等于
!
=不等于
这些运算符很简单,但要注意等于“==”和赋值“=”的区别,看下面的代码:
条件判断:
if(a=3){„„}
应该是:
if(a==3){„„}
(5)位运算(&,|,^,~,>>,<<)
&按位逻辑与,如0x0f&0x33结果是0x03。
|按位逻辑或,如0x0f|0x33结果是0x3f。
^按位逻辑异或,如0x0f^0x33结果是0x3c。
~按位取反,如~0x33结果是0xcc。
>>右移,移出丢去,移入补0。
如0x33>>1结果是0x19。
<<右移,移出丢去,移入补0。
如0x33<<2结果是0xcc。
(6)复合赋值运算符(+=,-=,*=,/=,%=,<<=,>>=,&=,|=,^=)
a+=b相当于a=a+b
a-=b相当于a=a-b
a*=b相当于a=a*b
a/=b相当于a=a/b
a%=b相当于a=a%b
a<<=b相当于a=a<
a>>=b相当于a=a>>b
a&=b相当于a=a&b
a|=b相当于a=a|b
a^=b相当于a=a^b
(7)问号表达式(?
:
)
<表达式1>?
<表达式2>:
<表达式3>
在运算中,首先对第一个表达式进行检验,如果为真,则返回表达式2的值;如果为假,则返回表达式3的值。
这是一种“二选一”的表达式。
例如:
a=(b>0)?
(2*3):
7;//当b>0时,a=6;当b不大于0时,a=7。
(8)逗号运算符(,)
多个表达式可以用逗号分开,其中用逗号分开的表达式的值分别结算,但整个表达式的值是最后一个表达式的值。
b=1;
c=2;
d=3;
a1=(++b,c--,d+3);//选括号,再赋值,a1取d+3,即a1=6
a2=++b,c--,d+3;//赋值优先级高,所以a2取++b,即a2=2
(9)运算符的优先级
7.语句
(1)赋值语句
如:
A=1+2;
T=Counter/3+5;
Area=Height*Width;
赋值不是“代数方程”,特别注意:
Num=Num+1;
//这显然不是一个等式,这是把Num+1的值赋给变量Num
(2)用逗号分隔开的声明语句
CharArea,Height,Width;
也可以把标识符写在不同的行上,如:
VfloatArea,
Height,
Width;
这样便于给每个标识符后边加上注释。
在声明变量的时候,也可以直接给变量赋值,这叫做变量的初始化。
如:
inta=3;
也可以只初始化部分变量,如:
inta=3,b,c=5;
inta=3,b=a,c=5;
(3)关于标准输入输出语句
51单片机的C语言程序中可以使用控制台格式化输入、输出函数scanf()和printf(),但因为单片机程序使用这两个函数不是很方便,所以不做介绍。
8.注释
(1)单行注释
一行中,在“//”后面的内容,被解释为注释。
(2)多行注释
以“/*”开头,用“*/”结尾,即/*„„*/中间的内容被解释为注释。
9.if语句
(1)形式1
if(表达式)语句1;
(2)形式2
if(表达式)
{
语句1;
语句2;
„„
语句N;
}
(3)if—else形式
if(表达式)语句1;
else语句2;
(4)if--elseif—else形式
if(表达式1)
语句1;
elseif(表达式2)
语句2;
elseif(表达式3)
语句3;
„„
else
语句n;
10.switch--case
switch(变量)
{
case常量1:
语句1或空;
case常量2:
语句2或空;
„„
case常量n:
语句n或空;
default:
语句n+1或空;
}
执行switch开关语句时,首选测试变量的值,并直接跳到与变量值相等的case常量处开始往下执行。
若不与任何一个常量相等,则执行default后面的语句。
注意:
A.switch中变量可以是数值,也可以是字符,但必须是整数。
B.case的个数可以根据需要增减,也可以不使用default。
C.每个case或default后的语句可以有很多,但不需要使用“{”和“}”括起来。
D.执行完一个case语句后面的程序后它并不主动跳出switch的花括号,而是继续往下,顺序执行。
除非利用break来跳出。
11.for循环
for(<初始化>;<条件表达式>;<增量>)
{
语句组;
}
For的执行流程是:
初始化→条件表达式为“真”→语句组→增量→条件表达式为“真”→„„语句组→增量→条件表达式为“真”→语句组→增量→条件表达式为“假”→结束。
初始化是进入循环时执行的语句,通常是一个赋值语句,它用来给循环控制变量赋初值;条件表达式是一个关系表达式,它决定什么时候退出循环;“增量”可以控制循环次数,定义循环控制变量每循环一次后按什么方式变化。
注意,这三个部分之间用“;”分开,而
不是“,”号。
例如:
for(i=1;i<=10;i++)
j=i*3;
上例中先给i赋初值1,判断i是否小于等于10,若是则执行语句j=i*3,之后i值增加1。
再重新判断,直到条件为假,即i>10时,结束循环。
注意:
A.语句组如果是一条语句,“{”和“}”可以省略。
B.for循环中的初始化、条件表达式和增量都是选择项,即可以缺省,但“;”不能缺省。
省略了初始化,表示不对循环控制变量赋初值。
省略了条件表达式,则不做判断,便成为死循环。
省略了增量,则不对循环控制变量进行操作,这时可在语句组中加入修改循
环控制变量的语句。
初始化、条件表达式和增量可以是对不同的变量进行测试,也可以是复合语句,以期获得特殊的循环效果。
C.for循环可以有多层嵌套。
12.while循环
while(条件)
{
语句组;
}
while循环表示当条件为真时,便执行语句。
直到条件为假才结束循环。
并继续执行循环程序外的后续语句。
while循环总是在循环的头部检验条件,这就意味着循环可能什么也不执行就退出。
注意:
A.在while循环体内也允许空语句。
B.可以有多层循环嵌套。
C.语句组如果是一条语句,“{”和“}”可以省略。
13.do--while循环
do{
语句块;
}while(条件);
这个循环与while循环的不同在于,它先执行循环中的语句,然后再判断条件是否为真,如果为真则继续循环;如果为假,则终止循环。
因此,do-while循环至少要执行一次循环语句。
14.循环控制
(1)break语句
break语句通常用在循环语句和开关语句中。
程序遇上break语句时,会跳出当前循环或switch语句。
通常break语句总是与if语句联在一起,即满足某条件时便跳出。
注意:
A.break语句对if-else的条件语句不起作用。
B.在多层循环中,一个break语句只向外跳一层。
C.如果有多层嵌套的循环,想从最里层跳出到最外层之外时,可用goto语句。
(2)continue语句
continue语句的作用是跳过循环本中剩余的语句而强行执行下一次循环。
即结束本次循
环,根据条件进入下一轮循环。
(3)goto语句
goto语句是一种无条件转移语句,格式为:
goto标号;
“标号”,函数内部用一个有效的“标识符”,后面跟一个冒号“:
”,这样标识的行可以用goto做的跳转目标。
执行goto语句后,程序将跳转到该标号处并执行其后的语句。
标号必须与goto语句同处于一个函数中,但可以不在一个循环层中。
通常goto语句与if条件语句连用,当满足某一条件时,程序跳到标号处运行。
不提倡使用goto语句,它将使程序层次不清,但在多层嵌套退出时,用goto语句则比较合理。
所有的goto语句其实都是可以用break,continue代替的。
15.一维数组
(1)数组就是数据类型相同的一组数,这组数可以通过“索引号”来存取。
声明数组与声明变量方法相似,只要在名称后用一对方括号说明它容纳的元素个数即可:
数据类型数组名[元素个数];
例如:
charArray1[5];//声明一个能存储5个字符元素的数组,没有初值。
IntArray2[]={5,2,13,4};//声明一个整型数组,并存入4个初始值。
(2)用下标访问数组元素
声明数组时,方括号中的数据是数组元素个数;存取数据时,方括号中的数据是数组元素编号(下标)。
数组下标从0开始编号。
上面的Array2数组中,Array2[0]=5,Array2[1]=2,Array2[2]=13,Array2[3]=4。
若用指令:
Array2[2]=100;
则:
把值100赋给数组Array2的2号元素(第3个),2号元素原来的13变为100。
若用指令:
charx=Array2[1];
则,把数组1号元素的值赋给变量x,即x=2。
16.二维数组
例如:
chara[3][8];//这个数组有3行,8列
charb[3][2]={{1,2},{4,5},{9,0}};//定义一个3行,2列的二维数组,
上式中:
b[0][0]=1;b[0][1]=2;b[1][0]=4;b[1][1]=5;b[2][0]=9;b[2][1]=0;
17.字符数组与字符串数组
(1)字符数组
charchArray[]={’A’,’r’,’r’,’a’,’y’,’4’};
//数组元素为字符的ASCII码
(2)字符串数组
charstrArray[]=”Array”;//将字符串“Array”共5个字符的ASCII码存入数组,并最后存入0值,来表示字符串结束。
charstrHZ[]=”单片机”;//将汉字内码存入数组,一个汉字占两个字节(两个元素),同样以0结束。
18.函数
函数是C语言的基本单元。
(1)普通过函数
[函数返回值类型]函数名(参数表)[using寄存器组号]
{
语句组;
}
(2)中断函数
void函数名(void)interrupt中断号[using寄存器组号]
{
语句组;
}
(3)任务函数
void函数名(void)_task_任务号[using寄存器组号]
《单片机控制装置安装与调试》电子工业出版社
{
语句组;
}
以上[using寄存器组号]是可选项。
函数与变量一样,需要先定义,再使用。
如果“定义”在其它C文件中,或者在使用它的语句后面,则需要先进行“说明”。
(4)函数参数传递
A.形式参数和实际参数
函数定义中的参数是形式参数(简称形参),函数的调用者提供给函数的参数叫实际参数(简称实参)。
可以理解为,在函数调用之前,实参的值将赋值给形参,做为形参的初值。
B.形参与实参的作用范围
形参是属于函数内部的局部变量;实参是函数外部即函数调用者的变量。
C.参数传递
形参和实参可能不只一个,如果多于一个时,函数声明、调用、定义的形式都要一一对应,不仅个数要对应,参数的数据类型也要对应。
参数传递有传值和传地址之分。
当函数参数为普通变量,常数时,传递的是值。
如果参数是指针,数组,结构等时,传递的是它们的地址。
(5)函数值的返回
如果函数定义了返回值,则可以把函数当作一个变量。
函数执行完成后,就会得到一个值。
注意:
A.有返回值的函数声明函数时,函数名前面不是void,而是返回值类型。
B.函数必须用return语句来返回一个值。
return语句在函数中可以不只出现一次,但是一旦遇上它,函数立即结束并返回。
C.函数的返回值可以赋给一个变量,也可以将函数放在一个表达式中参与运算。
19.函数重入与递归
(1)重入
函数正在运行,还没有结束,又被调用,称为重入。
在中断函数系统、多任务操作系统编程时,容易出现这种情况。
(2)递归
递归,就是函数自己调用了自己,或者在自己函数调用的下级函数中调用自己。
递归是重入的一种特殊情况。
递归函数必须确保有一个终止条件来结束递归下降过程,并且返回到顶层。
递归通常都可以用循环来实现,但很多时候使用递归比使用循环要简单。
20.预处理
预处理指令是以#号开头的代码行。
#号必须是该行除了任何空白字符外的第一个字符。
#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。
整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。
下面是部分预处理
指令:
#include包含一个源代码文件
#define定义宏
#undef取消已定义的宏
#if如果给定条件为真,则编译下面代码
#ifdef如果宏已经定义,则编译下面代码
#ifndef如果宏没有定义,则编译下面代码
#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#endif结束一个#if„„#else条件编译块
#error停止编译并显示错误信息
21.宏
宏定义了一个代表特定内容的标识符。
预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。
宏最常见的用法是定义代表某个值的全局符号。
宏的第二种用法是定义带参数的宏,这样的宏可以象函数一样被调用,但它是在调用语句处展开宏,并用调用时的实际参数来代替定义中的形式参数。
(1)#define指令
#define预处理指令是用来定义宏的。
该指令神明一个标识符,然后给出这个标识符代表的代码。
例如:
01#defineMAX_NUM10/*定义符号MAX_NUM代表10*/
02intarray[MAX_NUM];/*利用符号MAX_NUM声明数组的容量*/
03for(i=0;i 宏定义的符号具有一定的字面意义,便于程序阅读理解。 作为一种约定,习惯上总是全部用大写字母来定义宏,这样易于把程序中的宏标识符和一般变量标识符区别开来。 如果修改01行的值10,则所有使用符号MAX_NUM的地方同时发生改变,这方便进行一些参数的修改。 宏表示的值可以是一个常量表达式,其中允许包括前面已经定义的宏标识符。 例如: #defineONE1 #defineTWO2 #defineTHREE(ONE+TWO) //这里的括号很有必要,请看下面的例子就明白了。 如: six=THREE*TWO; 上式转换后变成: six=(ONE+TWO)*TWO; 如果没有括号,就转换成: six=ONE+TWO*TWO; //其意义与上面完全不同 宏还可以代表一个字符串常量,例如: #defineVERSIONVersion1.0Copyright(c)2003 (2)带参数的#define指令 带参数的宏和函数调用看起来有些相似。 看一个例子: #defineCUBE(x)(x)*(x)*(x) 可以用任何数字表达式甚至函数调用来代替参数x。 这里再次提醒大家注意括号的使用。 宏展开后完全包含在一对括号中,而且参数也包含在括号中,这样就保证了宏和参数的完整性。 看一个用法: #defineNUM3+2 volume=CUBE(NUM); 展开后为(3+2)*(3+2)*(3+2); 如果没有那些括号就变为3+2*3+2*3+2了。 下面的用法是不安全的: volume=CUBE(NUM++); 如果CUBE是一个函数,上面的写法是可以理解的。 但是,因为CUBE是一个宏,所以会产生副作用。 这里的参数不是简单的表达式,它们将产生意想不到的结果。 它们展开后是这样的: volume=(NUM++)*(NUM++)*(NUM++); 很显然,结果是10*11*12,而不是10*10*10;可见,使用带参数的宏一定要小心。 (3)#运算符 出现在宏定义中的#运算符把跟在其后的参数转换成一个字符串。 有时把这种用法的#称为字符串化运算符。 例如: #definePASTE(n)adhfkj#n 则,PASTE(15)表示adhfkj15。 (4)##运算符 ##运算符用于把参数连接到一起。 预处理程序把出现在##两侧的参数合并成一个符号。 看下面的例子: #defineNUM(a,b,c)a##b##c #defineSTR(a,b,c)a##b##c main() { printf(%d\n,NUM(1,2,3)); printf(%s\n,STR(aa,bb,cc)); } 最后程序的输出为: 123 aabbcc 千万别担心,除非需要或者宏的用法恰好和手头的工作相关,否则很少有程序员会知道##运算符。 绝大多数程序员从来没用过它。 22.条件编译指令 条件编译指令将决定那些代码被编译,而哪些是不被编译的。 可以根据表达式的值或者某个特定的宏是否被定义来确定编译条件。 (1)#if指令 #if指令检测跟在制造另关键字后的常量表达式。 如果表达式为真,则编译后面的代码,知道出现#else、#elif或#endif为止;否则就不编译。 (2)#endif指令 #endif用于终止#if预处理指令。 #defineDEBUG0 main() { #ifDEBUG printf(Debugging\n); #endif
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 C51 基础知识 汇总