单片机的C语言程序设计与运用第2版期末复习题及答案2.docx
《单片机的C语言程序设计与运用第2版期末复习题及答案2.docx》由会员分享,可在线阅读,更多相关《单片机的C语言程序设计与运用第2版期末复习题及答案2.docx(52页珍藏版)》请在冰豆网上搜索。
单片机的C语言程序设计与运用第2版期末复习题及答案2
中断类
例4-1P104
假设外部中断0和外部中断1均为下降沿触发,当外部中断0发生时,P0端口的电平反向,当外部中断1发生时,P1端口的电
平反向
interrupt0
〃P0端口反向
interrupt2
〃P1端口反向
P1=0xFF;
IT1=1;
#includevoidIS0(void){P0=~P0;}
voidIS1(void){P1=~P1;}
voidmain(){P0=0x00;
IT0=1;
EX0=1;EX仁1;EA=1;while
(1);
}
【例4-9】外部中断示例
在本实例中,首先通过P1.7口点亮发光二极管D1,然后外部输入一脉冲串,
则发光二极管D1亮、暗交替
21
22
232T
25
26
27
28
1D
1J
7T
13
W
1T
16
117
P5VM
P2.2/A10
P2.3/A11
P2.4/A12
P2.5/A13
P2.6/A14
P2.7/A15
P3.D/RXD
P3.1/TXD
P3.27IN1D
P3.3/FNTT
P3.4/TD
P3,5jT1
P3.6歴
P3.7/RD
PSENALEEA
PkOP1.1P1.2
Pt3
P1.4
P1.5
PI.9
P1.7
vcc
■弟
■3D
■31
DJ・
R147DR
■?
■8
■1
U1AT89C51
GND
#include
sbitP1_7=P1A7;
//外部中断0
voidinterrupt0()interrupt0using2
{P1_7=!
P1_7;}
voidmain()
{EA=1;//开中断
IT0=1;//外部中断0脉冲触发
EX0=1;//外部中断0
P1_7=0;
do{}while
(1);
}
如果有3个脉冲,则灯亮、暗交替一次,可如下面编程:
#include
SbitP17=P1A7;
unsignedchari=3;
voidmain()
{EA=1;IT0=1;EX0=1;
P17=0;
do{}while
(1);}
voidinterrupt0()interrupt0
{i=i-1;
if(i==0)
{P17=!
P17;i=3;
}
}
S1
S0
【例4-10】如图4-18所示,8只LED阴极接至单片机P0口,两开关SO、
分别接至单片机引脚P3.2()和P3.3()。
编写程序控制LED状态。
按下
Awc
RO
DO
470R
D7
47DR
卩U.S/PDS
XTAL2
PO.1/AD1
FPX/ADP
XTAL1W
21
32
■9
IS
1©
U1ATS9C51
1?
13
15
14
13
12
11
10
-31
■26
后,点亮8只LED;按下S1后,变为闪烁状态。
#include
sbitP32=P3A2;
//定义延时子函数
voiddelay(unsignedintd)
{while(--d>0);
}
voidmain()
{P0=0xFF;//熄灭LED
IT0=1;IT仁1;//外中断0、1脉冲触发方式
EA=1;EX0=1;EX1=1;//开中断
for(;;)//延时等待中断发生
{;}
}
voidINT0_ISR()interrupt0//外中断0中断服务函数
{P0=0x00;
}
voidINT1_ISR()interrupt2//外中断1中断服务函数
{while(P32!
=0)//如果有外部中断0,则退出
{delay(5000);
P0=0x00;
delay(5000);
P0=0xFF;
}
}
定时类
例4-16】设单片机的fosc=12MHz,要求在P1.0上产生周期为2ms的方波。
要在P1.0上产生周期为2ms的方波,定时器应产生1ms的周期性定时,定时到对P1.0取反。
要产生1ms的定时,应选择方式1,定时器方式。
TMOD的确定:
选择定时器/计数器TO,定时器方式。
方式1,GATE不起作用,高4位为0000,TMOD=01H。
TH、TL的确定:
单片机的fosc=12MHz,则单片机的机器周期为1ms,1ms=1OOOms,计数器的计数初值为65536-1OOO,THO=(65536-1OOO)/256,TLO=(65536-1OOO)%256。
①采用查询方式
程序如下:
#include
sbitP1_O=P1AO;
voidmain(void)
{TMOD=OxO1;
TRO=1;
for(;;)
{TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
do{}while(!
TF0);
P1_0=!
P1_0;
TF0=0;
}
}
②采用中断方式
程序如下:
#include
sbitP1_0=P1A0;
1using1
voidtimer0(void)interrupt
{P1_0=!
P1_0;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
}
voidmain(void)
{TMOD=0x01;
P1_0=0;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
EA=1;ET0=1;
TR0=1;
do{}while
(1);
}
PL4
P3.3/INT1
P1.3
P3.2/INID
P1.2
P3.1fD(D
P1.1
P30/R}{D
PtO
P2.7/A.15
P2.8/A14
P2.5/A13
Ea
P2,4/A12
ALE
PSEN
P1D姓
POJ/AD?
RST
PO.6/AE0
PD.5/AE5
WC
DO串
R1
470R
11・10•
25"
24"
34"
U1
【例4-17】设系统时钟频率为12MHz,编程实现从P1.1输出周期为1s的方波。
要输出周期为1s的方波,应产生500ms的周期性定时,定时到则对P1.1取反即可实现。
由于定时时间较长,一个定时器/计数器不能直接实现,一个定时器/计数器最长定时时间为65ms多一点,可以用以下两种方法实现。
U1
P0.3/AD3
XTAL2
P0.2/AD2
P0.1/AD1
P0.0/AD0
XTAL1斗
D1
R2
VCC
470R
R1
I1——
470R
8
7
3
1
31
22
21
9
18
19
AT89C51
28
27
26
32
33
34
35
36
37
38
39
5|
4
16
15
14
13
12
11
10
25
24
23
30
29
#include
sbitP1_仁P1A1;
unsignedchari;//定义计数变量
voidmain()
{i=0;//初始化
TMOD=0x01;
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
ET0=1;
TR0=1;
while
(1);
}
voidtime0_int(void)interrupt1//中断服务程序
{TH0=(65536-10000)/256;//重载初始值
TL0=(65536-10000)%256;//重载初始值
i++;//每发生一次中断,计数变量加1
if(i==50)//发生50次中断,定时0.5ms
{P1_1=!
P1_1;
i=0;//计数变量清零
}
(2)方法二
用定时/计数器T1计数实现,对10ms计数50次。
定时/计数器T1工作于计数方式时,计数脉冲通过T1(P3.5)输入。
设定时/计数器T0定时时间到对P1.0取反一次,则T1(P3.5)每10ms产生一个计数脉冲,那么定时500ms只需计数25次,设定时/计数器T1工作于方式2,初值X=256-25=231,
TH1=TL1=231。
因为定时/计数器T0工作于方式1,定时方式,则这时方
式控制字为01100001B(61H)。
定时/计数器T0和T1都采用中断方式工
作。
17
16
15
14
13
12
11
10
P3.7/RD
P3.6/WR
P3.5/T1
P3.4/T0
P3.3/INT1
P3.2/INT0
P3.1/TXD
P3.0/RXD
P1.7
P1.6
P1.5
P1.4
P1.3
P1.2
P1.1
P1.0
~4"
3
2
D1
■
R2
1・
470R
28
27
26
25
24
23
22
21
P2.7/A15
P2.6/A14
P2.5/A13
P2.4/A12
P2.3/A11
P2.2/A10
P2.1/A9
P2.0/A8
EAALE
PSEN
32
33
34
35
36
37
38
39
P0.7/AD7
P0.6/AD6
P0.5/AD5
P0.4/AD4
P0.3/AD3
P0.2/AD2
P0.1/AD1
P0.0/AD0
RST
XTAL2
AT89C51
VCC
8
7
6
5
31
30
29
18
XTAL1
U1
elseif(i==20)
//定义计数变量
//初始化
//中断服务程序
//重载初始值
//高电平时间到变低
//周期时间到变高
{P1_1=1;
i=0;
}
}
//计数变量清零
13"
12-
11■
2E■
27
26■
25"叫・
22-
虢・
34"
P3.4>T0
PI.4
P^.3/INT1
F1J
P32/IN7D
FV2
P3.1P1,1
P3.D/RXD
P1.D
P2.7/A15
P2.5/A14
P2.5yA13
EA
P2.4/A12
ALE
P2,3/A11
PSEN
P2.2/A10
P21伽
pamae
PC7/AEJ7
R3T
PC
PC5/^D5
\AJC
31
第五章
【例5-9】串行口自发自收
10・
卩3.7XRDP3.0iKWR
F1.7
Fi.6
pa.siTi
Pl.5
F3.4/TD
PI.4
F3.3XIHT1
卩1.2
F3.2X1MID
Fl.2
P3.1/TXD
PI1
P3.DI/RXD
PIJO
P2.7/A15
PS,^4
P2.5/A15
护
Pi.^AU
ALE
P2.3yA11
P2.2/A1D
P2.1/^0
昭3恕
PC.7/AD7
RST
PO.^^JZ
PO.^ACO
P0.^AD4
卩0.3/AD3
JCTA1L3
P0.2/AIB
FC.1/AD1
F0.WAD0
KTAL1:
AI39M1
Fir-il
■■I
789
333
■e
1-u-U--
332
I■■
0
..!
!
_
#include
#defineucharunsignedchar
#defineuintunsignedintvoidmain()
{uchari=0x55;
uintj=0;
TMOD=0X20;//设定定时器1模式2
TL仁TH1=0XF4;
PCON=0X00;
SCON=0X50;
TR1=1;
while
(1)
{SBUF=i;//发送数据
do()while(!
RI)
RI=0;
TI=0;
i=SBUF;//读取接收数据
P1=i;
i=~i;//将发送数据取反
for(j=0;j<12500;j++);
}
}
【例5-10】两个单片机串行通信1
半匸茫冲二2g(坯彳需8網耳瀬®cd龍邸箱赚瓶倉陳個需粢
rwixl-gc:
Is山£
LJW
=LU*d
■HIX...
■
Qo
■
CM
H
ffi
2
H■CO
■
■
L
■
IO
■1
■
■
■m
■
■
U1
U2
DlfSAJ
■DI
e
oint
.AD0C.5I
AEEICfl
oowcldCLLowrcwH?
s-£MWVSM£zowxoBk?
Q-£s-£二wQgCSIlwrMC.WSZIL暫aftMa.OMWocdoxt_-^ALMlFha.OL/lrgEwfiCLica-£劇”•£
9yvs£LowgmWWKg£9®ua.旨罠£E二£一且<克dL.weEICLCMhz电el」2WG量寸§®QXI£口足glE._*T£IXNI/C览Ew£K__2f
Edi
■■I■■■■■■■■»■■■■■■■!
■■■■■■■■■h!
■■■■■■!
■■■li■■■■■I■h■In
单片机1的C51源程序代码:
#include
#defineuintunsignedint
#defineucharunsignedchar
voidmain()
{uchari;
TMOD=0x20;TH1=TL1=0xff;
SCON=0x50;PCON=0x80;
TR1=1;
P1=0xff;
while
(1)
{P1=0xff;
i=P1;SBUF=i;
while(TI==0)
{;}
TI=0;
}
}
单片机2的C51源程序:
#include
#defineuintunsignedint
#defineucharunsignedchar
voidmain()
{uchari=0;
TMOD=0x20;TH1=TL1=0xff;
SCON=0x50;PCON=0x80;
TR1=1;
while
(1)
{while(RI==0){;}
RI=0;
i=SBUF;
P1=i;
}
}
两个单片机串行通信2
C51源程序代码如下:
#include
//TR=1,发送
//串行口初始化子函数
//发送
//接收
//T1工作于方式2
//串行口工作于方式1,REN=1
//发送联络信号
//等待一帧发送完毕
//发送完毕,标志位清O
//等待乙机应答信号
#defineucharunsignedchar#defineTR1ucharidatabuf[10];
ucharpf;
voidmain()
{int();
if(TR==0){send(buf);}
else
{receive(buf);}
}
/*串口初始化子函数*/voidinit(void)
{TMOD=0x20;
TH0=0xE8;
TL0=0xE8;
TR1=1;
SCON=0X50;
}
/*发送子函数*/voidsend(ucharidata*d){uchari;
do
{SBUF=0xAA;while(TI==0);TI=0;
while(RI==0);
RI=0;
}while(SBU"OxBB!
=O);
do
{pf=O;
//乙机未准备好,继续联络
//校验和变量清O
for(i=O;i<1O;i++){
SBUF=d[i];//发送一个数据
while(TI==0);
TI=0;}
SBUF=pf;
while(TI==0);TI=0;while(RI==0);RI=0;
}while(SBUF!
=0);
}
/*接收函数*/
voidreceive(ucharidata*d){uchari;
do
{while(RI==0);RI=0;}while(SBU"OxAA)!
=O);
SBUF=0xBB;
while(TI==O);TI=O;while
(1){pf=O;for(i=O;i<1O;i++){
d[i]=SBUF;
pf+=d[i];}
while(RI==O);RI=O;
If((SBUFApf)==0){
SBUF=OxOO;break;}else{
SBUF=0xFF;while(TI==0);TI=0;
}
}
//发送校验和
//等待乙机应答
//回答出错,则重新发送
//判断甲机是否请求
//发应答信号
//清校验和
//接收数据
//计算校验和
//接收甲校验和
//比较校验和
//校验和相等,发0x00
//校验和不相等,发0Xff
pf+=d[i];//计算校验和
}
第六章
静态:
【例6-1】利用单片机的并行口作为静态显示的输出口的示例
®123M5G70_BcTt日B日日當煤鶯欝CEAD
U2
XTALZ
RST
PO.V/MD1PC卫少压PO■咖口3PEL*心日0石如5POLACOPO.77/07
IP2.DXifle
F2.1X^QP2S2XA1D
18
曹■
対・
PSEN
P2.3XA11
ALE
Pi,4yAl;
31■
巫
P2.5/A13
P1.D
P2.8XA14
P2.7XA15
Pi.D/RXD
P1.I
P3.1/7XD
J■
J■
PI.2
FJ.3/IITILI
fl"
P13
P1.4
P3.3/IMTI
P3.4JTO
甲■
PI.5
F3JJT1
J■
P1.0
P3.6/WR
PI,7
P3.7/RD
U1ZWT89C51
3
14
6
7
11
2
2
p
D123-4567
1
7
■
■
1
6
■
1
6
■
■
1
4
■
■
1
■
1
3
■
■3
3
■
■孑
£
耶・
-3
&
5
■
■3
5
&
■
■3
4
7
■
■?
g
g
■
-3
2
■
■s
1
■
U3
静态轮流显示“12”--”和“AB的C51源程序如下:
#include
#defineucharunsignedchar
uchardatadis_buf[2];〃显示缓冲区
ucharcodeable[18]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x7
9,0x71,0x40,0x00};〃显示的代码表
voiddl()
{unsignedinti;
for(i=0;i<40000;i++);
}
voiddisplay(void)//显示函数
{ucharsegcode;
segcode=dis_buf[0];/F0口显示
segcode=table[segcode];
P0=segcode;
segcode=dis_buf[1];//P3口显示
segcode=table[segcode];
P3=segcode;
}
voidmain(void)〃主函数
{while
(1)
{dis_buf[0]=1;dis_buf[1]=2;//显示12
display();dl();
dis_buf[0]=16;dis_buf[1]=16;//显示--
display();dl();
disbuf[0]=10;disbuf[1]=11;//显示AB
display();dl();
}
}
示例中的显示函数display()可以再简单一些,如下面程序段:
voiddisplay(void)
{PO=table[dis_buf[O]];〃P0口显示
P3=table[dis_buf[1]];〃P3口显示
}
动态:
【例6-3】利用MCS-51单片机的并行口作为动态显示的段口与位口的示例
6位数码管动态显示“123456的C51源程序如下
1)随机调用
#include
#defineucharunsignedchar
uchardatadis_buf[6];〃显示缓冲区
ucharcodetable[18]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00};〃代码表voiddl_ms()//延时1ms函数
{unsignedintj;
for(j=0;j<200;j++);
}
voiddisplay(void)//显示函数
{ucharsegcode,bitcode,i;
bitcode=0xfe;〃位码赋初值
for(i=0;i<6;i++)
{segcode=dis_buf[i];〃显示缓冲器内容查表
P0=table[segcode];P3=bitcode;dl_ms();
P3=0xff;〃关闭显示
bitcode=b