微机原理与接口技术实验

实验01 存储器读写

TPC01-1.ASM

信息显示程序

俺也不清楚能不能麻溜的使用call dispmsg直接显示,对第一个实验印象不深了。

    include io.inc
    .model small
    .stack
    .data
msg 'Hello,Assembly!',13,10,0
    .code
start:
    mov ax,@data
    mov ds,ax
    
    mov ah,9
    mov dx,offset msg
    int 21h
    mov ax,4cooh
    int 21h
    end start

    .exit 0
    end start

TPC01-2.ASM

存储器的读写

实验报告中已指出:SRAM的段地址为0D000H,而SRAM6264的地址范围为D6000H~D6FFFH,说明初始偏移量为6000H,用“段基地址:偏移地址”(比如es:[bx])即可表示出存储器的位置。对存储器的读和写就是汇编的循环语句问题。

include io.inc
    .model small
    .stack
    .data
msg byte 'start read!',13,10,0
    .code
start:
    mov ax,@data
    mov ds,ax
    
    mov ax,0d000h   ;6264段地址
    mov es,ax       ;段基地址
    mov bx,6000h    ;偏移地址
    mov al,20h      ;ASCII码从20H开始
    mov cx,95       ;ASCII码有95个字符
    push es
    push bx
    push cx
write:
    mov es:[bx],al
    inc al
    inc bx
    loop write
    
    mov ax,offset msg
    call dispmsg
    call readc
    pop cx
    pop bx
    pop es
read:
    mov al,es:[bx]
    call dispc
    inc bx
    loop read
	
	.exit 0
    end start 

实验04 中断实验

TPC04-1.ASM

主片8259中断实验

该中断属于可屏蔽中断,编程思路与课本例7-6思路一致。因为中断向量号为0BH,所以需要做一些改动。

   include io.inc
    .model small
    .stack
    .data
intmsg byte 'TPCA Interrupt No.3!',13,10,0
counter byte 0      ;中断次数
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;获取原中断向量表项
    mov ax,350bh
    int 21h
    push es
    push bx
    
    cli             ;关中断
    ;设置新中断向量表项
    push ds
    mov ax,seg new0bh
    mov ds,ax
    mov dx,offset new0bh
    mov ax,250bh
    int 21h
    pop ds
    
    ;获取原IMR
    in al,21h
    push ax         ;push最少跟16位,所以不能用push al
    
    ;设置新IMR
    and al,0f7h     ;11110111
    out 21h,al
    
    mov counter,0   ;设置中断次数初值
    sti             ;开中断
    
start1:
    cmp counter,5
    jb start1
    
    cli             ;关中断 
    ;恢复IMR
    pop ax
    out 21h,al
    ;恢复原中断向量表项
    pop dx          ;offset
    pop ds          ;seg
    mov ax,250bh
    int 21h
    sti
    
    .exit 0

new0bh proc
    sti
    push ax
    push si
    push ds
    mov ax,@data    
    mov ds,ax
    inc counter
    mov si,offset intmsg
    call dpstri     ;不能使用DOS系统功能调用,所以需要调用ROM-BIOS
    ;EOI
    mov al,20h
    out 20h,al
    pop ds
    pop si
    pop ax
    iret
new0bh endp

dpstri proc         ;显示字符串子程序
    push ax
    push bx
dps1:
    mov al,[si]
    cmp al,0
    jz dps2
    mov bx,0
    mov ah,0eh
    int 10h
    inc si
    jmp dps1
dps2:
    pop bx
    pop ax
    ret
dpstri endp
    
end start

TPC04-2.ASM

从片8259中断实验

首先需要修改中断向量号为72H带来的变化。同时,因为是从片,所以需要修改主片的IR2状态和EOI命令。

    include io.inc
    .model small
    .stack
    .data
intmsg byte 'TPCA Interrupt No.3!',13,10,0
counter byte 0      ;中断次数
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;获取原中断向量表项
    mov ax,3572h
    int 21h
    push es
    push bx
    
    cli             ;关中断
    ;设置新中断向量表项
    push ds
    mov ax,seg new72h
    mov ds,ax
    mov dx,offset new72h
    mov ax,2572h
    int 21h
    pop ds
    
    ;获取原IMR
    in al,21h
    push ax
    
    ;设置新IMR
    and al,0fbh     ;11111011
    out 21h,al
    
    ;获取原IMR
    in al,0a1h
    push ax
    
    ;设置新IMR
    and al,0fbh     ;11111011
    out 0a1h,al
    
    mov counter,0   ;设置中断次数初值
    sti             ;开中断
    
start1:
    cmp counter,5
    jb start1
    
    cli             ;关中断 
    ;恢复IMR
    pop ax
    out 0a1h,al
    pop ax
    out 21h,al
    ;恢复原中断向量表项
    pop dx          ;offset
    pop ds          ;seg
    mov ax,2572h
    int 21h
    sti
    
    .exit 0

new72h proc
    sti
    push ax
    push si
    push ds
    mov ax,@data    
    mov ds,ax
    inc counter
    mov si,offset intmsg
    call dpstri     
    ;EOI:先从片后主片
    mov al,20h
    out 0a0h,al
    out 20h,al

    pop ds
    pop si
    pop ax
    iret
new72h endp

dpstri proc         ;显示字符串子程序
    push ax
    push bx
dps1:
    mov al,[si]
    cmp al,0
    jz dps2
    mov bx,0
    mov ah,0eh
    int 10h
    inc si
    jmp dps1
dps2:
    pop bx
    pop ax
    ret
dpstri endp
    
end start

TPC04-3.ASM

中断嵌套实验

实验3类似于实验1和2的结合,在优先级低的中断服务程序中加入delay函数即可。

实验3:
   include io.inc
    .model small
    .stack
    .data
msg3 byte 'TPCA Interrupt No.3!',13,10,0
msg31 byte 'TPCA Interrupt No.3 Again!',13,10,0
msg10 byte 'TPCA Interrupt No.10!',13,10,0
msg101 byte 'TPCA Interrupt No.10 Again!',13,10,0
counter3 byte 0
counter10 byte 0
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;获取原中断向量表项
    mov ax,350bh
    int 21h
    push es
    push bx
    
    mov ax,3572h
    int 21h
    push es
    push bx
    
    cli
    ;设置新中断向量表项
    push ds
    mov ax,seg new0bh
    mov ds,ax
    mov dx,offset new0bh
    mov ax,250bh
    int 21h
    pop ds
    
    push ds
    mov ax,seg new72h
    mov ds,ax
    mov dx,offset new72h
    mov ax,2572h
    int 21h
    pop ds
    
    ;获取原IMR(主)
    in al,21h
    push ax
    
    ;设置新IMR(主)
    and al,0f3h     ;11110011
    out 21h,al
    
    ;获取原IMR(从)
    in al,0a1h
    push ax
    
    ;设置新IMR(从)
    and al,0fbh     ;11111011
    out 0a1h,al
    
    mov counter3,0   ;设置中断次数初值
    mov counter10,0
    sti             ;开中断
    
start1:
    cmp counter3,5
    jb start1
start2:
    cmp counter10,5
    jb start2
    
    cli             ;关中断 
    ;恢复IMR
    pop ax
    out 0a1h,al
    pop ax
    out 21h,al
    ;恢复原中断向量表项
    pop dx          ;offset
    pop ds          ;seg
    mov ax,2572h
    int 21h
    
    pop dx
    pop ds
    mov ax,250bh
    int 21h
    sti
    
    .exit 0

new0bh proc
    sti
    push ax
    push si
    push ds
    mov ax,@data
    mov ds,ax
    inc counter3
    mov si,offset msg3
    call dpstri
    
    call delay
    
    mov si,offset msg31
    call dpstri
    ;EOI
    mov al,20h
    out 20h,al
    pop ds
    pop si
    pop ax
    iret
new0bh endp
    
new72h proc
    sti
    push ax
    push si
    push ds
    mov ax,@data
    mov ds,ax
    inc counter10
    mov si,offset msg10
    call dpstri
    
    call delay
    
    mov si,offset msg101
    call dpstri
    ;EOI
    mov al,20h
    out 0a0h,al
    out 20h,al

    pop ds
    pop si
    pop ax
    iret
new72h endp
dpstri proc         ;显示字符串子程序
    push ax
    push bx
dps1:
    mov al,[si]
    cmp al,0
    jz dps2
    mov bx,0
    mov ah,0eh
    int 10h
    inc si
    jmp dps1
dps2:
    pop bx
    pop ax
    ret
dpstri endp
delay proc
    push bx
    push cx
    mov bx,2000
delay1:
    xor cx,cx
delay2:
    loop delay2
    dec bx
    jnz delay1
    pop cx
    pop bx
    ret
delay endp

    end start

实验05 可编程定时器/计数器(8253/8254)

TPC05-1.ASM

编程记录脉冲个数

通过计数器0的I/O端口号读取计数器当前计数值,如果相同则继续说明没有经过一个时钟周期,反复读取,直到计数值变化,输出计数值。若计数未结束(计数值不为0),则循环上述步骤。

include io.inc
    .model small
    .stack
    .data
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;写入方式控制字
    mov dx,283h
    mov al,10h ;00010000
    out dx,al
    
    ;写入计数值
    mov dx,280h
    mov al,5
    out dx,al
    mov ah,al
again:
    ;反复读取计数值需要加延时
    call delay    
    in al,dx
    cmp al,ah
    jz again ;计数值没变
    
    call dispuib
    call dispcrlf
    
    mov ah,al
    cmp al,0
    jnz again ;计数未结束
    
    .exit 0
    
delay proc
    push bx
    push cx
    mov bx,2000
delay1:
    xor cx,cx
delay2:
loop dalay2
    dec bx
    jnz delay1
    pop cx
    pop bx
    ret
delay endp 
    end start

TPC05-2.ASM

编程输出一定频率的方波信号

方波信号应该选用方式3,在设定好初始化程序后,8254芯片就可以周期性地生成方波了

include io.inc
    .model small
    .stack
    .data
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;写入方式控制字(计数器0)
    mov dx,283h
    mov al,37h  ;00110111
    out dx,al
    ;写入计数初值
    mov dx,280h
    mov ax,1000h
    out dx,al
    mov al,ah
    out dx,al
    
    ;写入方式控制字(计数器1)
    mov dx,283h
    mov al,76h  ;01110110
    out dx,al
    ;写入计数初值
    mov dx,281h
    mov ax,1000
    out dx,al
    mov al,ah
    out dx,al
    
    .exit 0
	end start

TPC05-3.ASM

实现定时1秒的功能

这道题与课本上例7-6完全一样,例7-6的前提是该PC系统的IRQ来源于定时器,这里我们只需要补充定时器的实现细节即可(即定时器的初始化操作)

    include io.inc
    .model small
    .stack
    .data
intmsg byte 'Interrupt.',13,10,0
counter byte 0
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;获取原中断向量
    mov ax,350bh
    int 21h
    push es
    push bx
    
    ;设置新中断向量
    cli
    push ds
    mov ax,seg new0bh
    mov ds,ax
    mov dx,offset new0bh
    mov ax,250bh
    int 21h
    pop ds
    
    ;获取原IMR
    in al,21h
    push ax
    
    ;设置新IMR
    and al,0f7h  ;11110111
    out 21h,al
    
    ;8253/8254初始化
    ;计数器0
    mov dx,283h
    mov al,37h  ;00110111
    out dx,al
    mov ax,1000h
    mov dx,280h
    out dx,al
    mov al,ah
    out dx,al
    ;计数器1
    mov dx,283h
    mov al,77h  ;01110111
    out dx,al
    mov ax,1000h
    mov dx,281h
    out dx,al
    mov al,ah
    out dx,al
    
    mov counter,0
    
    sti
    
start1:
    cmp counter,5
    jb start1
    
    ;恢复
    cli
    pop ax
    out 21h,al
    pop dx
    pop ds
    mov ax,250bh
    int 21h
    sti
    
    .exit 0
new0bh proc
    sti
    push ax
    push si
    push ds
    mov ax,@data
    mov dx,ax
    inc counter
    mov si,offset intmsg
    call dpstri
    mov al,20h
    out 20h,al
    pop ds
    pop si
    pop ax
    iret
new0bh endp

dpstri proc
    push ax
    push bx
dps1:
    mov al,[si]
    cmp al,0
    jz dps2
    mov bx,0
    mov ah,0eh
    int 10h
    inc si
    jmp dps1
dps2:
    pop bx
    pop ax
    ret
dpstri endp

    end start
    

实验06 可编程并行接口(8255)

TPC06-1.ASM

方式0(基本输入输出)实验

先初始化,再对数据端口读写即可。 其中,端口A为方式0输出,端口C为方式0输入(输入信号为K0~K7),端口B任意。

    include io.inc
    .model small
    .stack
    .data
    .code
start:
    mov ax,@data
    mov ds,ax
    
    mov dx,28bh
    mov al,89h  ;10001001
    out dx,al
    
    mov dx,28ah
    in al,dx
    mov dx,288h
    out dx,al
    
    .exit 0
end start

TPC06-2.ASM

方式1(选通)输出实验

中断服务程序,中断的来源是手动按一次单脉冲按钮。我们只需要完善8255的初始化程序和把中断服务程序修改为数据端口的写操作即可。

    include io.inc
    .model small
    .stack
    .data
msg byte 01h
counter byte 0
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;获取原中断向量
    mov ax,350bh
    int 21h
    push es
    push bx
    
    ;设置新中断向量
    cli
    push ds
    mov ax,seg new0bh
    mov ds,ax
    mov dx,offset new0bh
    mov ax,250bh
    int 21h
    pop ds
    
    ;获取原IMR
    in al,21h
    push ax
    
    ;设置新IMR
    and al,0f7h ;111101111
    out 21h,al
    
    mov counter,0
    
    ;8255初始化
    mov al,0a0h ;10100000h
    mov dx,28bh
    out dx,al
    
    sti
start1:
    cmp counter,8
    jb start1
    
    ;恢复
    cli
    pop ax
    out 21h,al
    
    pop dx
    pop ds
    mov ax,250bh
    int 21h
    sti
    
    .exit 0
new0bh proc
    sti
    inc counter   
    call litlight
    
    ;EOI
    mov al,20h
out 20h,al

    iret
new0bh endp
litlight proc
    mov al,msg
    call disphb
    call dispcrlf
    mov dx,288h
    out dx,al
    rol light,1
    
    ret
litlight endp
    
    end start

TPC06-3.ASM

方式1(选通)输入实验

中断仍由手动产生,和上一个实验一样,我们只需完善8255的初始化程序和修改中断服务程序。

    include io.inc
    .model small
    .stack
    .data
counter byte 0
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;获取原中断向量
    mov ax,350bh
    int 21h
    push es
    push bx
    
    ;设置新中断向量
    cli
    push ds
    mov ax,seg new0bh
    mov ds,ax
    mov dx,offset new0bh
    mov ax,250bh
    int 21h
    pop ds
    
    ;获取原IMR
    in al,21h
    push ax
    
    ;设置新IMR
    and al,0f7h ;111101111
    out 21h,al
    
    mov counter,0
    ;8255初始化
    mov al,0b0h ;10110000
    mov dx,28bh
    out dx,al
    
    sti
start1:
    cmp counter,5
    jb start1
    
    ;恢复
    cli
    pop ax
    out 21h,al

    pop dx
    pop ds
    mov ax,250bh
    int 21h
    sti
    .exit 0
new0bh proc
    sti
    inc counter
    call displed
    ;EOI
    mov al,20h
    out 20h,al
    
    iret
new0bh endp
displed proc
    mov dx,288h
    in al,dx
    call disphb
    call dispcrlf
    ret
displed endp
    
    end start

实验08 数码管显示

TPC08-1.ASM

一位静态显示

输入一个数,通过并行接口8255传给数码管,这里涉及8255的初始化编程。因为传给数码管的数需要让其对应段发亮,所以需要换码操作。因为已经通过硬件方式选中S3,所以只需要关注段控制,将段表提前写好进行换码即可。

    include io.inc
    .model small
    .stack
    .data
ledtb byte 3fh,06h,5bh,4fh,66h
      byte 6dh,7dh,07h,7fh,6fh
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;8255初始化
    mov dx,28bh
    mov al,80h ;10000000
    out dx,al
    
    ;1位数码管显示
    call readuiw ;出口参数为ax
    mov bx,ax
    mov al,ledtb[bx] ;换码为显示代码
    mov dx,288h
    out dx,al
    
    .exit 0
	end start

TPC08-2.ASM

多位动态显示

让处理器通过8255传给段控制端口段显示代码,然后传给位控制端口位显示代码,顺序地输出段码和位码,依次让每个数码管显示数字,并不断重复显示。为此,可以开辟一个数码缓冲区,存放要显示地数字,第一个数字在最左边地数码管显示,下一个数字送到左边第二个数码管显示,以此类推,利用rol指令即可实现这一过程。和课本不同之处在于课本是循环8位,而实验要求循环4位,需稍加修改。

    include io.inc
    .model small
    .stack
    .data
leddt byte 3,4,5,6  ;存放要显示的数字
ledtb byte 3fh,06h,5bh,4fh,66h
      byte 6dh,7dh,07h,7fh,6fh
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;8255初始化
    mov al,80h ;10000000
    mov dx,28bh
    out dx,al
    
    mov si,offset leddt
    call displed

displed proc
    push ax
    push bx
    push dx
again:    
    xor bx,bx
    ;选中最左边的数码管
    ;也有可能是最右边...
    mov ah,01h  ;位码00000001
led1:
    mov bl,[si]
    mov al,ledtb[bx] ;换码
    mov dx,288h ;段控制端口
    out dx,al
    
    mov al,ah
    mov dx,289h ;位控制端口
    out dx,al
    
    call delay
    
    inc si
    rol ah,1    ;指向下一个数码管
    ;是否循环一个周期
    cmp ah,10h  ;00010000   
    jz again
    
    jmp led1 
    pop dx
    pop bx
    pop ax
    
    ret
displed endp
    
    
delay proc
    push bx
    push cx
    mov bx,5
delay1:
    xor cx,cx
delay2:
    loop delay2
    dec bx
    jnz delay1
    pop cx
    pop bx
    ret
delay endp
    
    end start

TPC08-3.ASM

多位循环显示

俺这道题不会,下面的代码感觉不怎么对。为了应付期末考试的话可以不用看这个了(追求满绩也不用看)

    include io.inc
    .model small
    .stack
    .data
buf byte 0,0,0,0  ;存放要显示的数字
ledtb byte 3fh,06h,5bh,4fh,66h
      byte 6dh,7dh,07h,7fh,6fh
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;8255初始化
    mov dx,28bh
    mov al,80h
    out dx,al
start1:
    xor si,si
    mov ah,08h ;位码
again:
    mov bl,buf[si]
    mov bh,0
    mov al,led[bx]
    mov dx,288h
    out dx,al  ;段
    
    mov al,ah
    mov dx,289h
    out dx,al  ;位
    call delay
    
    inc si
    shr ah,1
    jnz again
    
    mov bl,buf+3   ;要显示的数加1
    inc bl
    cmp bl,10
    jb next3
    mov bl,0
    mov bh,buf+2
    inc bh
    cmp bh,10
    jb next2
    mov bh,0
    mov cl,buf+1
    inc cl
    cmp cl,10
    jb next1
    mov cl,0
    mov ch,buf
    inc ch
    cmp ch,10
    jb next0
    mov ch,0
next0:
    mov buf,ch
next1:
    mov buf+1,cl
next2:
    mov buf+2,bh
next3: 
    mov buf+3,cl
    
    .exit 0
delay proc
    push bx
    push cx
    mov bx,5
delay1:
    xor cx,cx
delay2:
    loop delay2
    dec bx
    jnz delay1
    pop cx
    pop bx
    ret
delay endp

    end start

实验10 模/数转换器

TPC10-1.ASM

软件延时方式

软件延时方式不需要考虑EOC信号,因此只需要应用out和in指令实现对ADC0809进行启动和读数据两个操作即可。

    include io.inc
    .model small
    .stack
    .data
msg byte 'press any key to exit',13,10,0
    .code
start:
    mov ax,@data
    mov ds,ax
    
    mov ax,offset
    call dispmsg
again:
    mov dx,298h ;启动ADC
    out dx,al
    call delay
    
    in al,dx    ;从ADC读入数据
    call disphb
    call dispcrlf
    call readkey
    jz again
    
    .exit 0
delay proc
    push bx
    push cx
    mov bx,2000
delay1:
    xor cx,cx
delay2:
    loop delay2
    dec bx
    jnz delay1
    pop cx
    pop bx
    ret
delay endp
    end start

TPC10-2.ASM

查询方式

查询方式两步走:循环+test

    include io.inc
    .model small
    .stack
    .data
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;8255的初始化
    mov al,88h  ;10001000(PC7作输入端)
    mov dx,28bh
    out dx,al
start1:
    mov dx,298h ;启动ADC
    out dx,al
    call delay
    
    mov dx,28ah ;端口C
start2:
    in al,dx
    test al,80h ;10000000
    jz start2
    
    mov dx,298h
    in al,dx    ;读取数字量
    call disphb
    call dispcrlf
    
    jmp start1
    .exit 0
    
delay proc
    push bx
    push cx
    mov bx,2000
delay1:
    xor cx,cx
delay2:
    loop delay2
    dec bx
    jnz delay1
    pop cx
    pop bx
    ret
delay endp
    end start

TPC10-3.ASM

中断方式

中断方式的编程已经很熟悉了,和之前的处理方法一样。我们需要设置好中断服务程序之前的环境和修改相应的中断服务程序。

    include io.inc
    .model small
    .stack
    .data
counter byte 0
    .code
start:
    mov ax,@data
    mov ds,ax
    
    ;获取原中断向量
    mov ax,350bh
    int 21h
    push es
    push bx
    
    ;设置新中断向量
    cli
    push ds
    mov ax,seg new0bh
    mov ds,ax
    mov dx,offset new0bh
    mov ax,250bh
    int 21h
    pop ds
    
    ;获取原IMR
    in al,21h
    push ax
    
    ;设置新IMR
    and al,0f7h ;111101111
    out 21h,al
    
    mov counter,0
    
    ;启动ADC
    mov dx,298h
    out dx,al
    call delay
    
    sti
start1:
    cmp counter,10
    jb start1
    
    ;恢复
    cli
    pop ax
    out 21h,al
    
    pop dx
    pop ds
    mov ax,250bh
    int 21h
    sti
    
    .exit 0
new0bh proc
    sti
    inc counter
    
    ;读取并显示数字量
    mov dx,298h
    in al,dx
    call disphb
    call dispcrlf
    
    ;EOI
    mov al,20h
    out 20h,al
    iret
new0bh endp

delay proc
    push bx
    push cx
    mov bx,2000
delay1:
    xor cx,cx
delay2:
    loop delay2
    dec bx
    jnz delay1
    pop cx
    pop bx
    ret
delay endp
    end start 

祝大家微机都满绩

你可能感兴趣的:(接口)