8051单片机实验:实现电子计数器与数码管显示

在这篇文章中,我将分享一个基于8051单片机的电子计数器实验,涵盖数码管显示、按键扫描与防抖处理,以及软件延时等核心技术。实验目标是通过数码管显示计数器的值,并通过按键实现加减控制。以下是实验的详细过程、设计思路、代码实现、遇到的问题及解决方法,以及我的心得体会。


一、实验背景与目标

实验目的

  1. 掌握数码管显示方法:学会如何通过8051单片机控制八段数码管显示数字。

  2. 掌握软件延时方法:通过延时程序实现数码管的动态显示和按键防抖。

  3. 掌握键盘扫描及去抖动方法:实现按键的可靠检测,确保计数器的加减功能稳定运行。

实验内容

  • 在单片机开发板上实现一个电子计数器,使用CL3641AH数码管显示当前计数。

  • 通过按键K1和K2控制计数器加减,支持长按连续加减。

  • 使用三个数码管(LED1、LED2、LED3)分别显示计数的个位、十位和百位。

  • 参考电路图,实现数码管的片选、点亮以及按键的轮询检测。


二、实验设计与实现

1. 整体思路

实验的核心是利用8051单片机控制八段数码管的显示,并通过按键输入实现计数器的加减功能。具体步骤如下:

  • 将0到9的八段数码管编码存储在一个连续的表格中,通过查表方式获取对应数字的编码。

  • 使用寄存器R1、R2、R3分别存储个位、十位、百位的计数值,通过偏移量从表格中获取编码并输出到数码管。

  • 通过P3口检测按键输入,结合软件延时实现防抖,确保输入信号稳定。

  • 利用动态扫描和延时技术,使三个数码管“同时”显示计数器的个位、十位和百位。

2. 流程图

以下是实验的主要模块流程:

  1. 数据存储模块:初始化数码管编码表,存储0-9的段码。

  2. 数据计算模块:根据按键输入(K1加,K2减),更新寄存器中的计数值,处理进位/借位。

  3. 显示模块:通过查表获取段码,动态点亮数码管。

  4. 按键检测与防抖模块:轮询检测按键状态,调用延时程序消除抖动。

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单片机的编程与硬件控制,收获颇丰:

  1. 编程能力提升:熟悉了汇编语言的指令集和程序结构,学会了如何通过查表和偏移量控制数码管显示。

  2. 硬件调试经验:掌握了硬件连接的检查方法,理解了数码管和按键的电路原理。

  3. 问题解决能力:通过反复试验和查阅资料,解决了编程逻辑、硬件连接和防抖等问题,增强了调试能力。

  4. 系统优化意识:学会了通过延时和动态扫描优化程序性能,提高系统的稳定性和响应速度。


六、总结

本次实验让我从理论走向实践,深刻体会到单片机编程与硬件结合的魅力。尽管过程中遇到了一些挑战,但通过查阅资料、反复调试和优化,我成功实现了电子计数器的功能。这个过程不仅加深了我对8051单片机的理解,也让我对嵌入式系统的开发有了更大的兴趣。

如果你对单片机编程或数码管显示有兴趣,欢迎留言讨论!也希望这篇博文能为你的学习提供参考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值