在这篇文章中,我将分享一个基于8051单片机的电子计数器实验,涵盖数码管显示、按键扫描与防抖处理,以及软件延时等核心技术。实验目标是通过数码管显示计数器的值,并通过按键实现加减控制。以下是实验的详细过程、设计思路、代码实现、遇到的问题及解决方法,以及我的心得体会。
一、实验背景与目标
实验目的
-
掌握数码管显示方法:学会如何通过8051单片机控制八段数码管显示数字。
-
掌握软件延时方法:通过延时程序实现数码管的动态显示和按键防抖。
-
掌握键盘扫描及去抖动方法:实现按键的可靠检测,确保计数器的加减功能稳定运行。
实验内容
-
在单片机开发板上实现一个电子计数器,使用CL3641AH数码管显示当前计数。
-
通过按键K1和K2控制计数器加减,支持长按连续加减。
-
使用三个数码管(LED1、LED2、LED3)分别显示计数的个位、十位和百位。
-
参考电路图,实现数码管的片选、点亮以及按键的轮询检测。
二、实验设计与实现
1. 整体思路
实验的核心是利用8051单片机控制八段数码管的显示,并通过按键输入实现计数器的加减功能。具体步骤如下:
-
将0到9的八段数码管编码存储在一个连续的表格中,通过查表方式获取对应数字的编码。
-
使用寄存器R1、R2、R3分别存储个位、十位、百位的计数值,通过偏移量从表格中获取编码并输出到数码管。
-
通过P3口检测按键输入,结合软件延时实现防抖,确保输入信号稳定。
-
利用动态扫描和延时技术,使三个数码管“同时”显示计数器的个位、十位和百位。
2. 流程图
以下是实验的主要模块流程:
-
数据存储模块:初始化数码管编码表,存储0-9的段码。
-
数据计算模块:根据按键输入(K1加,K2减),更新寄存器中的计数值,处理进位/借位。
-
显示模块:通过查表获取段码,动态点亮数码管。
-
按键检测与防抖模块:轮询检测按键状态,调用延时程序消除抖动。
3. 主要模块设计与代码分析
(1)数据存储模块
设计思路:将0到9的八段数码管编码值存储在TABLE表格中,方便后续查表寻址。数码管的段码对应关系如下:
-
0: 3FH, 1: 06H, 2: 5BH, 3: 4FH, 4: 66H, 5: 6DH, 6: 7DH, 7: 07H, 8: 7FH, 9: 6FH
代码实现:
assembly
TABLE: DB 3FH, 06H, 5BH, 4FH, 66H
DB 6DH, 7DH, 07H, 7FH, 6FH
(2)按键检测与防抖模块
设计思路:
-
初始化P3口为高电平(0FFH),检测按键输入。
-
第一次检测到按键按下后,调用10ms延时程序进行防抖。
-
第二次检测确认按键状态,若有效(P3对应位为1),根据按键(K1或K2)跳转到加或减的计算程序。
代码实现:
assembly
KEY1:
MOV P3, #0FFH ; P3口全写入1
MOV A, P3
CPL A ; 取反,检测低电平
JZ KEY1 ; 无输入则继续检测
LCALL D10MS ; 延时10ms防抖
MOV A, P3
CPL A
JZ KEY1 ; 再次检测,无输入则返回
JB ACC.1, PK1 ; 检测K1(加)
JB ACC.0, PK2 ; 检测K2(减)
LJMP DISPLAY ; 返回显示模块
(3)数据计算模块
设计思路:
-
使用R1、R2、R3分别存储个位、十位、百位的计数值。
-
按键K1(加)时,R1加1,若进位则清零并递增R2,R2进位则清零并递增R3。
-
按键K2(减)时,R1减1,若借位则置9并递减R2,R2借位则置9并递减R3。
-
每次计算后跳转到显示模块,更新数码管显示。
代码实现:
assembly
PK1: ; 减计数
MOV A, R1
SUBB A, #01H
MOV R1, A
JNC DISPLAY ; 无借位则显示
CLR C
MOV R1, #09H ; 借位后个位置9
MOV A, R2
SUBB A, #01H
MOV R2, A
JNC DISPLAY
CLR C
MOV R2, #09H ; 十位借位置9
MOV A, R3
SUBB A, #01H
MOV R3, A
JNC DISPLAY
CLR C
MOV R3, #09H ; 百位借位置9
LJMP DISPLAY
PK2: ; 加计数
INC R1 ; 个位加1
CJNE R1, #0AH, DISPLAY ; 判断是否进位
MOV R1, #00H ; 进位清零
INC R2 ; 十位加1
CJNE R2, #0AH, DISPLAY
MOV R2, #00H
INC R3 ; 百位加1
CJNE R3, #0AH, DISPLAY
MOV R3, #00H
LJMP DISPLAY
(4)显示模块
设计思路:
-
根据R1、R2、R3中的计数值,通过查表(MOVC指令)获取对应的段码,输出到P0口。
-
通过P2口选择对应的数码管(高位: 08H,十位: 04H,个位: 00H)。
-
调用延时程序实现动态扫描,使三个数码管看起来“同时”显示。
代码实现:
assembly
DISPLAY:
; 高位显示
MOV A, R3
MOVC A, @A+DPTR
MOV P0, A
MOV A, #08H ; 选择高位数码管
MOV P2, A
LCALL DELAY_OUTPUT
; 十位显示
MOV A, R2
MOVC A, @A+DPTR
MOV P0, A
MOV A, #04H ; 选择十位数码管
MOV P2, A
LCALL DELAY_OUTPUT
; 个位显示
MOV A, R1
MOVC A, @A+DPTR
MOV P0, A
MOV A, #00H ; 选择个位数码管
MOV P2, A
LCALL DELAY_OUTPUT
(5)延时模块
设计思路:
-
提供两个延时子程序:DELAY_OUTPUT用于数码管动态显示的短延时,D10MS用于按键防抖的10ms延时。
-
通过嵌套循环实现精确延时。
代码实现:
assembly
DELAY_OUTPUT:
MOV R7, #10
D20:
MOV R6, #10
DJNZ R6, $
DJNZ R7, D20
RET
D10MS:
MOV R7, #250
D10:
MOV R6, #200
DJNZ R6, $
DJNZ R7, D10
RET
4. 完整代码
以下是实验的完整汇编代码:
assembly
ORG 0000H
LJMP MAIN
ORG 0100H
MAIN:
MOV R1, #00H ; 个位
MOV R2, #00H ; 十位
MOV R3, #00H ; 百位
MOV R0, #00H ; 控制输入选择位
MOV DPTR, #TABLE
LJMP DISPLAY
; 显示模块
DISPLAY:
; 高位显示
MOV A, R3
MOVC A, @A+DPTR
MOV P0, A
MOV A, #08H
MOV P2, A
LCALL DELAY_OUTPUT
; 十位显示
MOV A, R2
MOVC A, @A+DPTR
MOV P0, A
MOV A, #04H
MOV P2, A
LCALL DELAY_OUTPUT
; 个位显示
MOV A, R1
MOVC A, @A+DPTR
MOV P0, A
MOV A, #00H
MOV P2, A
LCALL DELAY_OUTPUT
; 按键检测模块
KEY1:
MOV P3, #0FFH
MOV A, P3
CPL A
JZ DISPLAY
LCALL D10MS
MOV A, P3
CPL A
JZ DISPLAY
JB ACC.1, PK1
JB ACC.0, PK2
LJMP DISPLAY
PK1:
MOV A, R1
SUBB A, #01H
MOV R1, A
JNC DISPLAY
CLR C
MOV R1, #09H
MOV A, R2
SUBB A, #01H
MOV R2, A
JNC DISPLAY
CLR C
MOV R2, #09H
MOV A, R3
SUBB A, #01H
MOV R3, A
JNC DISPLAY
CLR C
MOV R3, #09H
LJMP DISPLAY
PK2:
INC R1
CJNE R1, #0AH, DISPLAY
MOV R1, #00H
INC R2
CJNE R2, #0AH, DISPLAY
MOV R2, #00H
INC R3
CJNE R3, #0AH, DISPLAY
MOV R3, #00H
LJMP DISPLAY
TABLE: DB 3FH, 06H, 5BH, 4FH, 66H
DB 6DH, 7DH, 07H, 7FH, 6FH
DELAY_OUTPUT:
MOV R7, #10
D20:
MOV R6, #10
DJNZ R6, $
DJNZ R7, D20
RET
D10MS:
MOV R7, #250
D10:
MOV R6, #200
DJNZ R6, $
DJNZ R7, D10
RET
END
三、实现效果
实验完成后,计数器能够通过按键K1和K2实现加减功能:
-
按下K1,计数器加1,数码管显示的数值递增(从000到999)。
-
按下K2,计数器减1,数码管显示的数值递减(从999到000)。
-
长按K1或K2可实现连续加减,数码管显示稳定,动态扫描效果良好。
-
按键防抖有效,避免了误触发,计数器运行稳定。
四、实验中遇到的问题与解决方法
1. 编程逻辑错误
问题:初始代码编写时,数码管显示不正确,主要是因为对汇编语言指令(如MOVC、CJNE)的使用不熟悉,导致查表或进位逻辑错误。
解决方法:通过查阅8051指令集手册和反复调试,理清查表和进位逻辑,最终确保程序正确运行。
2. 硬件连接问题
问题:数码管显示不稳定,部分段码闪烁或不亮,可能是硬件连接松动或电路设计问题。
解决方法:仔细检查开发板的硬件连接,重新焊接松动的引脚,并确保数码管的片选信号正确输出。
3. 按键防抖处理不当
问题:按键响应不准确,多次触发或无响应,影响计数器的稳定性。
解决方法:优化防抖逻辑,采用10ms延时检测两次按键状态,并结合显示模块的调用,最终实现稳定的按键响应。
五、实验心得体会
通过本次实验,我深入理解了8051单片机的编程与硬件控制,收获颇丰:
-
编程能力提升:熟悉了汇编语言的指令集和程序结构,学会了如何通过查表和偏移量控制数码管显示。
-
硬件调试经验:掌握了硬件连接的检查方法,理解了数码管和按键的电路原理。
-
问题解决能力:通过反复试验和查阅资料,解决了编程逻辑、硬件连接和防抖等问题,增强了调试能力。
-
系统优化意识:学会了通过延时和动态扫描优化程序性能,提高系统的稳定性和响应速度。
六、总结
本次实验让我从理论走向实践,深刻体会到单片机编程与硬件结合的魅力。尽管过程中遇到了一些挑战,但通过查阅资料、反复调试和优化,我成功实现了电子计数器的功能。这个过程不仅加深了我对8051单片机的理解,也让我对嵌入式系统的开发有了更大的兴趣。
如果你对单片机编程或数码管显示有兴趣,欢迎留言讨论!也希望这篇博文能为你的学习提供参考。