《《单片机的C语言程序设计与运用(第2版)》期末复习题及答案.doc》由会员分享,可在线阅读,更多相关《《单片机的C语言程序设计与运用(第2版)》期末复习题及答案.doc(34页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 第四章中断类例4-1 P104 假设外部中断0和外部中断1均为下降沿触发,当外部中断0发生时,P0端口的电平反向,当外部中断1发生时,P1端口的电平反向。#includevoid IS0(void) interrupt 0P0=P0; /P0端口反向void IS1(void) interrupt 2P1=P1;/P1端口反向void main( )P0=0x00;P1=0xFF; IT0=1; IT1=1; EX0=1;EX1=1;EA=1; while(1);【例4-9】外部中断示例在本实例中,首先通过P1.7口点亮发光二极管D1,然后外部输入一脉冲串,则发光二极管D1亮、暗交替。 #i
2、ncludesbit P1_7=P17;void interrupt0( ) interrupt 0 using 2 /外部中断0P1_7=!P1_7;void main( )EA=1; /开中断 IT0=1; /外部中断0脉冲触发 EX0=1; /外部中断0 P1_7=0; do while(1);如果有3个脉冲,则灯亮、暗交替一次,可如下面编程:#includeSbit P17=P17;unsigned char i=3;void main( )EA=1;IT0=1;EX0=1; P17=0;do while(1); void interrupt0( ) interrupt 0 i=i-1
3、; if(i=0) P17=!P17; i=3; 【例4-10】如图4-18所示,8只LED阴极接至单片机P0口,两开关S0、S1分别接至单片机引脚P3.2()和P3.3()。编写程序控制LED状态。按下S0后,点亮8只LED;按下S1后,变为闪烁状态。#includesbit P32=P32;void delay(unsigned int d) /定义延时子函数while(-d0); void main( )P0=0xFF;/熄灭LED IT0=1;IT1=1;/外中断0、1脉冲触发方式 EA=1;EX0=1;EX1=1;/开中断 for( ; ; )/延时等待中断发生 ;void INT0
4、_ISR( ) interrupt 0/外中断0中断服务函数P0=0x00;void INT1_ISR( ) interrupt 2/外中断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的确定:选择定时器/计数器T0,定时器方式。方式1,GATE不起作
5、用,高4位为0000,TMOD=01H。TH、TL的确定:单片机的fosc=12MHz,则单片机的机器周期为1ms,1ms=1000ms,计数器的计数初值为65 536-1000,TH0=(65 536-1000)/256,TL0=(65 536-1000)%256。 采用查询方式程序如下:#includesbit P1_0=P10;void main(void)TMOD=0x01;TR0=1;for(;)TH0=(65536-1000)/256;TL0=(65536-1000)%256;do while(!TF0);P1_0=!P1_0;TF0=0; 采用中断方式程序如下:#includes
6、bit P1_0=P10;void timer0(void) interrupt 1 using 1P1_0=!P1_0;TH0=(65536-1000)/256;TL0=(65536-1000)%256;void main(void)TMOD=0x01;P1_0=0;TH0=(65536-1000)/256;TL0=(65536-1000)%256;EA=1;ET0=1;TR0=1;do while(1);【例4-17】设系统时钟频率为12MHz,编程实现从P1.1输出周期为1s的方波。要输出周期为1s的方波,应产生500ms的周期性定时,定时到则对P1.1取反即可实现。由于定时时间较长,一
7、个定时器/计数器不能直接实现,一个定时器/计数器最长定时时间为65ms多一点,可以用以下两种方法实现。(1)方法一用定时/计数器T0产生周期性为10ms的定时,然后用一个变量对10ms计数50次。系统时钟为12MHz,定时/计数器T0定时10ms,计数值N为10000,选方式1,方式控制字为B(01H),则初值X为X=65 536-10 000。#includesbit P1_1=P11;unsigned char i;/定义计数变量void main( )i=0; /初始化TMOD=0x01;TH0=(65536-10000)/256;TL0=(65536-10000)%256;EA=1;E
8、T0=1;TR0=1;while(1);void time0_int(void) interrupt 1 /中断服务程序TH0=(65536-10000)/256;/重载初始值TL0=(65536-10000)%256;/重载初始值i+;/每发生一次中断,计数变量加1if (i=50) /发生50次中断,定时0.5msP1_1=!P1_1;i=0;/计数变量清零(2)方法二用定时/计数器T1计数实现,对10ms计数50次。定时/计数器T1工作于计数方式时,计数脉冲通过T1(P3.5)输入。设定时/计数器T0定时时间到对P1.0取反一次,则T1(P3.5)每10ms产生一个计数脉冲,那么定时50
9、0ms只需计数25次,设定时/计数器T1工作于方式2,初值X=256-25=231,TH1=TL1=231。因为定时/计数器T0工作于方式1,定时方式,则这时方式控制字为B(61H)。定时/计数器T0和T1都采用中断方式工作。#include sbit P1_1=P11;sbit P1_0=P10;void main( )TMOD=0x61;/初始化TH0=(65536-10000)/256;TL0=(65536-10000)%256;TH1=231;TL1=231;EA=1;ET0=1;ET1=1;TR0=1;TR1=1;while(1);void time0_int(void) inter
10、rupt 1 /T0中断服务程序TH0=(65536-10000)/256;/重载初始值TL0=(65536-10000)%256;/重载初始值P1_0=!P1_0;void time1_int(void) interrupt 3 /T1中断服务程序 P1_1=!P1_1; 【例4-18】设系统时钟频率为12MHz,编程实现:P1.1引脚上输出周期为1s,占空比为20%的脉冲信号根据输出要求,脉冲信号在一个周期内高电平占0.2s,低电平占0.8s,超出了定时器的最大定时间隔,因此利用定时器0产生一个基准定时配合软件计数来实现。取50ms作为基准定时,采用工作方式1,这样这个周期需要20个基准定
11、时,其中高电平占4个基准定时。#includesbit P1_1=P11;unsigned char i;/定义计数变量void main( )i=0; /初始化TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;while(1);void time0_int(void) interrupt 1 /中断服务程序TH0=(65536-50000)/256; /重载初始值TL0=(65536-50000)%256;i=i+1;if(i=4) P1_1=0;/高电平时间到变低else if(i=20) /周期时
12、间到变高P1_1=1;i=0;/计数变量清零第五章【例5-9】串行口自发自收#include#define uchar unsigned char#define uint unsigned intvoid main( ) uchar i=0x55; uint j=0; TMOD=0X20;/设定定时器1模式2 TL1=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;j12500;j+)
13、; 【例5-10】两个单片机串行通信1单片机1的C51源程序代码:#include#define uint unsigned int#define uchar unsigned charvoid main( ) uchar i; 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#define uint unsigned int#define uchar unsigned ch
14、arvoid main( ) uchar i=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#define uchar unsigned char#define TR 1/TR=1,发送uchar idata buf10;uchar pf;void main( ) int( ); /串行口初始化子函数if(TR=0)send(buf);/发送elsereceive(buf);/接收/*
15、串口初始化子函数*/void init(void)TMOD=0x20;/T1工作于方式2TH0=0xE8;TL0=0xE8;TR1=1;SCON=0X50;/串行口工作于方式1,REN=1/*发送子函数*/void send(uchar idata*d)uchar i;doSBUF=0xAA;/发送联络信号while(TI= =0);/等待一帧发送完毕TI=0;/发送完毕,标志位清0while (RI= =0);/等待乙机应答信号RI=0;while (SBUF0xBB!=0);/乙机未准备好,继续联络dopf=0;/校验和变量清0for(i=0;i10;i+)SBUF=di;/发送一个数据p
16、f+=di;/计算校验和while(TI= =0);TI=0;SBUF=pf;/发送校验和while (TI= =0);TI=0;while (RI= =0);RI=0;/等待乙机应答while (SBUF!=0);/回答出错,则重新发送 /*接收函数*/void receive(uchar idata*d)uchar i;dowhile(RI= =0); RI=0;while(SBUF0xAA)!=0);/判断甲机是否请求SBUF=0xBB;/发应答信号while(TI= =0);TI=0;while(1)pf=0;/清校验和for(i=0;i10;i+) di = SBUF;/接收数据pf
17、+=di;/计算校验和while(RI= =0);RI=0;/接收甲校验和If(SBUFpf)= =0)/比较校验和SBUF=0x00;break;/校验和相等,发0x00elseSBUF=0xFF;/校验和不相等,发0Xffwhile(TI= =0);TI=0;第六章静态:【例6-1】利用单片机的并行口作为静态显示的输出口的示例 静态轮流显示“12”、“- -”和“AB”的C51源程序如下:#include#define uchar unsigned charuchar data dis_buf2;/显示缓冲区uchar code able18=0x3f,0x06,0x5b,0x4f,0x6
18、6,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00; /显示的代码表void dl( )unsigned int i; for(i=0;i40000;i+);void display(void)/显示函数 uchar segcode; segcode=dis_buf0;/P0口显示 segcode=tablesegcode; P0=segcode; segcode=dis_buf1;/P3口显示 segcode=tablesegcode; P3=segcode;void main(void)/主函数 while(
19、1) dis_buf0=1;dis_buf1=2;/显示12 display( ); dl(); dis_buf0=16;dis_buf1=16;/显示- - display( ); dl( ); dis_buf0=10;dis_buf1=11;/显示AB display( ); dl( ); 示例中的显示函数display( )可以再简单一些,如下面程序段:void display(void) P0=tabledis_buf0;/P0口显示 P3=tabledis_buf1;/P3口显示动态:【例6-3】利用MCS-51单片机的并行口作为动态显示的段口与位口的示例6位数码管动态显示“”的C5
20、1源程序如下1)随机调用#include#define uchar unsigned charuchar data dis_buf6;/显示缓冲区uchar code table18=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00;/代码表void dl_ms() /延时1ms函数 unsigned int j;for(j=0;j200;j+);void display(void)/显示函数 uchar segcode, bitcode, i; bitcode=0
21、xfe;/位码赋初值 for(i=0;i6;i+) segcode=dis_bufi;/显示缓冲器内容查表 P0=tablesegcode; P3=bitcode; dl_ms( ); P3=0xff;/关闭显示 bitcode=bitcode1;/调整位码 bitcode=bitcode|0x01; void main(void) dis_buf0=1; dis_buf1=2; dis_buf2=3; dis_buf3=4; dis_buf4=5;dis_buf5=6; while(1) display( ); (2)定时调用定时调用是通过定时器/计数器的定时功能来定时一定的时间(如20ms
22、),定时时间到来调用显示函数。void main(void) /定时调用 TMOD=0x01; TH0=-20000/256; TL0=-2000%256; EA=1;ET0=1; TR0=1; dis_buf0=1;dis_buf1=2;dis_buf2=3;void time0_int( ) interrupt 1TH0=-20000/256; TL0=-2000%256; display( ); dis_buf3=4;dis_buf4=5;dis_buf5=6; while(1) ;【例6-6】独立式按键示例C51源程序如下:#include#define uchar unsigned
23、char#define uint unsigned intuchar data key2;code uchar dirtab=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80;void dl_6( ) uint i; for(i=0;i600;i+);void key( ) uchar key1; P1=0xff; key1=P1; if(key1!=0xff) dl_6( ); P1=0xff;key1=P1; if(key1!=0xff) key1=P1; switch(key1) case 0xff: key2=8; break; case 0xf
24、e: key2=0; break; case 0xfd: key2=1; break; case 0xfb: key2=2; break; case 0xf7: key2=3; break; case 0xef: key2=4; break; case 0xdf: key2=5; break; case 0xbf: key2=6; break; case 0x7f: key2=7; break; default:break; void main( ) key2=8; while(1) key( ); P3=dirtabkey2; 【例6-7】 44矩阵键盘示例 #include#define
25、uchar unsigned char#define uint unsigned intuchar data dir_buf;code uchar dirtab=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40;code uchar keytab=0xee,0xed,0xeb,0xe7,0xde,0xdd,0xdb,0xd7,0xbe,0xbd,0xbb,0xb7,0x7e,0x7d,0x7b,0x77;void delay(void);void keyscan( );vo
26、id dir( );uchar key;void main(void) dir_buf=16; while(1) keyscan( ); dir( ) ; void dir( ) P2=dirtabdir_buf;void delay(void) uchar i; for(i=0;i200;i+);void keyscan( ) uchar code_h,code_l,i1,i2; P1=0xf0; /所有的行输出0 code_l=P1; /读列值 code_l=code_l&0xf0; /屏蔽掉高4位 if(code_l!=0xf0) delay( ); / P1=0xf0; code_l=
27、P1; code_l=code_l&0xf0; if(code_l!=0xf0) code_h=0xfe; for(i1=0;i14;i1+) kk:P1=code_h; code_l=P1; code_l=code_l&0xf0; if(code_l=0xf0) code_h=(code_h1)|0x01; goto kk; goto ll; /for ll: code_h=code_h&0x0f; key=code_h+code_l; for(i2=0;i216;i2+) if(key=keytabi2) dir_buf=i2; *【例6-10】一个88共阴极LED点阵显示“ILOVEYO
28、U” (不用记)一个88在某一个时刻只能显示一个字符,要想显示字符串,必须在显示完一个字符后接着显示下一个字符,因此需要建立一个字符串库。由于每个字符有8个段码值,该字符串有8个字符,所以该字符串库中有88共64个段码值。字符串ILOVEYOU的字模段码值 I 00H,00H,42H,7EH,42H,42H,00H,00HL 00H,42H,7EH,42H,02H,02H,02H,00HO 00H,3CH,22H,42H,42H,22H,3CH,00HV 00H,40H,70H,0CH,0CH,70H,40H,00HE 00H,42H,7EH,4AH,4AH,5AH,22H,00HY 00H,
29、40H,62H,1EH,12H,60H,40H,00HO 00H,3CH,22H,42H,42H,22H,3CH,00HU 00H,7CH,46H,02H,02H,7CH,40H,00H#include#define uint unsigned int#define uchar unsigned charcode uchar tab1=0x00,0x00,0x42,0x7e,0x42,0x42,0x00,0x00,/I 0x00,0x42,0x7e,0x42,0x02,0x02,0x02,0x00,/L0x00,0x3c,0x22,0x42,0x42,0x22,0x3c,0x00,0x00,0
30、x40,0x70,0x0c,0x0c,0x70,0x40,0x00,x00,0x42,0x7e,0x4a,0x4a,0x5a,0x22,0x00,0x00,0x40,0x62,0x1e,0x12,0x60,0x40,0x00, 0x00,0x3c,0x22,0x42,0x42,0x22,0x3c,0x00, 0x00,0x7c,0x46,0x02,0x02,0x7c,0x40,0x00 ;/Ucode uchar tab2=0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07;data uchar j;void delay(uint n) data uint i; f
31、or(i=0;in;i+); void dir( )data uchar h,v=0; for( h=j;hj+8;h+) P0=tab1h; P3=tab2v; delay(555); P3=0xff; v+; if(v=8) v=0; void dl( ) uint r;for(r=0;r40;r+)dir( ); void main(void) while(1) j=0; dir( );dl( ); j=8; dir( );dl( );j=16; dir( );dl( );j=24; dir( );dl( );j=32; dir( );dl( );j=40; dir( );dl( );j
32、=48; dir( );j=56; dir( );dl( ); *例6-12 编程在LCD1602上显示由键盘输入的字符或数字。(不用记)/S51+1602,晶振为12M#includereg51.h #includeintrins.h #includeabsacc.hsbit RS=P35; sbit RW=P36; sbit E=P37; #define busy 0x80 #define uchar unsigned char #define uint unsigned intuchar a=0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,;void delay_LCM(
33、uchar k)/延时函数 uint i,j; for(i=0;ik;i+) for(j=0;j60;j+) ; void test_1602busy()/测忙函数 P1=0xff; E=1;RS=0;RW=1; _nop_();_nop_(); while(P1&busy)/检测LCD DB7 是否为1 E=0; _nop_(); E=1; _nop_(); E=0; void write_1602Command(uchar co) /写命令函数 test_1602busy(); /检测LCD是否忙 RS=0;RW=0;E=0; _nop_(); P1=co; _nop_(); E=1; /
34、LCD的使能端 高电平有效 _nop_(); E=0; void write_1602Data(uchar Data)/写数据函数 test_1602busy(); P1=Data; RS=1; RW=0; E=1; _nop_(); E=0; void init_1602(void)/初始化函数 write_1602Command(0x38); /LCD功能设定,DL=1(8位),N=1(2行显示) delay_LCM(5); write_1602Command(0x01); /清除LCD的屏幕 delay_LCM(5); write_1602Command(0x06); /LCD模式设定,
35、I/D=1(计数地址加1) delay_LCM(5); write_1602Command(0x0F); /显示屏幕 delay_LCM(5); void DisplayOneChar(uchar X,uchar Y,uchar DData) Y&=1; X&=15; if(Y)X|=0x40; /若y为1(显示第二行),地址码+0X40 X|=0x80; /指令码为地址码+0X80 write_1602Command(X); write_1602Data(DData);void display_1602(uchar *DData,X,Y)/显示函数 uchar ListLength=0; Y
36、&=0x01; X&=0x0f; while(X16) DisplayOneChar(X,Y,DDataListLength); ListLength+; X+; void delay(uint i)/延时程序uint j;for (j=0;ji; j+);uchar checkkey()/ 检测有没有键按下uchar i ; uchar j ; j=0x0f; P2=j; i=P2; i=i&0x0f; if (i=0x0f) return (0); else return (0xff); uchar keyscan()/键盘扫描程序uchar scancode;uchar codevalue;uchar a;uchar m=0;uchar k;uchar i,j; if (checkkey() =0) return (0xff); else delay(100); if (checkkey()=0) return (0xff);else scancode=0xf7;m=0x00; /键盘行扫描初值,M为列数 for (i=1;i=4;i+) k=0x10; P2=scancode; a=P2; for (j=0;j4;j+)/J为行数 if (a&k)=0)