微机原理课设 汽车速度控制

热身


  测接口实验

    测试实验台的 8255 接口是否完好,可以这么测:按下一个键, LED 显示对应开关的打开与否。我们组运气比较倒霉,第一天时碰到有坏的接口。

    需要注意的地方:把端口号(我们的实验台 IOY0 是 0600H,状态控制字端口是 0606H,控制字 82H 表示 B口输入 其他口输出),状态控制字都检验一遍,查看 8255 每个端口是否能正常输入输出。

;(1)按下任意一个键,LED显示对应开关的打开与否
IOY0  EQU 0600H
AA    EQU IOY0+0*2
BB    EQU IOY0+1*2
CC    EQU IOY0+2*2
MODE  EQU IOY0+3*2
STACK1  SEGMENT STACK
     DW  256  DUP(?)
STACK1  ENDS
CODE SEGMENT
     ASSUME CS:CODE,SS:STACK1
START:
    MOV DX,MODE
    MOV AL,82H
    OUT DX,AL
NEXT:
    MOV DX,BB
    IN  AL,DX
    MOV DX,AA
    OUT DX,AL
    MOV AH,1
    JMP NEXT
    MOV AH,4CH
    INT 21H
CODE ENDS
    END START

  流水灯实验要求

    能够在自行设计的接口开发板上,利用不同开关控制 LED 灯的变化。例如:K1 从左往右,K2 从右往左,K3 从中间向两边,K4 从两边向中间依次亮灭变化

    

  解法

    这段代码当时做的时候没存储,不过代码的逻辑很简单:设置好实验台上的端口输出与状态字相关操作后,利用一个十六位的寄存器负责将数据输出到两个八排 LED 灯,每次循环执行 ROR 或者 ROL(根据需求而定)。

    当时的实验台:

      

    下面这段代码只是一个 Demo,可以以此基础上改:

;(2)流水灯实验
IOY0  EQU 0600H
AA    EQU IOY0+0*2
BB    EQU IOY0+1*2
CC    EQU IOY0+2*2
MODE  EQU IOY0+3*2
STACK1  SEGMENT STACK
     DW  256  DUP(?)
STACK1  ENDS
CODE SEGMENT
     ASSUME CS:CODE,SS:STACK1
START:
    MOV DX,MODE                这几行是设置控制字
    MOV AL,80H  ;80H 输出, 82H输入
    OUT DX,AL
    MOV BL,80H
    MOV BH,01H
NEXT:
    MOV DX,AA            输出步骤:1、设置值  2、设置地址  3、向端口输出
    MOV AL,BL
    OUT DX,AL
    MOV DX,BB
    MOV AL,BH
    OUT DX,AL
    CALL DELAY
    ROR BL,1
    ROL BH,1
    JMP NEXT
    MOV AH,4CH
    INT 21H
DELAY PROC NEAR
    MOV CX,20H
D1:
    MOV AX,0FFFFH
D2:
    DEC AX
    JNZ D2
    LOOP D1
    RET
DELAY ENDP
CODE ENDS
    END START

  数码管实验要求

    能够在自行设计的接口开发板上,上电数码管显示 0-7,实现拨动不同开关,数码管显示该开关位置(1-8);若拨动两个及以上的开关,数码管显示“E”

    

  解法

    B口读取开关并进行条件判断,并利用右移判断有几个0,再根据这个信息找到段码中对应的值并显示在数码管上。没有啥很难的算法,当时被坑的地方主要在于段寄存器没有初始化,使得数码管半天不亮。

IOY0 EQU 0600H
AA EQU IOY0 + 0 * 2
BB EQU IOY0 + 1 * 2
CC EQU IOY0 + 2 * 2
MODE EQU IOY0 + 3 * 2

DATA SEGMENT
    CODES db 00h, 3fh, 06h, 5bh, 4fh, 66h, 6dh, 7dh, 07h, 7fh, 6fh, 79h
    LEN EQU $-CODES
DATA ENDS

STACK1 SEGMENT STACK
    DW 256 DUP(?)
STACK1 ENDS

CODE SEGMENT
    assume cs:CODE, ds:DATA, ss:STACK1
START:
    ;set control-word
    MOV DX, MODE
    MOV AL, 82H
    OUT DX, AL
    
    ;set ds
    MOV AX, DATA
    MOV DS, AX

    
    L:
        ;GET KEY VALUE
        MOV DX, BB
        IN AL, DX
        CALL FUNCTION
        JMP L
    
    FUNCTION PROC
        CMP AL, 00H 
        JZ DEFAULT
        CMP AL, 01H
        JZ SHOW
        CMP AL, 02H
        JZ SHOW
        CMP AL, 04H
        JZ SHOW
        CMP AL, 08H
        JZ SHOW
        CMP AL, 10H
        JZ SHOW
        CMP AL, 20H
        JZ SHOW
        CMP AL, 40H
        JZ SHOW
        CMP AL, 80H
        JZ SHOW
        
        JMP EXCEPTION                
        
        SHOW:
            ;MOV AH, 00H
            ;MOV BL, 02H
            ;DIV BL
            MOV CL, 0
        ;get Codes address
            ;ADD SI, AX
            ;ADD SI, 01H
            JMP COUNT
        
        DEFAULT:
            MOV SI, OFFSET CODES
            MOV AL, DS:[SI] ;set original value
            MOV DX, AA ;set address
            OUT DX, AL
            CALL DELAY
            JMP L
            
        NEXT:
            MOV SI, OFFSET CODES
            MOV AH, 00H
            MOV AL, 00H
            MOV AL, CL
            ADD SI, AX
            MOV AL, DS:[SI] ;set original value
            MOV DX, AA ;set address
            OUT DX, AL
            CALL DELAY
        RET
        
        EXCEPTION:
            MOV SI, OFFSET CODES
            ADD SI, len 
            DEC SI
            MOV AL, DS:[SI] ;set original value
            MOV DX, AA ;set address
            OUT DX, AL
            CALL DELAY
        RET
        
        COUNT:
            ADD CL, 01H
            SHR AL, 1
            JNC COUNT
            JMP NEXT
            
    FUNCTION ENDP

        
    EXIT :
        MOV AH, 4CH
        INT 21H

    
    DELAY PROC
        PUSH CX
        PUSH BX
        MOV BX, 0FFFH
        D1: MOV CX, 010H
        D2: 
            LOOP D2
            DEC BX
            JNZ D1
            POP BX
            POP CX
        RET
    DELAY ENDP

CODE ENDS
END START

汽车控制


  我们的汽车控制逻辑是这样:利用两个数码管显示汽车速度,一个数码管显示档位,4个开关控制速度的增加与减少,K1 为 1 挡(10 km/h),K2 为 2 挡(20 km/h),K3 为 4挡(40km/h),K4 为 6挡(60km/h),加速时只能依次加,而不能直接增加到 6挡,减速时可以直接从 60 减速到 0。

  实现难点在于数码管的动态显示:由于四位一体数码管同用一个串口进行输入,这样的话我们就不能分别送不同的值给四个数码管,所以需要通过 8255 的 C 口输出数码管地址口而不是将数码管地址口全部接 GND,使其中三个通高电平,一个接地(共阴极数码管,相当于这个口输入为 0),使得某一个数码管亮而其他几个是熄灭的。然后再传值,传入的值是将速度除以 10 之后的十位数字或者是各位数字,采用 div 指令实现。然后我们通过改变延时时长与 call 子程序的次数,改变每个灯亮的间隔,让肉眼感觉多个数码管同时在改变数字。

  代码部分

IOY0         EQU   0600H          ;片选IOY0对应的端口始地址
MY8255_A     EQU    IOY0+00H*2     ;8255的A口地址
MY8255_B     EQU   IOY0+01H*2     ;8255的B口地址
MY8255_C     EQU   IOY0+02H*2     ;8255的C口地址
MY8255_MODE  EQU   IOY0+03H*2     ;8255的控制寄存器地址



 
SSTACK    SEGMENT STACK
    DW 32 DUP(?)
SSTACK    ENDS
DATA SEGMENT
    NUMS DB 3FH,06H,5BH,4FH,66h,6dh,7dh,07h,7fh,6fh,79H  ;
    ;SELECT_OUTSMG1  DB  0H, 0FEH, 0FDH, 0FBH, 0F7H
    
    
DATA ENDS
CODE    SEGMENT
    ASSUME CS:CODE,SS:SSTACK
START:    
    MOV AX,DATA
    MOV DS,AX
    MOV AX,SSTACK
    MOV SS,AX
        
        
    MOV DX, MY8255_MODE
    MOV AL, 82H    ;1000 0001 表示A口C口高四位低四位输出,B口为输入
    OUT DX, AL    ;控制字送控制寄存器
    MOV BX, 0    ;清零

CTRL:        
    MOV DX , MY8255_B
    IN AL, DX    ;C口值送AL,进行输入
    
    MOV AH,0    ;AX的高8位清零
    TEST AL,1H    ;AL是否等于1,进行and操作,影响标志位
    JNZ T1           ;若AL为XXXX XXX1,跳T1
    MOV  CX ,00      ;CX送0

    JMP A1
    

T1:        
    TEST AL, 2H
    JNZ T2           ;若AL为XXXX XX1X,跳T2
    MOV CX,10        ;CX送10
    MOV DX , MY8255_B
    mov AL,00010000B ;
    out DX, AL    ;将AL的值给C口
    
    JMP A1


        
T2:        
    TEST AL, 4H
    JNZ T3           ;若AL为XXXX X1XX,跳T3
    MOV CX, 20        ;CX送20
    MOV DX , MY8255_B
    mov AL, 00100000B
    out DX, AL
    
    JMP A1
        

T3:        
    TEST AL,8H
    JNZ T4           ;若AL为XXXX 1XXX,跳T4
    MOV CX,40
    MOV DX , MY8255_B
    mov AL,01000000B
    out DX, AL


    JMP A1
        

T4:        
    MOV CX,60        ;CX送60
    MOV DX , MY8255_B
    mov AL,10000000B
    out DX, AL

    
    JMP A1
    

A1:        
    CMP BX,CX
    JNZ AMD  ;ZF=0,跳AMD
    CMP BX,0
    JE CWT    ;ZF=1,跳CWT
        
        
AMD:        
    CMP CX,BX
    JB ASD   ;CX小于BX,跳ASD
    CALL PRINT1  ;执行子程序,会返回
    JMP CTRL
ASD:
    CALL PRINT2
    JMP CTRL

CWT:        
    CALL PRI
    JMP CTRL    



PRINT1 PROC
    ;因为每次只能亮1个的原因,所以要call多次实现肉眼错觉
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    ;CALL PRI
    ;CALL PRI
    ;CALL PRI
    INC  BX
    CMP BX,CX
    JB  PRINT1
    MOV BX,CX
    RET
PRINT1 ENDP

PRINT2 PROC
        
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    CALL PRI
    ;CALL PRI
    ;CALL PRI
    ;CALL PRI
    DEC  BX
    CMP CX,BX
    JB  PRINT2
    MOV BX,CX
    RET
PRINT2 ENDP


        
PRI PROC    
    PUSH CX
    PUSH DX
       PUSH AX
       PUSH BX
            
       ;速度高位
    MOV AX,BX
      MOV CL,10
      DIV CL        ;  AH 余数  AL  商  36 / 10 = 3 ..... 6  
      MOV CX,0
      MOV CX,14 ;0000 1110b,就是设置第一个数码管亮
      MOV BL,AL   ; 3   
           
      CALL HUA
      CALL YANSHI
  
      
      ;速度低位    
      MOV BL,AH
      MOV CX,13 ;0000 1101b,就是设置第二数码管亮
      CALL HUA
      CALL YANSHI
      
      ;档位
      MOV BL, AL
      MOV CX,7 ;0000 0111b,就是设置第4个亮
      CALL HUA
      CALL YANSHI
               
           
      POP BX
    POP AX
    POP DX
    POP CX
    RET
PRI ENDP


HUA PROC
    PUSH BX
    PUSH AX
    
    ;控制第XXX灯亮
    MOV DX, MY8255_C
    MOV AX,CX
    OUT DX,AX   ;B口输出CX
    
    
    ;输出值到数码管
    MOV BH,0
    MOV DX,MY8255_A
    MOV SI,OFFSET NUMS

    MOV AX,[SI+BX]
    OUT DX,AX   ;A口输出BX,也就是NUMS[BX]

    POP AX
    POP BX
    RET
HUA ENDP    

                    
YANSHI PROC


    PUSH CX
    MOV CX,2000
YS:
    CALL YANSHI2
    DEC CX
    JNZ YS
POP CX
    RET    
YANSHI ENDP


YANSHI2 PROC
    PUSH CX
    MOV CX,1
TYUY:
    DEC CX
    JNZ TYUY
    
    POP CX
    RET
YANSHI2 ENDP
CODE    ENDS
END START
        

  实验台接法

    注意实验台部分 B C 口对调,C 口低四位输入控制开关 ,所以代码需要将状态控制字改成 81 H 并且将下面的 MY8255_C 和 MY8255_B 对调

    

  实验台效果展示

    拨动 K1 K2,汽车速度为 20 km/h,档位为 2 挡

    

  

  电路布线图

    四位一体数码管的引脚可能会不一样,另外推荐做一个镜像图,焊板子背面的时候方便

    

   

  洞洞板实物图

    需要注意的是老师不让用飞线,而我嫌背面太丑用了两个飞线焊到了洞洞板的正面,所以得去掉这两个飞线,换成背面的导线 

    

    飞线版本的洞洞板(老师不让用)

    

      

    

    无飞线版本

    

    

    

感悟


  因为自己大一是电路相关专业的,有学过 C51 和 STM32 ,以及大二自己看了一点王爽的汇编,所以这次实验总体难度不大,但是周围的同学普遍对硬件有排斥的心理,而幸运的是我的队友们比较好,原意去学一下这次实验的东西。发现软工学生硬件真是一个硬伤,硬件课程少,没焊过甚至没见过电路板,感觉有点可惜

原文地址:https://www.cnblogs.com/Bw98blogs/p/10209491.html