1、单片机实验报告山东大学 第三单元Proteus 系统仿真实验实验一 基本并行口I/O口实验 自我完成实验1、实验要求当按键 SW1 按下之后,D1-D8 轮流点亮,点亮时间为 100ms,当按键停下后,停止轮换,再次按下后继续轮换。2、编程思路进行初始化工作,包括设置堆栈指针 SP,将 P2 口所有位设置为 1,使 P2 口所接发光二极管全部熄灭。将显示缓冲单元(设为 20H 单元)初始化为 FEH。 从 P1 口读数据,查看 P1.0 位,如果 P1.0 位为 0,则执行如下循环:将显示缓冲单元的值送给 P2 口,调用 100ms 延时程序,将显示缓冲单元的值循环左移 1 位,再送回显示缓冲
2、单元。如果 P1.0 位不为 0 则不执行上述循环。重复上面的操作3、实验步骤 根据上述实验内容,参考 1.2.2,在 Proteus 环境下建立图 3.5 所示原理图,并将其保 存为 basicIO_self.DSN 文件。 根据(2)和(3)编写控制源程序,将其保存为 basicIO_self.asm。 将源程序添加到 U1 中,并构造(build)该程序。 执行仿真过程观察 D1-D8 的指示,查看程序功能是否正确。 修改延时程序延时参数,重新执行和。4、源程序 ORG 0000H AJMP MAIN ORG 0030HMAIN: MOV SP,#60H MOV P2,#0FFH MOV
3、 A,#0FEH MOV 20H,A;缓冲单元LOOP: JNB P1.0,LOOP1; ;如果P1.0=0,跳转 SJMP LOOP ;否则循环不断检测 LOOP1: MOV P2,20H ;将缓冲单元内的值给P2口 LCALL DELAY100MS ;延时100ms; MOV A,20H RL A ;左移一位 MOV 20H,A JB P1.0,LOOP;如果P1.0=1,跳转到LOOP处 LJMP LOOP1;否则循环 DELAY100MS:MOV R7,#200 ;1us DL:MOV R6,#248 ;1us DJNZ R6,$ ;248*2=496us NOP ;1us DJNZ
4、R7,DL ;2us RET ;(496+1+1+2)*200+1=100.001ms END 5、电路图6、仿真结果当按键 SW1 按下之后,D1-D8 轮流点亮,点亮时间为 100ms,当按键停下后,停止轮换,再次按下后继续轮换。实验二 扩展并行I/O口实验 自我完成实验1、实验要求仿真实现交通信号灯控制功能。控制顺序为: 南北绿灯亮,同时东西红灯亮 10s; 南北黄灯亮,同时东西红灯亮 2s; 南北红灯亮,同时东西绿灯亮 10s; 东西黄灯亮,同时南北红灯亮 2s; 重复。2、编程思路进行初始化工作,包括设置堆栈指针 SP,将两个 373 的输出口所有位均设置为 1,使所有发光二极管全部
5、熄灭。分析两个 373 的地址:假定所有无关地址均定义为 1,那么 U4 的锁存地址为:#0FE00H,U5 的锁存地址为:#0FD00H。分析 4 个状态下两个 373 的输出数据值:假定“南北绿灯亮,同时东西红灯亮”为状态 1,即:Stat1;“南北黄灯亮,同时东西红灯亮”为状态 2,即:Stat2;“南北红灯亮,同时东西绿灯亮”为状态 3,即:Stat3;“东西黄灯亮,同时南北红灯亮”为状态 4,即:Stat4。3、实验步骤 根据上述实验内容,参考 1.2.2,在 Proteus 环境下建立图 3.7 所示原理图,并将其保存为 expandIO_self.DSN 文件。 根据(2)和(3
6、)编写控制源程序,将其保存为 expandIO_self.asm。 将源程序添加到 U1 中,并构造(build)该程序。 执行仿真过程观察各个方向的交通信号灯指示,查看程序功能是否正确。4、源程序 ORG 0000H AJMP MAIN ORG 0030HMAIN: MOV SP,#60H MOV A,#0FFH MOV DPTR,#0FE00H MOVX DPTR,A MOV DPTR,#0FD00H MOVX DPTR,ASTAT1: MOV A,#0F3H MOV DPTR,#0FE00H MOVX DPTR,A MOV A,#0CH MOV DPTR,#0FD00H MOVX DPT
7、R,A LCALL DELAY10SSTAT2: MOV A,#0C3H MOV DPTR,#0FE00H MOVX DPTR,A MOV A,#0FH MOV DPTR,#0FD00H MOVX DPTR,A LCALL DELAY2SSTAT3: MOV A,#0FCH MOV DPTR,#0FE00H MOVX DPTR,A MOV A,#03H MOV DPTR,#0FD00H MOVX DPTR,A LCALL DELAY10S STAT4: MOV A,#3CH MOV DPTR,#0FE00H MOVX DPTR,A MOV A,#0FH MOV DPTR,#0FD00H MOV
8、X DPTR,A LCALL DELAY2S LJMP STAT1DELAY2S:MOV R7,#20 DL2:MOV R6,#200 DL1:MOV R5,#250 DJNZ R5,$ DJNZ R6,DL1 DJNZ R7,DL2 RET DELAY10S:MOV R7,#100 DL3:MOV R6,#200 DL4:MOV R5,#250 DJNZ R5,$ DJNZ R6,DL4 DJNZ R7,DL3 RETEND 5、电路图6、实验结果 南北绿灯亮,同时东西红灯亮 10s; 南北黄灯亮,同时东西红灯亮 2s; 南北红灯亮,同时东西绿灯亮 10s; 东西黄灯亮,同时南北红灯亮 2s
9、;实验三 静态LED显示实验 自我完成实验1、实验要求图中 7SEG2 为十位显示数码管,7SEG1 为个位显示数码管,KEY_LOAD 为倒计时初值按钮,KEY_START 为倒计时启动按钮。要求实现的功能是:当 KEY_LOAD 按钮按下时加载倒计时初值(如:10s),当按下 KEY_START 按钮时,开始倒计时,每过 1s,计时器减 1,直到减到“00”为止。减到“00”时使 P3.0 引脚上的 LED 按 10Hz 频率进行闪烁,直到再次按下 KEY_LOAD 按钮才重新加载初值,并熄灭 LED。再次按下 KEY_START 按钮又一次开始倒计时,如此反复。2、编程思路分析两个 37
10、3 的地址:假定所有无关地址均定义为 1,那么 U2 的锁存地址为:#0FE00H,U3 的锁存地址为:#0FD00H。程序流程图:3、实验步骤 根据上述实验内容,参考 1.2.2,在 Proteus 环境下建立图 3.9 所示原理图,并将其保存为 staticLED_self.DSN 文件。 根据(2)和(3)编写控制源程序,将其保存为 staticLED_self.asm。 将源程序添加到 U1 中,并构造(build)该程序。 执行仿真过程观察秒表程序功能是否正确。4、源程序 ORG 0000H AJMP MAIN ORG 0030HMAIN: MOV SP,#60H;堆栈初始化 MOV
11、 R0,#0;各位 MOV R1,#1;十位 SETB P3.0;关掉LED1 CLR F0LOOP: JB P1.1,LOOP2;如果P1.1=1,跳转到LOOP2,LOOP1: CLR F0 MOV 30H,R0 MOV 31H,R1;装载初值 SETB P3.0;关闭LED1 LCALL DISPLAY;显示LOOP2: JB P1.0,LOOP;如果P1.0=1,跳回LOOP,否则继续执行LOOP3: LCALL DISPLAY;刷新显示 LCALL DELAY1S;延时1s LCALL ADJUST2;调整计时器寄存器 JB F0,LOOP4 LJMP LOOP3LOOP4: CLR
12、 P3.0 ;LED闪烁程序 LCALL DELAY100MS SETB P3.0 LCALL DELAY100MS JB P1.1,LOOP4 LJMP LOOP1 DISPLAY: ;显示子程序 MOV A,30H MOV DPTR,#TABLE MOVC A,A+DPTR MOV DPTR,#D1ADD MOVX DPTR,A MOV A,31H MOV DPTR,#TABLE MOVC A,A+DPTR MOV DPTR,#D10ADD MOVX DPTR,A RET ADJUST2: DEC 30H MOV A,30H CJNE A,#-1,GOTORET MOV 30H,#9 DE
13、C 31H MOV A,31H CJNE A,#-1,GOTORET SETB F0 RET GOTORET: RET DELAY1S:MOV R7,#10 DL2:MOV R6,#200 DL1:MOV R5,#250 DJNZ R5,$ DJNZ R6,DL1 DJNZ R7,DL2 RETDELAY100MS:MOV R7,#200 DL:MOV R6,#248 DJNZ R6,$ NOP DJNZ R7,DL RET TABLE: DB 0C0H,0f9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90HD1ADD EQU 0FE00H ;U3的锁存地址D10ADD
14、 EQU 0FD00HEND5、电路图6、仿真结果当 KEY_LOAD 按钮按下时加载倒计时初值(如:10s),当按下 KEY_START 按钮时,开始倒计时,每过 1s,计时器减 1,直到减到“00”为止。减到“00”时使 P3.0 引脚上的 LED 按 10Hz 频率进行闪烁,直到再次按下 KEY_LOAD 按钮才重新加载初值,并熄灭 LED。再次按下 KEY_START 按钮又一次开始倒计时,如此反复。实验四 矩阵键盘扫描实验 自我完成实验1、实验要求 D1D8 八个发光二极管构成彩色旋转灯,D9D13 为档位指示灯,一档旋转速度最慢(周期 1s,D13 亮),二档较快(周期 0.8s,
15、D12 亮),三档更快(周期 0.6s,D11 亮),四档再快(周期 0.4s,D10 亮),五档最快(周期 0.2s,D10 亮)。四个按键 KEY0-KEY1于设定旋转方向为顺时针旋转或者逆时针旋转,KEY2-KEY3 用于增快或则减慢旋转速度。2、编程思路按键扫描的方式可以采用前面示例程序中的方法:线反转法或行扫描法。可以用汇编语言实现,也可以用 C 语言实现。建议如前面示例所示,汇编采用行扫描法,C 语言用线反法。程序控制流程是:首先初始化设置默认运行参数,然后读取按键,识别键码,并根据键码的不同执行运行参数调整,最后根据当前的运行参数执行发光二极管 D1-D8 的轮流旋转。速度的控制
16、通过控制调用延时程序的次数来决定,假设延时程序的延时长度为 5ms。延时程序可以按如下方式实现(假设晶振频率为 12MHz):void delays()uchar t,ms;ms=5; /延时 5mswhile(ms-) for(t=0;t120;t+);或者采用内嵌汇编来实现:void delays()#pragma asmMOV R2,#50 /;5ms 延时程序DL1:MOV R1,#48DL2:DJNZ R1,DL2 / ;内循环 100usNOPDJNZ R2,DL1 /;中循环 10ms#pragma endasm旋转彩灯线反转法 C 语言程序控制流程图(1)主控流程图 (2)键盘
17、扫描子程序 Keyscan 流程图旋转彩灯行扫描法汇编控制流程图3、实验步骤 根据上述实验内容,参考 1.2.2,在 Proteus 环境下建立图 3.11 所示原理图,并将其保存为 keyscan_self.DSN 文件。 根据(2)和(3)编写控制源程序,将其保存为 keyscan_self.asm 或 keyscan_self.c。 将源程序添加到 U1 中,并构造(build)该程序。 执行仿真过程观察秒表程序功能是否正确。4、源程序#includereg52.h#includeintrins.h#define uchar unsigned char#define uint unsig
18、ned intsbit g0=P04;uchar code T_TABLE=200,160,120,80,40;/周期值表uchar code key_code=0x22,0x12,0x21,0x11;void delay()/延时5ms uchar t,ms; ms=5; while(ms-) for(t=0;t120;t+);void main() int aa=0xfe; uint dir=1; uint speed=0; int temp,temp2,keycode; int j,key; g0=0; while(1) P3=0x30; temp=P3; if(temp&0x30)!=
19、0x30)/按键检测 delay(); delay(); P3=0x30; temp=P3; if(temp&0x30)!=0x30) P3=0x03; temp2=P3; keycode=temp|temp2; for(j=0;j4;j+) if(keycode=key_codej) key=j; if(key=0) dir=1;/正转 if(key=1) dir=0;/反转 if(key=2) speed+; if(speed=5) speed=4;/换档 if(key=3) if(speed=0) speed+;/换档 speed-; switch (speed) case 0:P0=0
20、xef;break; case 1:P0=0xf7;break; case 2:P0=0xfb;break; case 3:P0=0xfd;break; case 4:P0=0xfe;break; default:break; P3=0x03; while(!(P3=0x03); if(dir=1)/正转时执行 P1=aa; for(j=0;jT_TABLEspeed;j+) delay(); aa=_crol_(aa,1);/左移 if(dir=0)/反转时执行 P1=aa; for(j=0;jT_TABLEspeed;j+) delay(); aa=_cror_(aa,1);/右移 5、电
21、路图:6、仿真结果: D1D8 八个发光二极管构成彩色旋转灯,D9D13 为档位指示灯,一档旋转速度最慢,二档较快,三档更快,四档再快,五档最快。四个按键 KEY0-KEY1于设定旋转方向为顺时针旋转或者逆时针旋转,KEY2-KEY3 用于增快或则减慢旋转速度。实验五 定时器计数器实验 自我完成实验1、实验要求用 NE555 构成的脉冲信号发生器,右边是用定时/计数器 0 和定时/计数器 1构成的频率计。为了检验频率计量是否准确,用 Proteus 的虚拟频率计来进行测量脉冲信号频率进行比对。7SEG1-7SEG6 用于频率计百分位、十分位、个位、十位、百位、千位的显示,单位为 Hz。要求单片
22、机上电运行后作为频率计将一直运行,改变脉冲发生器所产生的脉冲频率,则频率计的显示将跟随变化。2、编程思路定时/计数器 0 工作在定时器模式方式 1(16 位),定时/计数器 1 工作在计数器模式方式 2(8 位自动重装初值)。定时/计数器 1 计数 200 个脉冲后(每计数 200 个脉冲产生一次中断)统计这 200 个脉冲总的时间长度,计算出平均每个周期的时间长度。200 个脉冲所用时间长度的测量是靠定时/计数器 0 来实现的,定时/计数器 0 的初值为0。当定时/计数器 1 产生中断时,读出定时/计数器 0 当前计数器值,再加上在定时/计数器0 中断中累积的值即可得到。3、实验步骤 根据上
23、述实验内容,参考 1.2.2,在 Proteus 环境下建立图 3.11 所示原理图,并将其保存为 frequencycounter.DSN 文件。 根据(2)和(3)编写控制源程序,将其保存为 frequencycounter.c。 运行 Keil uVision2 开发环境,按照 1.1.3 节介绍的方法建立工程frequencycounter.uV2,CPU 为 AT89C51,包含启动文件 STARTUP.A51。 按照 1.2.2 第(6)节介绍的方法将 C 语言源程序 frequencycounter.c 加入工程frequencycounter.uV2,并设置工程 frequen
24、cycounter.uV2 属性,将其晶振频率设置为 12MHz,选择输出可执行文件,仿真方式为选择硬仿真,并选择其中的“PROTEUS VSMMONITOR 51 DRIVER”仿真器。 构造(Build)工程 frequencycounter.uV2。如果输入有误进行修改,直至构造正确,生成可执行程序 frequencycounter.hex 为止。 为 AT89C51 设置可执行程序 frequencycounter.hex。 运行程序,观察数码管的显示与虚拟频率计是否一致。 改变 RV2 的值,继续观察频率测量结果,观察数码管的显示与虚拟频率计是否一致。4、源程序#includereg
25、52.h#define uchar unsigned char#define uint unsigned intuchar code led_table=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90;uchar xdata da001 _at_ 0xfe00;uchar xdata da01 _at_ 0xfd00;uchar xdata da1 _at_ 0xfb00;uchar xdata da10 _at_ 0xf700;uchar xdata da100 _at_ 0xef00;uchar xdata da1k _at_ 0xdf0
26、0;uchar dv001,dv01,dv1,dv10,dv100,dv1k;long sumtime=0;/总时间float frequency,ptime;/分别为 频率, 单周期时间uint timer0H;uint timer0L;void s_timer0() interrupt 1 EA=0; sumtime=sumtime+65536; TH0=timer0H; TL0=timer0L; EA=1;void s_timer1() interrupt 3 EA=0; sumtime=sumtime+TH0*256+TL0; TH0=timer0H; TL0=timer0L; pti
27、me=(float)sumtime/200; sumtime=0; frequency=(float)1000000/ptime; dv1k=(uchar)(frequency/1000); frequency=frequency-dv1k*1000; dv100=(uchar)(frequency/100); frequency=frequency-dv100*100; dv10=(uchar)(frequency/10); frequency=frequency-dv10*10; dv1=(uchar)frequency; frequency=frequency-dv1; frequenc
28、y=frequency*10; dv01=(uchar)frequency; frequency=frequency-dv01; frequency=frequency*10; dv001=(uchar)frequency; da001=led_tabledv001; da01=led_tabledv01; da1=led_tabledv1; da10=led_tabledv10; da100=led_tabledv100; da1k=led_tabledv1k; EA=1; void main() TMOD=0X61;/T1计数器,方式2,T0定时器,方式1 timer0H=0;/T0定时器初值 timer0L=0; TH1=TL1=56;/T1计数器初值 256-200=56 EA=1;/开总中断 ET0=1;/开定时器0中断 TR0=1;/启动定时器0 ET1=1;/开启T1中断 TR1=1;/开启T1 while(1); 5、电路图6、仿真结果频率计显示的与脉冲发生器的频率基本一致。实
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1