51单片机实验指导书.doc
单 片 机 原 理 及 应 用 实 验 指 导 书温州大学物理与电子信息工程学院2009年9月目 录实验一 指令和汇编语言1实验二 C51序程序设计4实验三 I/O和中断实验7实验四 定时器计数器实验10实验五 键盘显示电路实验13实验六 单片机综合应用设计实验23附录1 Keil 工程文件的建立、设置与目标文件的获得29附录2 C51编程简介2附录3 Keil C51常用库函数原型6实验一 指令和汇编语言一、实验目的1、了解单片机开发系统的各主要组成部分,包括PC、仿真器和实验开发系统;2、掌握仿真器及其软件的使用,初步掌握程序的调试方法,包括跟踪、单步运行和断点设置等;3、熟悉51单片机的指令系统,掌握汇编语言程序的设计方法。二、实验仪器1、自制的C51实验开发板 1块2、直流温压电源 1台3、仿真器(EASYPROBE) 1只4、PC机 1台三、实验内容1、认识51单片机开发系统的结构。40芯扁平电缆PC机仿真器C51实验开发板(目标板)电 源图1-1 51单片机开发系统的结构2、初步认识仿真器软件和Keil C51软件界面及使用,参见附录1。3、简单程序调试(1) 传送指令设置内部RAM的值,(30H)=40H, (40H)=10H,单步执行下列程序,检查结果。MOV R0,#30HMOV A,R0MOV R1, AMOV B, R1 STOP: SJMP STOP执行后:(R0)= ,(R1)= ,(A)= ,(B)= ,(30H)= ,(40H)= 。(2) 运算指令单步执行MOV A, #0BFHMOV 20H, #85HSETB CADD A, 20H MOV A, #0BFHMOV 20H, #85HSETB CADDC A, 20HMOV A, #0BFHMOV 20H, #85HSETB CSUBB A, 20HMOV A, #0BFHMOV B, #85HMUL ABSJMP $结果标志(A)= CY= AC=OV= P= (A)= CY= AC=OV= P= (A)= CY= AC=OV= P= (A)= (B)=CY= AC=OV= P= 4、多字节十进制数加法被加数加数结果低位20H6730H6520H21H4531H7221H22H2332H9822H23H0133H8923H高位图1-2 4字节十进制数相加两个4字节十进制数和相加,将其8421-BCD码按低位到高位存放在地址为20-23H、30-33H的RAM中,运算结果存放在20-23H的地址中,如上图示。运算程序如下,ADD_BCD为多字节十进制数加法子程序的首地址。分别按“跟踪”、“单步”和“全速”方式调试程序。检查运算结果,区别“跟踪”、“单步”调试方式的不同。在“ADD_BCD子程序”的指令“DA A”处设置断点,再用“全速”方式运行,到达断点后,观察“A”的值,然后用“单步”运行,观察指令“DA A”的功能。同时理解“断点” 方式调试程序的特点。;主程序 ; MOV R0, #20H ;置被加数首地址 MOV R1, #30H ;置加数首地址 MOV R2, #04H ;置被加数和加数的长度(字节数) ACALL ADD_BCD ;调用多字节十进制数加法子程序ADD_BCDSTOP:SJMP STOP ;停止; 多字节十进制数加法子程序 ;入口: R0、R1为被加数和加数的首地址,按低位到高位存放;出口: R0为运算结果的首地址,也按低位到高位存放ADD_BCD:CLR C ;进位清零LOOP: MOV A, R0 ;一字节的被加数AADDC A, R1 ;一字节加DA A ;十进制数调整MOV R0, A ;存一字节的运算结果INC R0 ;被加数指向下一字节INC R1 ;加数指向下一字节DJNZ R2, LOOP ;循环控制RET ;子程序返回END四、预习要求1、读懂各程序;2、预先给出运算结果,以便和实验结果比较;3、回忆“跟踪”、“单步”和“断点”调试方式的特点。五、思考题1、为什么程序结束用“STOP:SJMP STOP”指令?用没有其他的停止方式? 51单片机启动后,是否一直不断地在执行指令?2、比较“跟踪”、“单步”和“断点”调试方式的特点。实验二 C51程序设计一、实验目的1、掌握仿真器及Keil C51软件的使用;2、熟悉C51程序的设计方法3、掌握C51程序的调试、诊断和排错方法。二、实验仪器1、仿真器(EASYPROBE) 1只2、PC机 1台三、实验内容1、双字节无符号数乘法运算,分别用汇编和C语言实验该功能,对比各自的特点。(1)汇编语言要求:将(R2R3)和(R6R7)中双字节无符号整数相乘,积送(R4R5R6R7)中。C语言程序:将变量aa和bb中的双字节无符号整数相乘,结果存入变量cc中。(2)汇编程序举例:(参照教科书85页)ORG0000HLJMPDBMULORG0040HDBMUL:MOVA,R3MOVB,R7MULAB;R3*R7(得第一次部分积)XCHA,R7;原R7的内容送A,R7R3R7L(在 ;R7K中得到乘积的第四字节)MOVR5,B;R5R3R7HMOVB,R2MULAB;R2*R7(得第二次部分积)ADDA,R5;R2R7L+R3R7HMOVR4,A;R4和CLRAADDCA,B;R2R7H+(R2R7L+R4时产生的进位)MOVR5,A;R5和MOVA,R6MOVB,R3MULAB;R3*R6(得第三次部分积)ADDA,R4;R3R6L+R4XCHA,R6;AR6,R6R3R6L+R4(在R6中得 ;到乘积的第三字节)XCHA,B;AR3R6H,BR6ADDCA,R5;R3R6H+R5+(R3R6L+R4时产生的进位)MOVR5,A;R5和MOVF0,C;FO进位MOVA,R2MULAB;R2*R6(得第四次部分积)ADDA,R5;R2R6L+(R3R6H+R5时产生的进位)MOVR5,A;在R5中得到乘积的第二字节CLRAMOVACC.0,C;累加器最高位进位MOVC,F0;ADDCA,B;R2R6H+FO+ACC.0MOVR4,A;在R4中得到乘积的第一字节RETENDC语言程序举例:#include <reg51.h>unsigned long aa _at_ 0x30;unsigned int bb _at_ 0x40; unsigned long cc _at_ 0x50;main() /aa=0x1088; /bb=0x20A0;cc=aa*bb;while(1); (3)若(R2R3)/aa=1088H,(R6R7)/bb=20A0H,运行程序检查结果。体会两种语言的各自的特点。2、编写水平垂直校验码生产程序。将你的11位学号生产水平垂直校验码,你的11位学号可以用ASCII码、BCD码 或二进制编码的一种来表示,然后每7位或8位分别进行奇校验,这就是水平校验, 对应的校验位存储位置可以自己规定。需要注意的是,位类型不能定义数组。3、再将上述的水平校验码,进行垂直奇校验,垂直校验位的存储位置也自己规定,得到水平垂直校验码,记下校验码结果。C语言程序举例:#include <reg51.h> unsigned char a11_at_ 0x30; /存储学号 unsigned char b _at_ 0x50; /存储水平校验结果 main() unsigned char i; for(i=0;i<11;i+) ACC = ai; if(P!=1)ACC|=0x80; /水平奇校验 ai=ACC;b=a0; for(i=1;i<11;i+) b=bai; while(1);4、编写相应的水平垂直校验码校验及纠错程序。将上述校验码结果的任何一位取反后,输入水平垂直校验码校验及纠错程序,观察校验结果,并纠错。四、预习要求1、了解水平垂直校验码的生产、校验及纠错过程;2、事先编写水平垂直校验码生产程序和校验及纠错程序。五、思考题1、如何保证变量空间、堆栈空间不会溢出?2、如何实现海明码、CRC校验码的检错和纠错?实验三 I/O和中断实验一、实验目的1、掌握单片机基本I/O口的使用特点,了解本扩展I/O口的方法;2、掌握单片机中断机制,掌握单片机中断的使用特点和编程方法。二、实验仪器 1、C51实验开发板 1块 2、直流温压电源 1台 3、仿真器 1只 4、PC机 1台 5、示波器 1台三、实验内容1、P1口直接输出,驱动LED指示灯,演示跑马灯效果连接仿真器和C51实验开发板,P1口做输出口,P1口连接至8只发光二极管接口JP8,如图3-1所示,接通开发板电源。编写程序,使发光二极管指示灯循环点亮。P1CPU89C51(接仿真头)图3-1 P1口输出CPU 89C51的振荡频率为11.0592MHz,发光二极管循环点亮需要一个延时子程序DELAY。延时时间为 (0B3+1)×256×10+2)×2×12÷=1(秒)。DELAY:MOV R5,#0AHMOV R6,#00HDELAY1:MOV R7,#0B3H DJNZ R7,$ DJNZ R6,DELAY1 DJNZ R5,DELAY1 RET 汇编语言参考主程序 ORG 0000H LJMP START ORG 0050HSTART:MOV A,#0FEH LOOP: MOV P1,A RL A LCALL DELAY SJMP LOOP修改上述程序,使指示灯两两右循环;修改上述程序,使指示灯右循环间隔为0.1秒;C语言参考程序:#include <reg51.h>code unsigned char C51BOX23 _at_ 0x43;void delay(void); unsigned char RL(unsigned char c,n);main() unsigned char n; /*n是循环移位数*/ P0 = 0xFE; /*P1为*/ n = 1; /*设定移位数为1,可以定义所需循环移动的位数,例如:2,3等*/ while(1) P0 = RL(P0,n); delay(); /*延时函数*/void delay(void) unsigned char i,j,k; for(i=100;i!=0;i-) for(j=100;j!=0;j-) for(k=50;k!=0;k-);/*循位左移位函数*/unsigned char RL(unsigned char c,n) unsigned char a,b,result; a=c>>(8-n); b=c<<n; result=a|b; return(result);修改上述程序,使指示灯两两右循环;修改上述程序,使指示灯右循环间隔为0.1秒;2、P1口直接输入,读取DIP开关值,P2直接输出,用LED指示结果P1做输入口,连接至DIP开关接口JP4,P2口输出连接至8只发光二极管接口JP8,如图3-2所示。编写程序,使DIP开关的电平通过发光二极管指示灯显示出来。P1CPU89C51P2图3-2 P1口输入由于51单片机的I/O口特点,输入口读入数据前要求先置1,使I/O口上的下拉管截止,为外部数据的输入做准备。汇编参考程序 ORG 0000H LJMP START ORG 0040HSTART:MOV P1,#0FFH ;P1口置1 MOV A,P1 ;读入P1口的DIP电平MOV P2,A ;P2口输出至指示灯 SJMP START将参考程序改为C程序。3、P3口查询方式输入的交通灯时序P3口作为输入口,查询P3.2的电平。当P3.2为低电平时,P2.0输出的1赫兹的方波,表示正常情况下的交通灯时序;当P3.2为高电平时,P2.0输出占空比为75%的2赫兹矩形波,表示紧急情况下的交通灯时序。用C程序来实现上述交通灯时序的功能,延时时间可通过示波器大致地校准。C语言参考程序:#include <reg51.h>sbit P3.2=P30;void delay(unsigned char ntime); main() P2 = 0; while(1) if (P3.2) P2|=0x01; delay(75); P2&=0x01; delay(25); else P2=0x01; delay(100);; /*延时函数*/void delay(unsigned char ntime) unsigned char i,j,k; for(i=ntime;i!=0;i-) for(j=100;j!=0;j-) for(k=50;k!=0;k-);4、中断方式输入的交通灯时序将P3.2作为单片机的中断信号INT0,利用中断方式,读取P3.2的电平,实现上述交通灯时序。用C程序编写中断程序函数,以及初始化和主程序。C语言参考程序:#include <reg51.h>void delay(unsigned char ntime) ;void INT_0(void) interrupt 0 / 外部中断程序 P2|=0x01; delay(75); P2&=0xFE; delay(25); void Init_INT0(void) /初始化 IT0=0; / INT0低电平触发(为1则为下降沿触发) EA=1; / CPU所有中断开(IE最高位MSB) EX0=1; / INT0中断开 main() P2 = 0; Init_INT0(); while(1) P2=0x01; delay(100); /*延时函数*/void delay(unsigned char ntime) unsigned char i,j,k; for(i=ntime;i!=0;i-) for(j=100;j!=0;j-) for(k=50;k!=0;k-);四、预习要求1、指出中断的设置和开启(即初始化)需要用到哪些特殊功能寄存器的哪些功能位。指出中断响应以及中断返回时,硬件完成哪些操作,软件完成了哪些操作。软件操作部分的代码中哪些由编译器直接生成,哪些由用户程序完成。2、事先修改和编写相应的程序。五、思考题1、如何设置堆栈空间?2、中断方式输入的交通灯时序的程序中,在中断响应时,哪些变量值要入栈,共占用多少栈空间。实验四 定时器计数器实验一、实验目的1、掌握单片机定时器的工作原理,体会定时器的使用特点;2、进一步掌握中断的技术编程方法和特点;3、体会用定时器中断扫描键盘,以提高CPU的效率。二、实验仪器1、C51实验开发板 1块2、直流温压电源 1台3、仿真器 1只4、PC机 1台三、实验内容1、在P1.0脚上输出2KHz的方波2KHz的方波需要定时器产生0.25ms连续的定时信号,可选用T0方式2,自动装入参数的8位定时方式。单片机的主频为11.0592MHz,定时器初始值应为256-0.25×1000×11.0592/12=26=1AH参考程序 ORG 0000H AJMP START ORG 000BH ;T0中断入口地 CPL P1.0 RETI ORG 0100HSTART: MOV SP,#2FH MOV TMOD,#02H ;置T0为方式2 MOV TL0,#1AH ;延时0.25mS的定时器初始值 MOV TH0,#1AH SETB PT0 SETB TR0 SETB ET0 SETB EA ;开中断 SJMP $运行程序,用示波器观察波形的脉宽和周期。将上述程序改为C程序,重新运行,观察波形的脉宽和周期。#include <reg51.h>void TIME0(void) interrupt 1 / 外部中断程序 P2=0x01; void Init_TIME0(void) /初始化 TMOD = 0x2; TL0 = 0x1A; TH0 = 0x1A; PT0 = 1; TR0 = 1; ET0 = 1; EA = 1; main() Init_TIME0(); while(1); 2、秒计数秒计数可用20次50ms的计数溢出来实现。50ms的计数可选用T0方式1,16位定时方式,定时器初始值应为65536-50×1000×11.0592/12=19456=4C00H 考虑中断响应时间及重装定时器初始值的时间共计约4个机器周期,定时器初始值加4(即4C04)。秒计数值通过P2口输出,用LED指示灯显示。参考程序 ORG 0000H AJMP START ORG 000BH ;T0中断入口地 LJMP INT0 RETI ORG 0100HSTART: MOV SP,#2FH MOV TMOD,#01H ;置T0为方式1 MOV TL0,#04H ;延时50mS的定时器初始值 MOV TH0,#4CH SETB PT0 SETB TR0 SETB ET0 SETB EA ;开中断 MOV R7,#20 ; 20次计数溢出计数器 MOV R6,#00 ; 秒计数器 MOV DPTR,#TAB ;显示秒计数LOOP: MOV A,R6 ;显示高4位 SWAP A ANL A,#0FH MOVC A,A+DPTR ;读字段码MOV P2,#60H ;字段码地址MOVX R0,A ;输出字段码MOV A,#0FBH ;1号灯MOV P2,#80H ;灯位控制地址MOVX R0,A ;输出灯位控制LCALL DELAY ;延时 MOV A,R6 ;显示低4位 ANL A,#0FH MOVC A,A+DPTR ;读字段码MOV P2,#60H ;字段码地址MOVX R0,A ;输出字段码MOV A,#0F7H ;4号灯MOV P2,#80H ;灯位控制地址MOVX R0,A ;输出灯位控制LCALL DELAY ;延时 SJMP LOOP;中断服务程序INT0: MOV TL0,#04H ;延时50mS的定时器初始值 MOV TH0,#4CH DJNZ R7,SKIP INC R6 MOV R7,#20SKIP: RETIDELAY:TAB:DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07HDB 7FH,6FH,77H,7CH,39H,5EH,79H,71H ;“0”-“F”的字段码 ORG 0000H AJMP START ORG 000BH ;T0中断入口地 LJMP INT_0 RETI ORG 0100HSTART: MOV SP,#2FH MOV TMOD,#01H ;置T0为方式1 MOV TL0,#04H ;延时50mS的定时器初始值 MOV TH0,#4CH SETB PT0 ; SETB TR0 ; SETB ET0 ; SETB EA ; ;开中断 MOV R7,#20 ; ; 20次计数溢出计数器 MOV R6,#00 ; ; 秒计数器 MOV DPTR,#TAB ; ;显示秒计数LOOP: MOV A,R6 ; ;显示高4位 SWAP A ; ANL A,#0FH; MOVC A,A+DPTR ; ;读字段码 MOV P2,#60H ; ;字段码地址 MOVX R0,A ; ;输出字段码 MOV A,#0FBH ; ;3号灯 MOV P2,#80H ; ;灯位控制地址 MOVX R0,A ; ;输出灯位控制 LCALL DELAY ; ;延时 MOV A,R6 ; ;显示低4位 ANL A,#0FH ; MOVC A,A+DPTR ;;读字段码 MOV P2,#60H ; ;字段码地址 MOVX R0,A ; ;输出字段码 MOV A,#0F7H ; ;4号灯 MOV P2,#80H; ;灯位控制地址 MOVX R0,A ; ;输出灯位控制 LCALL DELAY ; ;延时 SJMP LOOP;;中断;服务程序 ;INT_0: MOV TL0,#04H ; ;延时50mS的定时器初始值 MOV TH0,#4CH ; DJNZ R7,SKIP ; INC R6 ; MOV R7,#20 ;SKIP: RETI ;DELAY: MOV R5,#46H DJNZ R5,$ RETTAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71HORG 0000H AJMP START ORG 000BH ;T0中断入口地 LJMP INT_0 RETI ORG 0100HSTART: MOV SP,#2FH MOV TMOD,#01H ;置T0为方式1 MOV TL0,#04H ;延时50mS的定时器初始值 MOV TH0,#4CH SETB PT0 ; SETB TR0 ; SETB ET0 ; SETB EA ; ;开中断 MOV R7,#20 ; ; 20次计数溢出计数器 MOV R6,#00 ; ; 秒计数器LOOP: MOV DPTR,#TAB ; ;显示秒计数 MOV A,R6 ; ;显示高4位 SWAP A ; ANL A,#0FH; MOVC A,A+DPTR ; ;读字段码 ;MOV P2,#60H ; ;字段码地址 MOV DPTR,#6FFFH; MOVX DPTR,A ; ;输出字段码 MOV A,#0FBH ; ;3号灯 ;MOV P2,#80H ; ;灯位控制地址 MOV DPTR,#8FFFH MOVX DPTR,A ; ;输出灯位控制 LCALL DELAY ; ;延时 MOV DPTR,#TAB MOV A,R6 ; ;显示低4位 ANL A,#0FH ; MOVC A,A+DPTR ;;读字段码 MOV DPTR,#6FFFH; ;字段码地址 MOVX DPTR,A ; ;输出字段码 MOV A,#0F7H ; ;4号灯 MOV DPTR,#8FFFH; ;灯位控制地址 MOVX DPTR,A ; ;输出灯位控制 LCALL DELAY ; ;延时 SJMP LOOP;;中断;服务程序 ;INT_0: MOV TL0,#04H ; ;延时50mS的定时器初始值 MOV TH0,#4CH ; DJNZ R7,SKIP ; MOV A, R6 ; INC A DA A MOV R6,A MOV R7,#20 ;SKIP: RETI ;DELAY: MOV R5,#46H DJNZ R5,$ RETTAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H END设计C程序实现上述秒计数功能。#include <reg51.h>#include <intrins.h>code unsigned char C51BOX23 _at_ 0x43;unsigned char n; /20次计数溢出计数器unsigned char time; / 秒计数器unsigned char code led7code=0X3f,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F;unsigned char xdata LED_light _at_ 0x8FFF; /灯位地址unsigned char xdata LED_seg _at_ 0x6FFF; /段码地址void TIME0(void) interrupt 1 / 外部中断程序 TL0 = 0x04;TH0 = 0x4c;-n;if(n=0) +time; n = 20; if(time=100) time=0; void Init_TIME0(void) /初始化