C51语言复习题参考答案.docx
《C51语言复习题参考答案.docx》由会员分享,可在线阅读,更多相关《C51语言复习题参考答案.docx(18页珍藏版)》请在冰豆网上搜索。
![C51语言复习题参考答案.docx](https://file1.bdocx.com/fileroot1/2023-1/29/5326006f-d88f-4a5c-a01a-cabe7973bb42/5326006f-d88f-4a5c-a01a-cabe7973bb421.gif)
C51语言复习题参考答案
1.利用下列( D )关键字可以改变工作寄存器组
A、interrupt B、sfr
C、while D、using
2.C51中一般指针变量占用( C )字节存储。
A、一个 B、两个 C、三个 D、四个
3.使用宏来访问绝对地址时,一般需包含的库文件是( B )
A、 B、 C、 D、
4.执行#definePA8255 XBYTE[0x3FFC];
PA8255=0x7e;
后存储单元0x3FFC的值是(A )
A、Ox7e B、8255H C、未定 D、7e
5.设有inti;则表达式i=1,++i,++i||++i,i的值为(C)
A、1B、2C、3D、4
6.设有inta[]={10,11,12},*p=&a[0];则执行完*p++;*p+=1;后a[0],a[1],a[2]的值依次是(C)
A、10,11,12B、11,12,12C、10,12,12D、11,11,12
7.设有inti;则表达式i=1,++i,i||++i,i的值为(B)
A、1B、2C、3D、4
二、判断题:
(每小题1分,共10分。
正确的在括号内打“√”,错误的打“×”。
判对得分,不判、判错均不得分。
)
1.若一个函数的返回类型为void,则表示其没有返回值。
(√ )
2.特殊功能寄存器的名字,在C51程序中,全部大写。
(√ )
3.“sfr”后面的地址可以用带有运算的表达式来表示。
( × )
4.#include <>与#include “”是等价的。
(√ )
5.sbit不可以用于定义内部RAM的可位寻址区,只能用在可位寻址的SFR上。
(× )
6.Continue和break都可用来实现循环体的中止。
( × )
7.若一个函数的返回类型为void,则表示其没有返回值。
(√ )
8.所有定义在主函数之前的函数无需进行声明。
( × )
9.inti,*p=&i;是正确的C说明。
(√ )
10.7&3+12的值是15。
( × )
11.一个函数利用return不可能同时返回多个值。
(√ )
三、填空( 每空1分,共20分。
在空白处填上正确的内容)
1.KeiLC51软件中,工程文件的扩展名是____UV2______,编译连接后生成可烧写的文件扩展名是_____HEX_______。
2.C51支持的指针有一般指针和存储器指针。
3.C51中,没有专门的循环语句,我们可以用函数______crol_______完成一个字节的循环左移,用____irol_____完成二个字节的循环左移。
4.函数 是C语言的基本单位。
5.C语言中输入和输出操作是由库函数scanf 和 printf 等函数来完成。
6.若有说明inti,j,k;则表达式i=10,j=20,k=30,k*=i+j的值为__900______。
7.数组是一组有固定数目和相同类型成分分量的有序集合。
8.变量的指针就是变量的地址;指针变量的值是指针。
9.在C语言中,把多个不同类型的变量结合在一起形成的一个组合型变量,称为结构变量,简称结构。
10.C51的数据类型有基本类型、构造类型、指针类型、空类型。
11.C51的基本数据类型有位型、字符型、整形、长整形、浮点型、双精度浮点型。
12.C51的构造数据类型有数组类型、结构类型、共用体型、梅举型。
13.C51的存储类型有data、bdata、idata、pdata、xdata、code。
14.C51的存储模式有SMALL、COMPACT和LARGE。
15.C51程序与其他语言程序一样,程序结构也分为顺序结构、选择结构(或分支结构)、循环结构三种。
16.数组的一个很重要的用途就是查表。
17.
四、问答题(共20分)
1.简述C51语言和汇编语言的比较(5分)
使用C51语言进行嵌入式系统的开发,有着汇编语言所不可比拟的优势:
①编程调试灵活方便;
②生成的代码编译效率高;
③模块化开发;
④可移植性好;
⑤便于项目的维护;
2.简述单片机的C语言的特点(7分)
单片机的C语言的特点主要体现在以下几个方面:
①无需了解机器硬件及其指令系统,只需初步了解MCS-51的存储器结构;
②C51能方便的管理内部寄存器的分配、不同存储器的寻址和数据类型等细节问题,但对硬件控制有限;而汇编语言可以完全控制硬件资源;
③C51在小应用程序中,产生的代码量大,执行速度慢;但在较大的程序中代码效率高;
④C51程序由若干函数组成,具有良好的模块化结构,便于改进和扩充;
C51程序具有良好的可读性和可维护性;而汇编语言在大应用程序开发中,开发难度增加,可读性差;
C51有丰富的库函数,可大大减少用户的编程量,显著缩短编程与调试时间,大大提高软件开发效率;
⑦使用汇编语言编制的程序,当机型改变时,无法直接移植使用,而C语言程序是面向用户的程序设计语言,能在不同机型的机器上运行,可移植性好。
3.哪些变量类型是51单片机直接支持的?
(5分)
答:
C51编译器支持的数据类型有:
位型(bit)、无符号字符型(unsignedchar)、有符号字符型(signedchar)、无符号整型(unsignedint)、有符号整型(signedint)、无符号长整型(unsignedlong)、有符号长整型(signedlong)、浮点型(float)和指针型等。
C51编译器支持的数据类型、长度和值域如表1-1所示。
表1-1C51的数据类型
数据类型
长度/bit
长度/byte
值域
bit
1
0,1
unsignedchar
8
1
0~255
signedchar
8
1
-128~127
unsignedint
16
2
0~65535
signedint
16
2
-32768~32767
unsignedlong
32
4
0~4294967295
signedlong
32
4
-2147483648~2147483647
float
32
4
±1.176E-38~±3.40E+38(6位数字)
double
64
8
±1.176E-38~±3.40E+38(10位数字)
一般指针
24
3
存储空间0~65535
4.简述C51的数据存储类型(10分)
答:
我们都知道,8051单片机存储区可分为内部数据存储区、外部数据存储区以及程序存储区。
8051单片机内部的数据存储区是可读写的,8051派生系列最多可有256字节的内部数据存储区,其中低128字节可直接寻址,高128字节(从0x80到0xFF)只能间接寻址,从20H开始的16字节可位寻址。
内部数据区可分为3个不同的存储类型:
data、idata和bdata。
外部数据区也是可读写的,访问外部数据区比访问内部数据区慢,因为外部数据区是通过数据指针加载地址来间接访问的。
C51提供两种不同的存储类型xdata和pdata访问外部数据。
程序存储区是只能读不能写。
程序存储区可能在8051单片机内部或者在外部或者内外都有,这由8051单片机的硬件决定。
C51提供了code存储类型来访问程序存储区。
每个变量可以明确地分配到指定的存储空间,对内部数据存储器的访问比对外部数据存储器的访问快许多,因此应当将频繁使用的变量放在内部存储器中,而把较少使用的变量放在外部存储器中。
各存储区的简单描述如表1-2所示。
表1-2C51存储类型与8051存储空间的对应关系
存储区
描述
DATA
片内RAM的低128字节,可在一个周期内直接寻址
BDATA
片内RAM的位寻址区,16字节
IDATA
片内RAM的256字节,必须采用间接寻址
XDATA
外部数据存储区,使用DPTR间接寻址
PDATA
外部存储区的256个字节,通过P0口的地址对其寻址。
使用MOVX@Ri,需要两个指令周期
CODE
程序存储区,使用DPTR寻址。
以上介绍的是C51的数据存储类型,C51存储类型及其大小和值域如表1-3所示。
表1-3C51存储类型及其大小和值域
存储类型
长度/bit
长度/byte
值域
data
8
1
0~255
idata
8
1
0~255
pdata
8
1
0~255
code
16
2
0~65535
xdata
16
2
0~65535
5.简述C51对51单片机特殊功能寄存器的定义方法(5分)
答:
MCS-51通过其特殊功能寄存器(SFR)实现对其内部主要资源的控制。
MCS-51单片机有21个SFR,有的单片机还有更多的SFR,它们分布在片内RAM的高128字节中,其地址能够被8整除的SFR一般可以进行位寻址。
关于MCS-51单片机的特殊功能寄存器参看附录A。
对SFR只能用直接寻址方式访问。
C51允许通过使用关键字sfr、sbit或直接引用编译器提供的头文件来实现对SFR的访问。
(1)使用关键字定义sfr
为了能直接访问特殊功能寄存器SFR,C51提供了一种自主形式的定义方法。
这种定义方法与标准的C语言不兼容,只适用于对8051系列单片机进行C编程。
这种定义的方法是引入关键字“sfr”,语法如下:
sfr特殊功能寄存器名字=特殊功能寄存器地址;
如:
sfrSCON=0x98;/*串口控制寄存器地址98H*/
sfrTMOD=0X89;/*定时器/计数器方式控制寄存器地址89H*/
(2)通过头文件访问SFR
8051系列单片机的寄存器数量与类型是极不相同的,因此对单片机特殊功能寄存器的访问可以通过对头文件的访问来进行。
为了用户处理方便,C51编译器把MCS-51单片机的常用的特殊功能寄存器和特殊位进行了定义,放在一个“”或“”的头文件中。
当用户要使用时,只需要在使用之前用一条预处理命令“#include<>”把这个头文件包含到程序中,然后就可以使用特殊功能寄存器名和特殊位名称了。
用户可以通过文本编辑器对头文件进行增减。
(3)SFR中位定义
在8051单片机的应用问题中,经常需要单独访问SFR中的位,C51的扩充功能使之成为可能,使用关键字“sbit”可以访问位寻址对象。
特殊位(sbit)的定义,像SFR一样不与标准C兼容。
与SFR定义一样,用关键字“sbit”定义某些特殊位,并接受任何符号名,“=”号后将绝对地址赋给变量名。
这种地址分配有三种方法:
第一种方法:
sbit位名=特殊功能寄存器名^位置;
当特殊功能寄存器的地址为字节(8位)时,可使用这种方法。
特殊功能寄存器名必须是已定义的SFR的名字。
“^”后的“位置”语句定义了基地址上的特殊位的位置。
该位置必须是0~7的数。
如:
第二种方法:
sbit位名=字节地址^位置;
这种方法是以一个整常数为基地址,该值必须在0x80~0xFF之间,并能被8整除,确定位置的方法同上。
第三种方法:
sbit位名=位地址;
这种方法将位的绝对地址赋给变量,地址必须在0x80~0xFF之间。
6.C51的data、bdata、idata有什么区别?
(6分)
答:
data、bdata、idata是表明数据的存储类型,
data是指片内RAM的低128字节,可在一个周期内直接寻址;
bdata是指片内RAM的位寻址区,16字节;
idata是指片内RAM的256字节,必须采用间接寻址。
7.C51中的中断函数和一般的函数有什么不同?
(6分)
答:
C51编译器允许用C51创建中断服务函数,中断函数是由中断系统自动调用的。
中断函数的定义格式为:
函数类型函数名interruptnusingn
其中:
interrupt和using为关键字;
interrupt后面的n为中断源的编号,即中断号;
using后面的n所选择的寄存器组,取值范围为0~3。
定义中断函数时,using是一个选项,可以省略不用。
如果不用using选项,则由编译器选择一个寄存器组作为绝对寄存器组。
8051的中断过程通过使用interrupt关键字和中断号(0~31)来实现,中断号告诉编译器中断函数的入口地址。
8.按照给定的数据类型和存储类型,写出下列变量的说明形式(6分)
(1)在data区定义字符变量val1
答:
chardatavall;
(2)在idata区定义整型变量val2
答:
intidataval2;
(3)在xdata区定义无符号字符型数组val3[4]。
答:
unsignedxdataval3[4];
(4)在xdata区定义一个指向char类型的指针px。
答:
charxdata*px;
(5)定义可位寻址变量flag。
答:
bitflag;
(6)定义特殊功能寄存器变量P3。
答:
SfrP3=0xB0;
9.什么是重入函数?
重入函数一般什么情况下使用,使用时有哪些需要注意的地方?
答:
多个函数可以同时使用的函数,称为重入函数。
(6分)
通常情况下,C51函数不能被递归调用,也不能应用导致递归调用的结构。
有此限制是由于函数参数和局部变量是存储在固定的地址单元中。
重入函数特性允许你声明一个重入函数。
即可以被递归调用的函数。
重入函数可以被递归调用,也可以同时被两个或更多的进程调用。
重入函数在实时应用中及中断服务程序代码和非中断程序代码必须共用一个函数的场合中经常用到。
10.如何消除键盘的抖动?
(5分)
答:
由于按键是机械开关结构,所以当用手按下其中一个键时,往往会出现所按键在闭合位置和断开位置之间发生跳几下后才会稳定到闭合状态的情况。
在释放一个键时,也会出现类似的情况,这就是键的抖动,抖动的持续时间不一,但通常不会大于10ms。
若抖动问题不解决,就会引起对闭合键的多次读入。
对于键抖动最方便的解决方法就是当发现有键按下后,不是立即进行扫描,而是延时大约10ms后再进行。
由于一个键按下的时间一般会持续上百毫秒,所以延迟10ms后再扫描处理并不迟。
11.在使用8051的定时器/计数器前,应对它进行初始化,其步骤是什么?
(4分)
答:
(1)确定T/C的工作方式——编程TMOD寄存器;
(2)计算T/C中的计数初值,并装载到TH和TL;
(3)T/C在中断方式工作时,须开CPU中断和源中断——编程IE寄存器;
(4)启动定时器/计数器——编程TCON中TR1或TR0位。
五、程序分析题(10分)
1.设单片机时钟频率为6MHz,分析下面程序实现什么功能?
#include""
sbitP10=P1^0;
voidmain()
{
TMOD=0x01;
TH0=(65536-12500)/256;
TL0=(65536-12500)%256;
ET0=1;
EA=1;
TR0=1;
while
(1);
}
voidT0_srv(void)interrupt1using1
{
TH0=(65536-12500)/256;
TL0=(65536-12500)%256;
P10=!
P10;
}
解:
引脚输出50ms周期的方波。
2.分析下面程序实现什么功能?
#include""
#include""
voidinit_ser()
{SCON=0x50;/*SCON:
工作模式1,8-bitUART,允许接收*/
TMOD|=0x20;/*TMOD:
定时器T1,工作模式2,8位自动重载方式*/
TH1=0xf3;/*当波特率为2400时,定时器初值*/
TR1=1;/*定时器T1开始运行*/
TI=1;/*允许发送数据*/
}
longfactorial(intn)reentrant
{longresult;
if(n==0)
result=1;
else
result=n*factorial(n-1);
returnresult;
}
voidmain()
{intj;
longtmp;
long(*p)(intn);/*函数指针变量定义*/
init_ser();
p=(void*)factorial;/*函数指针变量p指向factorial()函数*/
for(j=0;j<11;++j)
{tmp=(*p)(j);/*用指针变量p调用factorial()函数*/
printf("%d!
=%ld\n",j,tmp);
}
for(;;){;}
}
解:
输出0~10的阶乘。
六、编程题(30分)
1.在8051系统中,已知振荡频率是12MHz,用定时器/计数器T0实现从产生周期是2s的方波,试编程。
(10分)
解:
#include<>
sbitP1_1=P1^1;//定义位变量
unsignedchari;//定时次数
voidtimer0over(void);//函数声明(定时50ms函数)
voidmain()//主函数
{
i=0;
TMOD=0x01;//定时器T0定时50ms,方式1
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;//开T0
for(;;)
{
if(TF0)
timer0over();
}
}
voidtimer0over(void)
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TF0=0;
i++;
if(i==20)//20次到了吗?
{
i=0;
P1_1=!
P1_1;
}
}
2.在8051系统中,已知振荡频率是12MHz,用定时器/计数器T1实现从产生高电平宽度是10ms,低电平宽度是20ms的矩形波,试编程。
(10分)
解:
#include<>
unsignedchari;
sbitP1_1=P1^1;
voidmain()//主函数
{
i=0;
TMOD=0x10;//T1定时方式1,定时时间10ms
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
ET1=1;
TR1=1;
while
(1);
}
voidtimer1_int(void)interrupt3
{
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
i++;
if(i==1)P1_1=0;
elseif(i==3)
{
i=0;
P1_1=1;
}
}
3.用单片机和内部定时器来产生矩形波,要求频率为100Hz,占空比为2:
1,设单片机的时钟频率为12MHz,写出有关程序。
(10分)
解:
#include<>
unsignedchari;
sbitP1_1=P1^1;
voidmain()
{
i=0;
TMOD=0x10;
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
ET1=1;
TR1=1;
while
(1);
}
voidtimer1_int(void)interrupt3
{
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
i++;
if(i==2)P1_1=0;
elseif(i==3)
{
i=0;
P1_1=1;
}
}
4.如图1-1所示,单片机P1口的和各接一个开关S1、S2,、、和各接一只发光二极管。
由S1和S2的不同状态来确定哪个发光二极管被点亮,如表1-4所示。
(10分)
解:
(一)程序如下:
#include<>
voidmain()
{
chara;
a=P1/*读P1口*/
a=a&0x03;/*屏蔽高6位*/
if(a==0)P1=0x83;
elseifa==1P1=0x43;
elseifa==2P1=0x23;
elseP1=0x13;
}
(二)程序如下:
#include“”
voidmain()
{
chara;
a=P1;/*读P1口*/
a=a&0x03;/*屏蔽高6位*/
switch(a)
{
case0:
P1=0x83;break;
case1:
P1=0x43;break;
case2:
P1=0x23;break;
case3:
P1=0x13;
}
}
(三)程序如下:
#include“”
voidmain()
{
chara;
loop:
a=P1;
a=a&0x03;/*屏蔽高6位*/
switch(a)
{
case0:
P1=0x83;break;
case1:
P1=0x43;break;
case2:
P1=0x23;break;
case3:
P1=0x13;
}
gotoloop;
}
(四)程序如下:
#include“”
voidmain()
{
chara;
while
(1)
{
a=P1;
a=a&0x03;/*屏蔽高6位*/
switch(a)
{
case0:
P1=0x83;break;
case1:
P1=0x43;break;
case2:
P1=0x23;break;
case3:
P1=0x13;
}
}
}
(五)程序如下:
#include“”
voidmain()
{
chara;
do{
a=P1;
a=a&0x03;/*屏蔽高6位*/
switch(a)
{
case0:
P1=0x83;break;
case1:
P1=0x43;break;
case2:
P1=0x23;break;
case3:
P1=0x13;
}
}while
(1);
}
(六)程序如下:
#include“”
voidmain()
{
chara;
for(;;)
{
a=P1;
a=a&0x03;/*屏蔽高6位