大连理工大学软件学院 《单片机原理与应用》实验报告
姓 名: 韩广义 学号: 201193046 班级: 软1106 姓 名: 于世友 学号: 201192080 班级: 软 1103
组 号: 25
实验箱编号: 25
实验时间: 2013年5月28日实验室: 嵌入式实验室 实验台: _ 指导教师: 侯刚老师 成绩:
实验5:秒表定时器实验
一、实验目的和要求 实验目的:
1. 学习单片机的基本接口技术。
2. 学习74HC595、74HC138使用及与51单片机的控制方法。 实验要求:
用汇编语言设计程序,完成8个数码管的显示控制。
检查内容:当按下INT 按钮时,数码管开始快速计时,高五位为 秒数,低三位为ms 数,每1ms 刷新一次显示内容。当再次按下 INT 按钮时,停止计数。 二、实验原理和内容
:按键电路
我们在参考实验4的基础上,理解按键按钮的电路实现功能,使用了138和595两块电路,实现了实验要求功能。 原理内容见编程中的注释。 三、主要仪器设备及软件编程环境
Keil uVision2编译器、51单片机 四、实验步骤与编程
NumbList:
;; 0
1
2
3
4
5
6
7
8
9
ORG 00H LJMP START ORG 0BH
;定时器0的中断服务程序入口
LJMP T0_INT_SRV
ORG 013H ;外部中断1的中断服务程序入口 LJMP EX1_INT_SRV ORG 30H
DB 3fH, 6H, 5bH, 4fH, 66H, 6dH, 7dH, 7H, 7fH, 6fH
;; AFH 0EH DBH CFH E6H EDH FDH FH FFH EFH 带有小数
点的数码表示
MsecAddr EQU 70h ;毫秒的存放地址70H~72H 每个字节用于保存1位 SecAddr 表NumList
DispNomAddr EQU 78h ;78H~7FH中放置的是每个LED值对应的打印值 START:
;;初始化LED,默认为0 的话,此段可以省略,
MOV A,#0h
;A中数值为数码0
EQU 73h ;秒数的存放地址73h~77H 每个字节用于保存1位,保存的是实际值,显示的时候查
MOV R2,#8 ;一共8位 MOV R0,#MsecAddr MOV R1,#DispNomAddr
INILOOP:
MOV @R0,A MOV @R1,A INC R0 INC R1
DJNZ R2,INILOOP
;初始化8个LED
;;****************************************************** ;;开启中断
;;*******************************************************
SETB EA ;开启所有的中断 SETB EX1 ;允许外部中断1 SETB IT1 ;外部中断1跳变触发 SETB PX1 ;提高外部中断优先级
CLR PT0 ;降低定时器0的优先级 CLR TR0 ;关闭定时器0
MOV TMOD,#0001B ;T0设定为16位计数器(定时方式)
;;显示8LED的内容,无限循环显示 ;;无限循环 REFRESH:
;; 从DispNursAddr读值 在LED上显示 MOV P0,#0 MOV R6,#8h
MOV R1,#0;用于屏蔽高位不用的LED MOV R0,#DispNomAddr+7
NomShfting: ;移动到下一个要显示的数
CJNE R1,#0,BitShfting;不等则转移 DEC R0 INC P0
DJNZ R6,NomShfting
MOV R1,#1 CJNE A,#3fH,PING; MOV R7,#8h CLR A MOV A,@R0
;把要显示的数放到累加器A中
PING:
BitShfting:
DEC R0
;移动到下一个要显示的值
RLC A MOV P0.5,C
;把移出位放到SER引脚
;; 在SRCLK上制造一个正跳变,接收SER的值 CLR P0.4 SETB P0.4
DJNZ R7,BitShfting
;; 在RCLK上制造一个正跳变,接收整个8位值
CLR P0.3 SETB P0.3
LCALL DispDelay ;延迟
INC P0 ;(P0.0~P0.2) 对应LED移动
DJNZ R6,NomShfting LJMP REFRESH
;;******************************************************************* T0_INT_SRV:;;T0的中断服务程序
;; 用64h ~ 69h保存中断服务程序中用到得寄存器的值 MOV 69h,R0 MOV 68h,R1 MOV 67h,A MOV 66h,DPH MOV 65h,DPL MOV 64h,R7
;; 第1步,先累加1ms的值到保存计数值的位置
;push DPTR ;push R7
;push R0 ;push R1 ;push A
NOMINC: MOV R0,#MsecAddr
MOV R7,#8
;一共有8个数要判断
INCLOOP: ;有进位的话,高位也累加
INC @R0 ;对当前位进行加1
CJNE @R0,#10,INCFINISH ;如果当前位没有进位则循环结束
MOV @R0,#0 ;如果当前位有进位则当前位清零,并对下一位进行判断 INC R0 ;指针移动到下一位的位置 DJNZ R7,INCLOOP
INCFINISH:
;; 第2步,更新显示列表里面的数值
UpdateDispNom:
MOV R7,#8
MOV R0,#MsecAddr MOV R1,#DispNomAddr MOV DPTR,#NumbList
UpdateDispLoop:
MOV A,@R0
;把实际值放到A中
MOVC A,@A+DPTR ;用实际值取列表中的显示值 MOV @R1,A INC R0
;把A中显示值放到LED要显示的对应字节中去
;移动实际值指针
INC R1 ;移动显示值指针
DJNZ R7,UpdateDispLoop;一共有8个LED值要更新
PutPointer: ;子第三个数和第四个数之间加一个小数点
MOV R0,69h MOV R1,68h MOV A,67h MOV DPH,66h MOV DPL,65h MOV R7,64h RETI
;pop DPTR ;pop R7
;pop R0 ;pop R1 ;pop A
;; 第3步,重置定时器0 MOV TH0,#0FCH
MOV TL0,#017H ;重置定时器的值 SETB TR0 ;开启定时器 ;; 还原用到的寄存器的值 MOV R0,#DispNomAddr+3 MOV A,@R0
;
ORL A,#10000000b ;用或操作对对应位赋值1 MOV @R0,A
;更新
;;**************************************************************** EX1_INT_SRV:;外部中断1的服务程序 ;;设置T0,计时1ms
MOV 69h,R0 MOV R0,#03fH
;push R0
INT_DELAY:
JB P3.3, SRV_END MOV TH0,#0FCH
MOV TL0,#017H ;(65535-1000=0xFC17)定义为1ms CPL ET0 ;开启/关闭定时器中断0 SETB TR0
;启动定时器0
DJNZ R0,INT_DELAY ;按键去抖动
SRV_END:
MOV R0,69h
;pop R0
RETI ;中断服务程序返回 ;;相应中断后,硬件将IE1置零0
;;***************************************************************** ;;LED显示切换 DispDelay:
MOV R4,#05H
MOV R5,#0ffH DJNZ R5,LOOP2
LOOP1: LOOP2: END
DJNZ R4,LOOP1
RET
五、实验数据与结果分析
数据结果与实验要求完全符合。当第一次按下INT键时,开始秒表计时;再按下,停止计时;再按下,从停止的地方继续计时。根据定时器原理进行理论数据计算的寄存器值为FC17,实验结果与真实情况有较大误差,可能是由于程序执行和指令调用花费了一部分时间。经过测试和调整,我们选择了FC90作为定时数据,基本误差可控在5%以内。
六、讨论、建议
希望老师能让我们借用试验箱来进行代码的测试。