1、 实验一 功能:使连接在MCS-51单片机P1.0引脚的LED闪烁。 设计思路: 开始 让P1端口初值为11111111B P1.0求反 软件延时 图2.1 实验一程序流程图 ① 点亮LED需要约10 mA电流,此时LED两端电压差约2 V。因此,将LED的阴极通过一个电阻连接到P1.0引脚(电阻阻值约为200 W),阳极连接到电源VCC(5 V)。 ② 为便于观察,交替的时间间隔不应太小(建议选择在0.5 s左右),由于该时间不要求严格精确,所以,可采用软件延时的方法实现。 ③ 程序可采用图2.1中的流程结构。 ORG 0000H AJMP START O
2、RG 0030H START: MOV P1,#0FFH LOOP: CPL P1.0 ACALL DELAY AJMP LOOP DELAY: MOV R0,#99 DL2: MOV R1,#99 DL1: NOP NOP DJNZ R1,DL1 DJNZ R0,DL2 RET END 实验二 设计并调试一个双字节无符号数乘法子程序。 功能:双字节无符号数乘法子程序。 入口参数: 被乘数放在R7(高)和R6(低); 乘数放在R5(高)和R4(低); 积(片内RAM中的连续4字节)的首地址放在R0中。 设计思路: 图2.1 双字节无符号乘法
3、示意图 积 R6 ´ R4 B A R5 R4 R6 ´ R5 R7 ´ R5 R7 ´ R4 + ´ 低字节 高字节 R7 R6 B A B A B A M1 M0 M3 M2 由于MCS-51指令集中只有单字节无符号数乘法指令,因此需要将双字节无符号数相乘变换成4次单字节无符号数相乘,才能利用乘法指令实现双字节无符号数乘法计算。变换方法如图2.1所示。 MCS-51指令集中乘法指令的结果是固定存放在A和B中的,因此每次乘法操作后都须将结果保存在积中。所以应首先将积的初值置0且在每次乘法指令结束后需要进行2次加操作,分别将A和B加到积的对
4、应位置(注意:在两次加法之间要考虑进位)。 ORG 0000H AJMP START ADR EQU 20H ORG 0030H START: MOV R0,#ADR MOV R4,#14H MOV R5,#05H MOV R6,#35H MOV R7,#21H ACALL DW_MUL AJMP $ DW_MUL: MOV R1,#04H CLE: MOV @R0,#00H INC R0 DJNZ R1,CLE MOV R0,#ADR MU: MOV A,R4 MOV B,R6 MUL AB MOV @R0
5、A MOV A,B INC R0 ADDC A,@R0 MOV @R0,A MOV A,R4 MOV B,R7 MUL AB ADDC A,@R0 MOV @R0,A MOV A,B INC R0 ADDC A,@R0 MOV @R0,A MOV A,R5 MOV B,R6 MUL AB DEC R0 ADDC A,@R0 MOV @R0,A MOV A,B INC R0 ADDC A,@R0 MOV @R0,A MOV A,R5 MOV B,R7 MUL AB ADDC A,@R0
6、 MOV @R0,A MOV A,B INC R0 ADDC A,@R0 MOV @R0,A RET END 实验三:设计并调试一个将双字节无符号二进制数转换为压缩BCD数的子程序。 功能:双字节无符号二进制数转换为压缩BCD数子程序 入口参数: 双字节无符号二进制数的地址放在R0中; 存放转换结果(BCD数)的地址放在R1中。 设计思路: ① 双字节无符号二进制数最大值为0FFFFH,对应的十进制数为65535,其压缩BCD编码表示为06H,55H,35H,所以转换结果应用3个字节存放。 ② Y=(D15D14…D1D0) 2 = (((…(((0´
7、2)+D15)´2+D14) ´2+…) ´2+D1) ´2+D0) 2。 Y0=(0´2)+D15,Y1= Y0+D14,Y2= Y1+D13,…,Y15= Y14+D0,Y= Y15。 Y0|BCD =( (0´2)+D15)|BCD,Y1|BCD =( Y0+D14)|BCD,…, Y15 |BCD = ( Y14+D0)|BCD Y |BCD =Y15|BCD 算法: 1、Y=0 2、Y=Y´2+Di (i =15,14,…,2,1,0) 3、对Y进行十进制调整 4、重复2、3步16次 ③ Y=Y´2+Di可用Y=Y+Y+C实现(Di首先放在C中),考虑到Y存放在3
8、个字节,应分别加3次,且要考虑每次加法产生的C。 ORG 0000H AJMP START ORG 0030H START:MOV SP,#60H MOV R1,#25H MOV R0,#20H MOV @R0,#43H INC R0 MOV @R0,#4AH ACALL DW_BCD AJMP $ DW_BCD:DEC R0 MOV A,R0 MOV R6,A MOV A,R1 MOV R7,A MOV R2,#3 CLEAR:CLR A MOV @R1,A INC R1 DJNZ R2,CLEAR MOV R
9、3,#16 CLR C YIWEI: MOV A,R6 MOV R0,A MOV A,@R0 RLC A MOV @R0,A INC R0 MOV A,@R0 RLC A MOV @R0,A MOV R2,#3 MOV A,R7 MOV R1,A FANG: MOV A,@R1 ADDC A,@R1 DA A MOV @R1,A INC R1 DJNZ R2,FANG DJNZ R3,YIWEI RET END MOV R1,#25H MOV R0,#20H
10、 MOV @R0,#0FFH INC R0 MOV @R0,#0FFH ;20H 21H=FFH mov @r1,#0efh ACALL DW_BCD AJMP $ DW_BCD: DEC R0 MOV A,R0 MOV R6,A MOV A,R1 MOV R7,A ;R7=25h R6=20H MOV R2,#3 CLEAR: CLR A MOV @R1,A INC R1 DJNZ R2,CLEAR;25H 26H 27H==00 MOV R3,#16 CLR C
11、 YIWEI: MOV A,R6 MOV R0,A MOV A,@R0 RLC A MOV @R0,A INC R0 MOV A,@R0 RLC A MOV @R0,A MOV A,R7 MOV R1,A MOV R2,#3 FANG: MOV A,@R1 ADDC A,@R1 DA A;16进制到10 进制的转化 MOV @R1,A INC R1 DJNZ R2,FANG DJNZ R3,YIWEI RET END 实验四:利用外部中断
12、输入引脚(中断方式)控制步进电机的转动。 要求:每产生1次中断,步进电机只能步进1步。 使用INT0的中断服务程序控制步进电机正向步进;使用INT1中断服务程序控制步进电机反向步进。 设计思路: ① 主程序在完成对INT0和INT1的设置后,可进入死循环(等待中断请求)。 ② 为便于实验观察和操作,设INT0和INT1中断触发方式为边沿。 ③ 步进电机的转动控制由外部中断的服务程序来实现。 ④ 当前步进电机的相位通电状态信息可以使用片内RAM中的一个字节单元来存储。 ORG 0000H LJMP RESET ORG 0003H ;外部中断0 服务程序入口
13、 LJMP INT_EX0 ORG 000BH ;定时器/计数器0 溢出中断服务程序入口 RETI ORG 0013H ;外部中断1 服务程序入口 LJMP INT_EX1 ORG 001BH ;定时器/计数器1 溢出中断服务程序入口 RETI ORG 0023H ;串行口中断服务程序入口 RETI ORG 0040H ;复位处理程序 RESET: MOV SP, #67H SETB IT0 SETB IT1 SETB EX0 SETB EX1 MOV 30H,#11110111B
14、CLR A ;累加器A清零 SETB EA MAIN: SJMP MAIN INT_EX0: ;使用INT0的中断服务程序控制步进电机正向步进 PUSH ACC MOV A,30H RR A ;累加器A的内容向右循环移位一位 MOV 30H,A MOV P1,A POP ACC RETI INT_EX1: ;使用INT1中断服务程序控制步进电机反向步进 PUSH ACC MOV A,30H RL A ;累加器A的内容向左循环移位一位 MOV 30H,A MOV P1,A POP ACC
15、 RETI END 另一种实验方法: ORG 0000H ;复位入口 LJMP RESET ORG 0003H ;外部中断0 服务程序入口 LJMP INT_EX0 ORG 000BH ;定时器/计数器0 溢出中断服务程序入口 RETI ORG 0013H ;外部中断1 服务程序入口 LJMP INT_EX1 ORG 001BH ;定时器/计数器1 溢出中断服务程序入口 RETI ORG 0023H ;串行口中断服务程序入口 RETI ORG 040H ;复位处理程序 RESET: MOV SP,#
16、67H SETB IT0 SETB IT1 SETB EX0 SETB EX1 MOV 30H,#11110111B CLR A SETB EA MAIN: SJMP MAIN ;----------------------------------------使用INT0的中断服务程序控制步进电机正向步进 INT_EX0: MOV R0,#00H ;正转至TABLE取码指针初值 ABC: MOV A, R0 ;至TABLE取码 MOV DPTR, #TABLE ;存表
17、 MOVC A,@A+DPTR ;取表代码 JZ INT_EX0 ;是否取到结束码(00H)? MOV P0, A ; 输出至P0,正转 INC R0 ;取下一个码 JMP ABC ;转至Z_M处,循环 RETI ;----------------------------------------使用INT1中断服务程序控制步进电机反向步进 INT_EX1:
18、 MOV R0, #05 ;反转至TABLE取码指针初值 ABC1: MOV A, R0 ;至TABLE取码 MOV DPTR, #TABLE ;存表 MOVC A, @A+DPTR ;取表代码 JZ INT_EX1 ;是否取到结束码(00H)? MOV P0, A ; 输出至P0, 反转 INC R0 ;取下一个码 JMP
19、 ABC1 ; 转至F_M1处,循环 RETI ;反转子程序 TABLE: DB 0FCH, 0F9H, 0F3H, 0F6H ;正转 DB 00H ;正转结束码 DB 0F7H, 0F3H, 0FBH, 0F9H ; 反转 DB 0FDH, 0FCH, 0FEH, 0F6H DB 00H ;反转结束码
20、 END ;程序结束 实验五:利用定时/计数器测量电动机的转速。 使用T1作为定时器(定时时间为50毫秒),T0作为计数器(计数由电机测速电路产生的脉冲个数,每转4个脉冲),每1秒时间后,读出T0的值(读出后须将T0清0),将该值(速度值*4)显示到LCM显示器上(显示子程序/函数由实验库文件提供)。 本次实验程序需要使用实验库文件(LCMDRV_12864.LIB)。该库中的子程序/函数占用单片机片内RAM中地址为18H~20H的单元,因此实验程序不能使用这些单元。如果用汇编编写实验程序,必须先用$INCLUDE (
21、LCMDRV_12864.INC )指令加载实验库头文件 REFRESHDISP EQU 08H ;刷新显示标志 SPEED_CNTH EQU 30H ;速度脉冲计数高8位 SPEED_CNTL EQU 31H ;速度脉冲计数低8位 SECOND_CNT EQU 32H ;秒计数 VAR_END EQU 32H ;最后一个字节变量的位置, STACK_INI EQU VAR_END+1 ;须保证足够的空间实验程序架构(汇编): $INCLUDE(LCMDRV_12864.INC) ;包含库程序定义 ORG 0000H ;复位入口 LJM
22、P RESET ORG 0003H ;外部中断0 服务程序入口 RETI ORG 000BH ;定时器/计数器0 溢出中断服务程序入口 RETI ORG 0013H ;外部中断1 服务程序入口 RETI ORG 001BH ;定时器/计数器1 溢出中断服务程序入口 LJMP INT_T1 ORG 0023H ;串行口中断服务程序入口 RETI ORG 040H ;复位处理程序 RESET: MOV SP,#60H ;设置栈底指针 MOV R7,#00H ;初始化显示器(不
23、显示光标) LCALL _LCM_Init SETB ET1 ;此处添加设置中断许可和优先的指令(ET1, PT1) SETB PT1 MOV TMOD,#00010110B ;定时/计数设置 MOV TH1,#3CH ;此处添加设置定时/计数器的指令(TMOD, THx, TLx) MOV TL1,#0B0H MOV TH0,#0 MOV TL0,#0 CLR REFRESHDISP ;清刷新显示标志 MOV SECOND_CNT,#20 ;启动内部定时 SETB TR1 SETB TR0 ;此处添加启动定时/计数的指令
24、TRx) SETB EA ;开中断 MAIN: JNB REFRESHDISP,$ ;判断是否需要刷新显示 CLR REFRESHDISP ;清刷新显示标志 MOV R7,#01H ;从第2行第8列开始显示速度值(5位数值) MOV R5,#07H MOV R2,SPEED_CNTH MOV R3,SPEED_CNTL CALL _LCM_DispUIntXY SJMP MAIN ;内部定时中断服务程序 ************************** INT_T1: MOV TH1,#3CH ;此处添加重置定时常数的指令
25、MOV TL1,#0B0H MOV A,R7 ;此处添加保护现场内容的指令(如果有的话) PUSH ACC INC R7 CJNE R7,#20,LLEND ;判断一秒钟时间到的指令,没到时间则跳转恢复现场, MOV SPEED_CNTL, TL0 ;记录速度检测计数(供主程序显示用) MOV SPEED_CNTH, TH0 MOV TL0, #00 ;速度检测计数归零 MOV TH0, #00 SETB REFRESHDISP ;设置刷新显示标志 (控制主程序刷新显示) LLEND: POP ACC ;此处添加恢复现场内容的指令(如果有的
26、话) MOV R7,A RETI END 实验六:利用8155实现并行I/O扩展。 利用P1端口访问CAT24WC02(兼容AT24C02)。 程序一: 使用8155实现对并行接口的扩展。利用8155的PA口输入D1区KEY组各按键的状态信息,然后将该状态信息通过单片机的P1口输出到D1区LED组显示。 主程序在完成各项初始化设置后,可进入一死循环,在该循环里面不断的读取8155 PA口的信息并将其输出到单片机的P1口。 ORG 0000H AJMP MAIN ORG 0030H MAIN: MOV DPTR,#7F00H MOV A,#11
27、110000B MOVX @DPTR,A LOOP: MOV DPTR,#07F01H MOVX A,@DPTR MOV P1,A SJMP LOOP END 程序二:先将单片机内部RAM中30H~37H单元的值复制到CAT24WC02中的00H~07H单元。然后又将这8个数从CAT24WC02中复制到单片机内部RAM的40H~47H单元中 ① CAT24WC02的器件地址:0A0H ② CAT24WC02芯片手册CAT24WCxxx.pdf 实验七:利用ADC0809/DAC0832实现模拟电压信号的采集与输出。 使用T1作为定时器(定时时间为
28、50毫秒),每1秒时间后,启动ADC0809转换,在转换结束后(触发外部中断)读出A/D转换值,将该值输出到DAC0832,并同时显示到LCM显示器上(显示子程序/函数由实验库文件提供)。 本次实验程序需要使用实验库文件(LCMDRV_12864.LIB)。该库中的子程序/函数占用单片机片内RAM中地址为18H~20H的单元,因此实验程序不能使用这些单元。如果用汇编编写实验程序,必须先用$INCLUDE (LCMDRV_12864.INC )指令加载实验库头文件 设计思路: ① 主程序在完成对INT1和T1的设置后,可进入死循环(等待中断请求)。 ② 在T1的中断服务程序中需要使用一存
29、储单元对T1的中断次数进行计数,当计数次数达20次时,意味着定时1秒时间到(参见实验五),此时才启动一次AD转换(通过向ADC0809的一次写操作实现)。 ③ AD转换的结束信号作为中断请求(INT1)。在对该中断的响应和服务时,才读出本次AD转换的结果值,该值又作为DA转换的值(向DAC0832写)。 ④ 为便于理解,数值在显示前应进行BCD转换(库文件自动完成转换)。 $INCLUDE(LCMDRV_12864.INC) ;包含库程序定义 REFRESHDISP EQU 08H ;刷新显示标志 AD_VAL EQU 30H ;AD转换结果值 SECOND_CNT
30、EQU 31H ;秒计数 VAR_END EQU 31H ;最后一个字节变量的位置, STACK_INI EQU VAR_END+1 ;须保证足够的空间 ORG 0000H ;复位入口 LJMP RESET ORG 0003H ;外部中断0 服务程序入口 RETI ORG 000BH ;定时器/计数器0 溢出中断服务程序入口 RETI ORG 0013H ;外部中断1 服务程序入口 LJMP INT_INT1 ORG 001BH ;定时器/计数器1 溢出中断服务程序入口 LJMP INT_T1 ORG
31、 0023H ;串行口中断服务程序入口 RETI ORG 0040H ;复位处理程序 RESET: MOV SP,#STACK_INI ;设置栈底指针 MOV R7,#00H ;初始化显示器(不显示光标) LCALL _LCM_Init SETB IT1 ;脉冲触发方式 SETB ET1 SETB EX1 SETB PT1 ;定时/计数器高级中断 CLR PX1 MOV TMOD,#00010000B MOV TH1,#3CH MOV TL1,#0B0H ;设置定时/计数器的指令(TMO
32、D, TH1, TL1) MOV R6,#0 CLR REFRESHDISP ;清刷新显示标志 MOV SECOND_CNT,#20 SETB TR1 SETB EA MAIN: JNB REFRESHDISP,$ ;判断是否需要刷新显示 CLR REFRESHDISP ;清刷新显示标志 MOV R7,#01H ;从第2行第8列开始显示转换值(5位数值) MOV R5,#07H MOV R2,#00H ;转换值扩展成16位 MOV R3,AD_VAL CALL _LCM_DispUIntXY SJMP MAI
33、N INT_INT1: PUSH ACC MOV DPTR,#3C00H ;此处添加读A/D转换结果的指令 MOVX A,@DPTR MOV AD_VAL,A ;保存转换结果(供主程序显示用) MOV DPTR,#3800H MOVX @DPTR,A ;此处添加启动D/A转换的指令 SETB REFRESHDISP ;设置刷新显示标志 (刷新显示由主程序完成) POP ACC RETI INT_T1: MOV TH1,#3CH MOV TL1,#0B0H ;此处添加重置定时常数的指令 INC R6 CJNE R6,#20,LL1 ;判断一秒钟时间到的指令, 没到恢复现场, MOV R6,#0 MOV DPTR,#3C00H MOVX @DPTR,A ;此处添加启动A/D转换的指令 LL1: RETI END






