软件实验一
1、分别编程实现两个16位无符号数相加,结果存放在40H41H中;两个16位的无符号数相减,结果存放在30H31H中。
; 两个16位无符号数相加,结果存放在30H31H中
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN :
MOV R3,#01H ;输入加数高八位
MOV R4,#23H ;输入加数低八位
MOV R5,#45H ;输入被加数高八位
MOV R6,#67H ;输入被加数低八位
MOV A,R4 ;将R4存入寄存器A
ADD A,R6 ;A与R6相加,结果存入A
MOV 31H,A ;将低八位的和数存入31H
MOV A,R3 ;将R3存入寄存器A
ADDC A,R5 ;A与R5相加,结果存入A
MOV 30H,A ;将高八位的和数存入30H
SJMP $
END
; 两个16位的无符号数相减,结果存放在30H31H中。
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN :
MOV R3,#12H ;输入减数高八位
MOV R4,#34H ;输入减数低八位
MOV R5,#56H ;输入被减数高八位
MOV R6,#78H ;输入被减数低八位
MOV A,R4 ;将R4存入寄存器A
CLR C ;C位清"0"
SUBB A,R6 ;A与R6相减,结果存入A
MOV 31H,A ;将低八位的差数存入31H
MOV A,R3 ;将R3存入寄存器A
SUBB A,R5 ;A与R5相减,结果存入A
MOV 30H,A ;将高八位的差数存入30H
SJMP $
END
2、编程实现
X (X ≥40)
Y= 2X (20 ;实现X>=40时,Y=X;20 LJMP MAIN ORG 0030H MAIN: CMP40: CJNE R2,#40,NEXT0 ;X与40比较,结果由CY读出 NEXT0: JNC BIGGER40 ;判断C的值,C为0时则X大于或者等于40,跳到BIGGER40 JC CMP20 ;判断C的值,C不为0时则X小于40,跳到CMP20 CMP20: CJNE R2,#21,NEXT1 ;X与21比较,结果由CY读出 NEXT1: JNC BIGGER20 ;判断C的值,C为0时则X大于或者等于21(即X大于20),跳到BIGGER20 JC SMALLER20 ;判断C的值,C不为0时则X小于20,跳到SMALLER20 BIGGER40: MOV A,R2 ;X>=40时,将X的值赋给存放Y的值的R3 MOV R3,A SJMP $ BIGGER20: MOV A,R2 ;20 MUL AB MOV R3,A SJMP $ SMALLER20: CLR A ;X<20时,将0赋给Y MOV R3,A SJMP $ 3、学生实验:编写80个数相加,结果存放在30H31H中。 ;编写80个数相加,结果存放在30H31H中 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV R2,#80 ;输入累加的个数N存放到R2中 MOV R0,#32H ;输入参与累加数据的首个数据的地址 ADDER: MOV A,@R0 ;将参与累加的数据的值赋给A ADD A,31H ;将A与当前累加数的和的低位(31H)相加结果存放在A中 MOV 31H,A ;将求得的和数的低位放入31H中 CLR A ;对A清"0" ADDC A,30H ;计算已得累加数高位与当前进位相加,结果存放在A中 MOV 30H,A ;将求得的和数的高位放入30H中 INC R0 ;R0中的数据加1 LOOP: DJNZ R2,ADDER ;循环判断 SJMP $ END 软件实验二 1、编写R1×R2R3=R4R5R6,R1R2×R3R4=R4R5R6R7。 ; R1×R2R3=R4R5R6 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV A,R3 ; R1乘以低位数R3 R3xR1=R5R6 MOV B,R1 MUL AB MOV R6,A MOV R5,B MOV A,R2 ; R1乘以高位数R2 ;R2xR1=R4A MOV B,R1 MUL AB MOV R4,B ADD A,R5 ; 高。低乘数结果相加 R5+A=R5 MOV R5,A ;R4+CY=R4 MOV A,R4 ADDC A,#00H MOV R4,A SJMP $ END ;R1R2×R3R4=R4R5R6R7 ORG 0000H LJMP MAIN ORG 0030H ;————R2乘以R3R4存放于R5R6R7 MAIN: LCALL MULL MOV R5,30H MOV R6,31H MOV R7,32H ;调用子程序MULL ;————R1先赋给R2,再乘以R3R4 MOV A,R1 MOV R2,A LCALL MULL ;调用子程序MULL CLR C ;进位清"0" MOV A,32H ;R6加上32H中的值,存放于R6 ADD A,R6 MOV R6,A MOV A,R5 ;R5加上31H中的值,存放于R5 ADDC A,31H MOV R5,A MOV A,#00H ;30H加上进位C,存放于R4 ADDC A,30H MOV R4,A SJMP $ ;————子程序MULL:实现R2乘以R3R4R结果存放于30H31H32H MULL: MOV A,R4 ; R2乘以低位数R4 R3xR1=31H32H MOV B,R2 MUL AB MOV 32H,A MOV 31H,B MOV A,R3 ; R2乘以高位数R3 ;R2xR1=30H MOV B,R2 MUL AB MOV 30H,B ADD A,31H ; 高。低乘数结果相加 31H+A=31H MOV 31H,A ;30H+CY=30H MOV A,30H ADDC A,#00H MOV 30H,A RET END 2、找出内RAM中从30H到50H中在最小值。 ;找出内RAM中从30H到50H中在最小值,并将最小值存放于60H中 ORG 0000H LJMP MAIN ORG 0030H ADDRMAX EQU 50H ;定义ADDRMAX为所查找范围的上限值 ADDRMIN EQU 30H ;定义ADDRMIN为所查找范围的下限值 MAIN: MOV R0,#ADDRMIN ;将地址指针存放于R0中,并赋初值 LOOP1: MOV 60H,@R0 LOOP2: CJNE R0,#ADDRMAX,NEXT1;判断R0是否达到所查找范围的上限 NEXT1: JNC OUT ;是就跳出循环 INC R0 ;否则RO加1 MOV A,@R0 CJNE A,60H,NEXT2 ;将相邻两个数((R0))和(60H)进行比较 NEXT2: JNC LOOP2 ;若((R0))大于(60H)则直接跳到LOOP2 JC LOOP1 ;若((R0))小于或者等于(60H)则 OUT: SJMP $ ;跳到LOOP1 END 3、用查表方式编写y=x3(x为0~9的整数),要求分别用@A+DPTR和@A+PC的方法。 ;用@A+DPTR的方法,X存放于R4中,Y存放于R2R3中 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV A,R4 ADD A,R4 ;将累加器A翻倍 MOV DPTR,#TAB MOVC A,@A+DPTR MOV R2,A MOV A,R4 ;重新将X的值存入A ADD A,R4 ;A翻倍 INC A ;A加1 MOVC A,@A+DPTR MOV R3,A SJMP $ TAB: DW 0000H,0001H,0008H,0019H,0040H ;0~9立方表 DW 007DH,00C4H,0157H,0200H,02D9H END ;用@A+PC的方法。X存放于R4中,Y存放于R2R3中 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV A,R4 ADD A,R4 ;存放X的R4加倍 ADD A,#09H ;累加器加上偏移量 MOVC A,@A+PC MOV R2,A MOV A,R4 ADD A,R4 ADD A,#04H ;累加器加上偏移量 MOVC A,@A+PC MOV R3,A SJMP $ TAB: DW 0000H,0001H,0008H,0019H,0040H ;0~9立方表 DW 007DH,00C4H,0157H,0200H,02D9H END 4.编程实现:时钟频率6MHZ,延时2MS;时钟频率12MHZ,延时10S ;延时2MS,时钟频率6MHZ ORG 0000H LJMP MAIN ORG 0030H MAIN: LCALL DEL SJMP $ DEL: MOV R7,#5 ;外循环 DEL1: MOV R6,#100 ;内循环 DEL2: DJNZ R6,DEL2 ;先执行内循环,后执行外循环 DJNZ R7,DEL1 RET END ;延时10S,时钟频率12MHZ ORG 0000H LJMP MAIN ORG 0030H MAIN: LCALL DEL SJMP $ DEL: MOV R7,#5 ;外二循环 DEL1: MOV R6,#50 ;外一循环 DEL2: MOV R5,#200 ;内循环 DEL3: DJNZ R5,DEL3 ;先执行内循环,后执行外一循环 DJNZ R6,DEL2 ;最后执行外二循环 DJNZ R7,DEL1 RET END 软件实验三 1、 用查表方式编写y=x13+x23+x33。(x为0~9的整数) #include void main() { int a[10]={0,1,8,27,,125,216,343,512,729}; //0~9的立方表 int x1,x2,x3,y; x1=0; x2=6; x3=6; y=a[x1]+a[x2]+a[x3]; //X1,X2,X3的立方和 while(1); } 2、 有10个8位二进制数据,要求对这些数据进行奇偶校验,凡是满足偶校验的数据(1的个数为偶数)都要存到内RAM50H开始的数据区中。试编写有关程序。 #include void main() { unsigned char data a[10]={0,1,8,19,40,75,88,57,2,9}; //二进制数据存入数组a中 char i; char *d=0x50; //定义d为指向内RAM50H的指针 //对a[i]进行奇偶校验,偶数存入内RAM50H开始的数据中 for(i==0;i<10;i++) { ACC=a[i]; //a[i]存入累加器ACC中 if (P==0) //对a[i]进行奇偶校验 { *d=a[i]; //偶数存入内RAM50H开始的数据区中 d++; //d指针加1 } } while(1); } 3、 有10个8位带符号二进制数,请将10个数按从小到大的顺序排列,并存到内RAM50H开始的单元中。 #include void main() { signed char data a[10]={0,-100,-80,110,40,105,88,57,-2,9}; //将二进制数存入数组a char i,j,k,x,y; char *d=0x50; //定义d为指向内RAM50H的指针 //冒泡法排序,由小到大 x=10; for(i==0;i<10;i++) { x--; j=0; for(j==0;j if (a[j]>a[j+1]) //判断a[j]>a[j+1],是的话两者互换 {y=a[j+1];a[j+1]=a[j];a[j]=y;} } } //排序后数据存入内RAM50H开始的单元中 for(k==0;k<10;k++) { *d=a[k]; d++; } while(1); } 硬件实验一 p1口输入输出实验 1.基本部分: (1). P1口做输出口,接八只发光二极管,使发光二极管循环点亮; (2). P1.0,P1.1作输入口接两个拨动开关,P1.2,P1.3作输出口,接两个发光二极管,读取开关状态,在发光二极管上显示出来。 ;P1口做输出口,接八只发光二极管,使发光二极管循环点亮 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV P1,#80H LED: LCALL DELAY_100MS MOV A,P1 RR A MOV P1,A SJMP LED ;子程序:延时50MS DELAY_100MS: MOV R3,#200 ;第二层循环赋值 LOOP1: MOV R2,#125 ;第一层循环赋值 LOOP2: DJNZ R2,LOOP2 DJNZ R3,LOOP1 RET END ;P1.0,P1.1作输入口接两个拨动开关,P1.2,P1.3作输出口,接两个发光二极管 ORG 0000H LJMP MAIN ORG 0030H MAIN: SETB P1.0 ;设置P1.0和P1.1为输入口 SETB P1.1 SWITCH: MOV C,P1.0 MOV P1.2,C MOV C,P1.1 MOV P1.3,C SJMP SWITCH 2.扩展部分: (1)利用P1口控制发光二极管LED灯按照下面方式工作: (A)LED灯从左到右依次点亮; (B)LED灯从右到左依次点亮; (C)(C)按照以上步骤重复运行,其中要求灯亮的时间为500MS ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV P1,#80H ;A.LED灯从左到右依次点亮 LED1: MOV R5,#07H MOV R6,#07H LED2: LCALL DELAY_500MS ;延时500MS MOV A,P1 RR A MOV P1,A DJNZ R5,LED2 ;B.LED灯从右到左依次点亮 LED3: LCALL DELAY_500MS ;延时500MS MOV A,P1 RL A MOV P1,A DJNZ R6,LED3 SJMP LED1 ;子程序:延时500MS DELAY_500MS: MOV R4,#10 ;第三层循环赋值 LOOP0: MOV R3,#100 ;第二层循环赋值 LOOP1: MOV R2,#125 ;第一层循环赋值 LOOP2: DJNZ R2,LOOP2 LOOP3: DJNZ R3,LOOP1 DJNZ R4,LOOP0 RET END (2) 利用P1口控制发光二极管LED灯按照下面方式工作: (A) 从左到右奇数LED灯依次点亮; (B) 从右到左偶数LED灯依次点亮; (C) 按照以上步骤重复运行,其中要求灯亮的时间为500MS ;利用P1口控制发光二极管LED灯按照下面方式工作 ;A.从左到右奇数LED灯依次点亮; 2 ;B.从右到左偶数LED灯依次点亮; ;C.按照以上步骤重复运行,其中要求灯亮的时间为500MS ORG 0000H LJMP MAIN ORG 0030H MAIN: LED1: MOV R5,#03H MOV R6,#03H MOV P1,#80H LCALL DELAY_500MS ;A.从左到右奇数LED灯依次点亮; LED2: MOV A,P1 RR A RR A MOV P1,A LCALL DELAY_500MS ;延时500MS DJNZ R5,LED2 MOV P1,#01H LCALL DELAY_500MS ;B.从右到左偶数LED灯依次点亮; LED3: MOV A,P1 RL A RL A MOV P1,A LCALL DELAY_500MS ;延时500MS DJNZ R6,LED3 SJMP LED1 ;子程序:延时500MS DELAY_500MS: MOV R4,#10 ;第三层循环赋值 LOOP0: MOV R3,#100 ;第二层循环赋值 LOOP1: MOV R2,#125 ;第一层循环赋值 LOOP2: DJNZ R2,LOOP2 LOOP3: DJNZ R3,LOOP1 DJNZ R4,LOOP0 RET END 硬件实验二 外部中断实验 1.基本部分: //用单次脉冲申请中断,在中断处理程序中对输出信号进行反转。 #include sbit p1_0=P1^0; //主程序,对外部中断0初始化 void main() {EA=1; EX0=1; IT0=1; while(1); } //外部中断服务子程序 int0() interrupt 0 {if(p1_0==0) p1_0=1; //对P1_0信号进行反转 else if(p1_0==1) p1_0=0; } 2.扩展部分: //将外部中断源连接到单片机的外部中断1上,计算其外部中断1的中断次数(<255) //并能实时将结果显示在发光二极管LED上(二进制形式)。 #include int data x=0; void main() {P1=0; EA=1; //外部中断0初始化 EX0=1; IT0=1; while(1) ; } //中断服务子程序 int0() interrupt 0 {x++; //计数 P1=x; } 硬件实验三 外部中断(急救车与交通灯) //模拟交通灯控制 //平时按交通灯方式运作 //急救车通过时,四个方向的交通灯均亮红灯5秒 #include int x,y,i,j,k; //变量声明 int d0,d1,d2,d3; void com_led(); //函数声明 void com_interrupt(); void delay(x); void main() {com_led(); // 灯初始化 com_interrupt(); // 外部中断0初始化 do{P1=0x0C; //东西向亮红灯55秒,南北向亮绿灯55秒, delay(11); P1=0x0A; //东西向亮红灯5秒,南北向亮绿灯5秒, delay(1); P1=0x21; //东西向亮绿灯55秒,南北向亮红灯55秒, delay(11); P1=0x11; //东西向亮黄灯55秒,南北向亮红灯55秒, delay(1); } while(1); } //外部中段0服务子程序 int accident() interrupt 0 {y=P1; //现场保护 d0=x; d1=i; d2=j; d3=k; P1=0x09; //急救车通过,东西南北向均亮红灯5秒 delay(1); x=d0; //现场恢复 1 i=d1; j=d2; k=d3; P1=y; } //交通灯初始化函数 void com_led() {P1=0x09; //东西南北向灯均亮5秒 delay(1); } //外部中段0初始化函数 void com_interrupt() {EA=1; EX0=1; IT0=1; } //延时5*X秒函数 void delay(x) {do{for(i=0;i<7;i++) for(j=0;j<215;j++) for(k=0;k<200;k++); } while(--x); } 硬件实验四 定时器实验 1.基本部分: ;用CPU内部定时器中断方式计时,实现每一秒钟输出状态发生一次反转 ORG 0000H LJMP MAIN ORG 001BH ;定时器1中断入口 LJMP IT1P ORG 0030H MAIN: MOV R0,#200 MOV R1,#50 MOV TMOD,#20H ;定时器1初始化,选择方式2 MOV TH1,#0CEH ;定时器装入初值,一次计时100微秒 MOV TL1,#0CEH SETB EA ;开相应端口 SETB TR1 SETB ET1 SJMP $ IT1P: DJNZ R0,LOOP4 ;每计时10000次(即1秒),P1.0翻转一次 DJNZ R1,LOOP3 CPL P1.0 MOV R1,#50 LOOP3: MOV R0,#200 LOOP4: RETI END 2.扩展部分: ;利用定时器T1实现LED灯左右移动 ORG 0000H LJMP MAIN ORG 001BH ;定时器1中断入口 LJMP IT1P ORG 0030H MAIN: MOV R0,#100 MOV R1,#50 MOV R2,#0FFH LOOP0: LCALL PT1M2 ;调用T1初始化子程序 MOV R3,#04H MOV R4,#04H MOV P1,#80H SETB TR1 ;开定时允许端口 LOOP1: CJNE R2,#00H,LOOP1 ;计时器运行一次后再往下运行,R2为0时则已经运行一次 MOV R2,#0FFH ;R2重新赋非0值 MOV A,P1 ;P1的值右移两位 RR A RR A MOV P1,A SETB TR1 ;重新开定时器允许端口 DJNZ R3,LOOP1 ;循环3次 MOV P1,#01H ;P1赋01H LOOP2: CJNE R2,#00H,LOOP2 ;计时器运行一次后再往下运行,R2为0时则已经运行一次 MOV R2,#0FFH ;R2重新赋非0值 MOV A,P1 ;P1的值左移两位 RL A RL A MOV P1,A SETB TR1 ;重新开定时器允许端口 DJNZ R4,LOOP2 ;循环3次 LJMP LOOP0 PT1M2: MOV TMOD,#20H ;T1初始化子程序 MOV TH1,#0CEH MOV TL1,#0CEH SETB EA SETB ET1 RET IT1P: DJNZ R0,T1P4 ;T1中断服务子程序 DJNZ R1,T1P3 ;每500毫秒,定时器允许端口就关掉 CLR TR1 ;等P1左移或者右移结束再重新开启 MOV R2,#00H MOV R1,#50 T1P3: MOV R0,#100 T1P4: RETI END 硬件实验五 计数器实验 1.基本部分: ;8031内部定时计数器T0,按计数器模式和方式1工作,对P3.4(T0)进行计数,将其值 ;按二进制在P1口驱动LED灯上显示出来。 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV TMOD,#05H ;计数器初试化,按计数器模式和方式1工作? MOV TH0,#00H ;计数器清0 MOV TL0,#00H SETB ET0 ;开计数中断 SETB EA ;开总中断 SETB TR0 ;开计数允许 LOOP: MOV P1,TL0 ;将计数器的低八位赋给P1,以驱动LED灯显示 AJMP LOOP END 2.扩展部分: ;利用T0作为定时器,T1作为计数器,将实验箱上的脉冲信号源接到T1引脚, ;测量出脉冲信号源的频率 ORG 0000H LJMP MAIN ORG 000BH ;定时器T0中断入口 LJMP IT0P ORG 0030H MAIN: MOV TMOD,#25H ;T0,T1初始化,T0作为定时器(方式2),T1作为计数器(方式1) MOV TH0,#0CEH ;T0装入初值 MOV TL0,#0CEH MOV TH1,#00H ;T1清0 MOV TL1,#00H MOV R2,#100 ;定时10毫秒标志位,R2为0时说明已定时10毫秒 SETB TR0 ;允许定时器T0定时 SETB TR1 ;允许计数器T1计数 SETB ET0 ;开T0中断 SETB ET1 ;开T1中断 SETB EA ;开总中断 OUT: MOV P1,TL1 ;将计数器低八位赋给P1,驱动LED灯显示 CJNE R2,#00H,OUT ;定时10毫秒判断,满10毫秒后关闭TR0,TR1 CLR TR1 CLR TR0 SJMP $ IT0P: DJNZ R2,T0P4 ;定时器T0中断子程序:每定时一次(即100微秒),R2就减1 T0P4: RETI END 硬件实验六 串行数转并行数 //利用P1口及74LS1实现拨盘开关对LED灯的控制 #include int x,i,j,k; //变量声明 void delay(x); //延时函数声明 void main() //主程序 { P1=0xFF; //设置P1口为输入端口 SCON=0x00; //寄存器设置:TI清0 IE=0xB0; //开串行口中断,总中断 SBUF=0X00; //开始时灯全暗1S delay(3); while(1) //将P1口的状态读入串行口 {SBUF=P1; delay(1);}; //延时0.3S } com() interrupt 4 //串行口中断处理子程序 {TI=0; } void delay(x) //延时0.3*X秒函数 {do{for(i=0;i<1;i++) for(j=0;j<100;j++) for(k=0;k<200;k++); } while(--x); } 硬件实验七 并行数转串行数 //并行数据转串行数据 #include int PI; //中断标志位的变量声明 void main() { IE=0xB0; //串行口初始化 SCON=0x10; REN=1; //开读允许 PI=0; //标志位清0 while(1) {while(PI==0); //中断前一直执行 P1=SBUF; //中断处理,SBUF的值赋给P1 REN=0; //关读允许 PI=0;} //标志位清0 } com() interrupt 4 //中断服务子程序 {RI=0; PI=0; } 硬件实验八 单片机串行口通信实验 1.基本部分:双机通讯,一侧的拨盘控制另一侧的LED灯 //发送 #include void main() {SCON=0X40; //串行口初始化 TMOD=0X20; //计数器初始化 TH1=0XCE; TL1=0XCE; P1=0XFF; //P1置1,作为输入口 ES=1; TR1=1; EA=1; while(1) SBUF=P1; //开始传送数据 } com () interrupt 4 {TI=0; //中断处理,TI清0 } //接收 #include void main() {SCON=0X40; //串行口初始化 TMOD=0X20; //计数器初始化 TH1=0XCE; TL1=0XCE; ES=1; TR1=1; EA=1; while(1) {REN=1; while(RI==0) ; //产生中断前,一直本地运行此句 } } com () interrupt 4 //中断处理子程序 {REN=0; //清0RI,REN RI=0; P1=SBUF; //接收到的数据由P1输出 } 2.扩展部分:自发自收,发送存在RAM中的数据,由单片机自己接收后在LED灯上显示出来 //自发自收 #include char *a,*b ; int i,j,k,x,m; char c[8]={0x55,0xaa,0x33,0xcc,0x0f,0xf0,0x66,0x99}; //数据存放 void aaa (); void delay(x); void main() {SCON=0X50; //串行口初始化 PCON=0X80; TMOD=0X20; //计数器初始化 TH1=0X0CE; TL1=0X0CE; TR1=1; ES=1; EA=1; P1=0x00; //P1清0 b=0x30; aaa(); //RAM存入数据 for(a=0X30;a<0X38;a++) { SBUF=*a ; //发送数据 delay(5); //延时1.5秒 P1=SBUF; //接收数据 } while(1); } com () interrupt 4 //中断处理,清0RI,TI {TI=0; RI=0; } void delay(x) //延时0.3*X秒函数 {do{for(i=0;i<1;i++) for(j=0;j<100;j++) for(k=0;k<200;k++); } while(--x); } void aaa () //将数据存入规定的RAM区 {for(m=0;m<8;m++) {*b=c[m]; b++;} } 硬件实验九 存储器扩展实验 //存储器扩展 #include void main() {char xdata *i; //声明外部存储器地址变量 char xdata *j; i=0x8020; //地址赋值 j=0X8100; while(i<0X8030) //将外部存储器8020~8030内的数据转存到 {*j=*i; //外部存储器8100~8110内 i++; j++; } while(1); } 硬件实验十 8255输入、输出实验 //8255输入、输出实验 #include unsigned char xdata i _at_ 0x8003; //声明地址分别为8003(初始化串行口)、8000(C口)、8001(B口) unsigned char xdata j _at_ 0x8000; unsigned char xdata k _at_ 0x8001; void main() { i=0x82; //串行口初试化,PB读入,PC输出 while(1) j=k; //PB读入的值赋给PC输出 } 硬件实验十三、十四 八段数码管显示 键盘扫描显示实验 #include unsigned char xdata keyin _at_ 0x8001; unsigned char xdata out_seg _at_ 0x8004; unsigned char xdata out_bit _at_ 0x8002; unsigned char x,y,key,i,j,k; unsigned char code number[24]={0xf8,0x80,0x90,0x66,0x66,0x66, 0x99,0x92,0x82,0x66,0x66,0x66, 0xf9,0xa4,0xb0,0x66,0x66,0x66, 0xc0,0x66,0x66,0x66,0x66,0x66}; void main() {x=0; y=0; while(y==0) { while(x==0) {led(); //无键闭合,调用显示子程序,延时6MS ks1(); //调用判断键盘有无键闭合子程序 } led(); //可能有键闭合,延时12MS,软件去抖动 led(); // ks1(); //调用判断键盘有无键闭合子程序 } key_number(); //经去抖动后,判定键确实闭合,调用键号判断子程序 ks1(); //调用显示子程序,显示相应键值 } ks1() //判断键盘有无键闭合子程序 {out_bit=0; x=~keyin; y=x; } led () //显示子程序 {out_bit=0x1f; //选中第一个LED显示器 for(j=0;j<5;j++) {out_seg=0xff; //前5个LED显示器不输出数据 delay(); //延时1MS out_bit=out_bit>>1; //列数右移 } out_bit=out_bit>>1; out_seg=number[key]; //第6个LED显示器输出按下键的数值,0~9输出相应值,其他键则输出”三“ delay(); } key_number() //键号判断子程序 {out_bit=0x1f; for(i=0;i<6;i++) { switch (keyin) { case 7 : key=0+i+1; break; case 11 : key=6+i+1; break; case 13 : key=12+i+1; break; case 14 : key=18+i+1; break; default : break; } out_bit=out_bit>>1; } } delay() //延时0.3*X秒函数 { for(k=0;k<250;k++); }