硬件实验2:数码管显示实验

来源:互联网 发布:乐乎lofter福利 编辑:程序博客网 时间:2024/05/04 00:14

实验要求:

这里写图片描述

实验板:

这里写图片描述

我还是先介绍一下电路图吧,上面的电路图是我们学院做的板子的结构图,下面是我用proteus搭建的仿真工程:proteus仿真工程我已经上传了,传送门:仿真工程下载
电路图

里面用到的器件如下图所示:
器件

我用的是74LS138,功能和74HC138一样,但是驱动更强。在搭建电路的时候,也遇到了一些坑,因为是第一次自己用proteus搭建仿真环境,所以遇到麻烦也无所谓了。主要是P0口最开始没有接上拉电阻,导致74HC595无法输出,Q0~Q7一直是高阻态,我查了一下网上的资料,说是通常在开漏输出的口线上需要上拉电阻,而P0口恰好就是开漏输出的口线。但是这个电阻也不能过大,否则压降全部都降在了电阻上面,就没有足够的电压来驱动芯片了,所以我选了一个经典的电阻值470欧姆。

晶振是12MHz的,由于74LS138是38译码器,一次只能选中一个数码管,也就是说不能够一次性的显示多位,但是实验显然有一次性显示多位的需求,因此为了能够利用人的视觉残留和LED的残影来达到“假装”一次显示多位的目的,我每隔很短的时间来选中下一个数码管并且显示。这个很短的时间经过我不断地调试发现14ms还不错,虽然理论上20ms以内人类的眼睛就不会察觉出来,但是随着板子的使用也会有所差异,所以需要根据自己的情况适当进行调整。

实验代码:

    ORG 00H    LJMP    MAIN    ORG 0BH     ;定时器0的中断服务程序入口    LJMP    T0_INT    ORG 30HNUMBER:     ;;       1   2   3   4   5   6   7   8    DB   6H,     5bH,    4fH,    66H,    6dH,    7dH,    7H,     7fH    DB   6H,     5bH,    4fH,    66H,    6dH,    7dH,    7H,     7fHNUMADD      EQU 78h ;78H~7FH中放置的是每个LED值对应的打印T0Count     EQU     70h     ;;中断次数计数,每次50ms 10次为500msDISCOUNT    EQU     71h     ;;显示的次数计数,前8次和为递增显示,后8次为循环显示。MAIN:    MOV     A,#0h           ;A中数值为数码0    MOV     R2,#8           ;一共8位    MOV     R1,#NUMADDINILOOP:    MOV     @R1,A    INC     R1    DJNZ    R2,INILOOP  ;初始化8个LED;;******************************************************    ;;开启中断    SETB    EA   ;开启所有的中断     SETB    ET0   ;开启定时器中断    MOV     TMOD,#0001B ;T0设定为16位计数器(定时方式)    MOV     TH0,#03cH    MOV     TL0,#0afH   ;(65535-50000=0x3caf)定义为50ms    SETB    TR0  ;开启定时器0    MOV     T0Count,#0    ;;中断次数计数,每次50ms 10次为500ms    MOV     DISCOUNT,#0  ;;显示的次数计数,前8次和为递增显示,后8次为循环显示。;;*******************************************************   ;;显示8LED的内容,无限循环显示  LOOP:    ;; 从DispNursAddr读值 在LED上显示    MOV     P0,#00h    MOV     R6,#8h    MOV     R0,#NUMADDNUMSHIFT: ;移动到下一个要显示的数    MOV     R7,#8h  ;循环8次    CLR     A       ;将Acc清零    MOV     A,@R0   ;把要显示的数放到累加器A中  BITSHIFT:           ;74HC595:8位串行输入,8位并行输出    RLC     A       ;带进位的左移    MOV     P0.5,C  ;把移出位放到SER引脚    ;; 在SRCLK上制造一个正跳变,接收SER的值    CLR     P0.4    SETB    P0.4    DJNZ    R7,BITSHIFT    ;结束8位串行输入    INC     R0      ;移动到下一个要显示的值    ;; 在RCLK上制造一个正跳变,接收整个8位值    CLR     P0.3    SETB    P0.3    LCALL   DELAY  ;延迟    INC P0              ;(P0.0~P0.2) 对应LED移动    DJNZ    R6,NUMSHIFT    /*依次输出12345678*/    LJMP    LOOP;无限循环显示;;*******************************************************************   T0_INT:;;T0的中断服务程序    ;; 用64h ~ 69h保存中断服务程序中用到得寄存器的值    MOV     69h,R0      ;push R0    MOV     68h,R1      ;push R1    MOV     67h,A       ;push A    MOV     66h,DPH    MOV     65h,DPL     ;push DPTR    MOV     64h,R7      ;push R7    MOV     A,T0Count       INC     A    MOV     T0Count,A       ;;读取中断的次数,且中断次数增一    CJNE    A,#10,RET0   ;;如果已经产生了10次中断则就是500ms,对显示内容处理1次    ;; UPDATE:    MOV     R1,#NUMADD     MOV     DPTR,#NUMBER          MOV     T0Count,#0  ;;中断次数清零    MOV     A,DISCOUNT    ;;读取对显示内容处理的次数,前8次和后8次处理是不一样的    INC     A    MOV     DISCOUNT,A    DEC     A        MOV     B,#8    DIV     AB             ;;余数B正好为循环闪烁时的起始位置    JNZ    Disp2          ;;若商A为0则说明小于8,递增显示,不为0 则大于8,循环显示Disp1:   ;;递增显示的处理模块    MOV     A,B             ;;从B处递增    MOV     R0,A    ADD     A,R1    MOV     R1,A    MOV     A,R0    MOVC    A,@A+DPTR    ;用实际值取列表中的显示值      MOV     @R1,A        ;把A中显示值放到LED要显示的对应字节中去    LJMP    RET0Disp2:  ;;循环显示的处理模块    MOV     R7,#8    MOV     A,B          ;B处为循环闪烁的起点    MOV     R0,A UpdateDisplay:    MOVC    A,@A+DPTR    ;用实际值取列表中的显示值    MOV     @R1,A        ;把A中显示值放到LED要显示的对应字节中去    INC     R0          ;    INC     R1          ;移动显示值指针    MOV     A,R0    DJNZ    R7,UpdateDisplay;一共有8个LED值要更新RedoT0: ;;重置定时器0    MOV     TH0,#03cH    MOV     TL0,#0afH       ;重置定时器的值    SETB    TR0             ;开启定时器    ;; 还原用到的寄存器的值    MOV     R0,69h      ;pop R0    MOV     R1,68h      ;pop R1    MOV     A,67h       ;pop A    MOV     DPH,66h    MOV     DPL,65h     ;pop DPTR    MOV     R7,64h      ;pop R7    RETI;;****************************************************************  ;;LED显示切换DELAY:      MOV     R4,#10HLOOP1:      MOV     R5,#70LOOP2:    DJNZ    R5,LOOP2    DJNZ    R4,LOOP1    RET END

我来讲一下思想吧

首先我们需要定义一个数值表,里面存的是12345678 12345678
表
然后我们再在指定的内存区中来存放我们即将赋予8个LED数码管的值
LED表值
………………………………………………………………………………………………………………………………


  1. 首先是初始化,将这些LED的值都初始化为0,数值表指针指向数值表的位置0
  2. 然后,将指针所指向的数字放到LED数值表的对应位置上
  3. 指针加一,LED数值表的指针也加一
  4. 刷新显示LED数值表中的数字,若显示次数小于等于8,重复2、3步骤,否则,跳转到5
  5. 数值表指针赋值为1
  6. 重复2、3步骤
  7. 数值表指针赋值为( 当前指针 + 1 ) % 8,跳转到2
  8. 结束