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


    热身


      测接口实验

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

  • 相关阅读:
    开发3dMax插件的方法和应用
    实现X*N
    fork与vfork的区别
    使用递归算法写一段程序
    宏和函数的区别
    多线程学习(一)
    [算法天天练]堆排序
    [转][算法天天练]堆与堆排序
    [转]快速排序 挖坑讲解方法
    [算法天天练]选择排序法
  • 原文地址:https://www.cnblogs.com/Bw98blogs/p/10209491.html
Copyright © 2020-2023  润新知