【接口技术】实验五:可编程并行接口8255

一. 实验目的

  1. 了解8255芯片结构及编程方法。
  2. 了解8255输入/输出实验方法。
  3. 掌握8255控制键盘及显示电路的基本功能及编程方法。
  4. 掌握一般键盘和显示电路的工作原理。

二. 实验内容

实验5-1 8255并行输入/输出实验

将实验的线路连接好后,编程,将8255的C口作为输入。输入信号由8个逻辑电平开关提供,A口作为输出,其内容由发光二极管来显示。编程从8255C口输入数据,再从A口输出。

电路图:
在这里插入图片描述
接线:
在这里插入图片描述
汇编代码:

P8255A    EQU  288H
P8255B    EQU  0602H
P8255C    EQU  28AH
P8255MODE EQU  28BH

code segment
    assume cs:code

start:    
        mov dx,P8255MODE
        mov al,10001001b
        out dx,al
 
next:    
        mov dx,P8255C
        in al,dx
        mov dx,P8255A
        out dx,al

        mov dl,0ffh
        mov ah,06h
        int 21h
        jz next
        mov ax, 4ch
        int 21h

code ends
end start

运行结果:

运行程序,拨动开关,相应的二极管被点亮。效果如下图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验5-2 并行接口键盘反转扫描实验

编程,设置8255C口键盘输入、A口为数码管段码输出。使得在4×4小键盘上每按一个键,8位数码管上显示出相应字符。
在这里插入图片描述
电路图:
在这里插入图片描述
接线:
在这里插入图片描述
汇编代码:

a8255 equ 288H    ;8255 A口    
c8255 equ 28aH    ;8255 C口
k8255 equ 28bH    ;8255 控制口

;========================数据定义段data开始=======================;

data segment

table1 dw 0770h,0B70h,0D70h,0E70h,07B0h,0BB0h,0DB0h,0EB0h        ;键盘行列码表,对应着si寄存器,用于确定按下按键的位置及按键信息
       dw 07D0h,0BD0h,0DD0h,0ED0h,07E0h,0BE0h,0DE0h,0EE0h

LED    DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH        ;LED段码表,分别代表0~F
       DB 39h,5EH,79h,71h,0ffh

char  db '0123456789ABCDEF'                                      ;字符表,对应着di寄存器,用于最后在屏幕上输出内容

mes   db 0ah,0dh,'PLAY ANY KEY IN THE SMALL KEYBOARD! ',0ah,0dh  ;提示信息,用于开始时在屏幕上提示输入
      db 'IT WILL BE ON THE SCREEN! END WITH E ',0ah,0dh,'$'

key_in db 0h

data ends

;========================数据定义段data结束=======================;

;=======================堆栈定义段stacks开始======================;

stacks segment stack
     db 100 dup (?)
stacks ends

;=======================堆栈定义段stacks结束======================;

code segment
        assume cs:code,ds:data,ss:stacks,es:data

start:
        cli                       ;禁止中断发生
        mov ax,data               ;将data放入通用寄存器ax中,data是伪指令,起到过渡作用
        mov ds,ax                 ;将ax中的data转到ds数据段寄存器中,让数据段指向正确的位置,但内存数不能放入段地址
        mov es,ax                 ;将ax中的data放入通用寄存器es中
        mov ax,stacks             ;将stack堆栈放入通用寄存器ax中,起到过渡作用
        mov ss,ax                 ;将ax中的stack转到数据段寄存器ss中

        mov dx,offset mes         ;显示提示信息mes
        mov ah,09                 ;将功能号09H送入ah
        int 21h                   ;返回DOS,输出需要显示的信息

        mov dx,k8255              ;设置8255 (工作方式0;A口输出;C口高四位输出,低四位输入),初始化控制字,将控制字k8255送入端口dx
        mov al,81h                ;将控制字10000001(81h)送入al中,特征位D7默认置1,A组方式0,D6D5=00,端口A输出,D4=0,PC7~PC4输出,D3=0,B组方式0,D2=0,B端口输出,D1=0,PC3~PC0输入,D0=1
        out dx,al                 ;将al中的控制字送入端口dx中

main_key:
        call key                  ;获取一个输入的字符并显示
        call display              ;调用显示子程序,显示得到的字符

        cmp byte ptr key_in,'E'   ;将输入的字符key_in与'E'进行比较,计算key_in-'E'的值,判断是否执行退出操作,按'E'退出程序
        jnz main_key              ;如果key_in-'E'的值不为0,则跳转至main_key,继续循环
        mov ax,4c00h              ;如果key_in-'E'的值等于0,则退出
        int 21h                   ;返回DOS,退出

;==========================子程序key开始=========================;

key proc near                     ;开始定义子程序key的伪指令,NEAR属性为段内近调用,调用程序和子程序在同一代码段中,只能被相同代码段的其他程序调用

key_loop:                         ;开始定义key_loop循环,等待键盘按键按下
        mov ah,1                  ;调用DOS的1号功能,没有入口参数,只有出口al
        int 16h                   ;读取键盘缓冲区输入
        jnz exit                  ;若pc键盘有键按下则退出

        mov dx,c8255              ;设置端口C,准备读取行3~0
        in al,dx                  ;进行读行扫描值
        and al,0fh                ;将al寄存器中的高四位内容清零
        cmp al,0fh                ;将al中高四位清零后的内容与0fh进行比较,判断是否有键被按下
        jz key_loop               ;如若未发现有键按下则继续转至key_loop进行循环                           
        call delay                ;调用延迟子程序delay

        mov ah,al                 ;设置8255 (工作方式0;A口输出;C口高四位输入,低四位输出),将al内容送入ah暂存
        mov dx,k8255              ;初始化控制字,将控制字k8255送入端口dx
        mov al,88h                ;将控制字10001000(88h)送入al中,特征位D7默认置1,A组方式0,D6D5=00,端口A输出,D4=0,PC7~PC4输出,D3=1,B组方式0,D2=0,B端口输出,D1=0,PC3~PC0输入,D0=0
        out dx,al                 ;将al中的控制字送入端口dx中 
        mov al,ah                 ;将ah中的暂存值还给al
        
        mov dx,c8255              ;设置端口C,准备读取列3~0
        in al,dx                  ;读列扫描值 
        and al,0f0h               ;将al低四位清零
        cmp al,0f0h               ;将al中低四位清零后的内容与0f0h进行比较,判断是否有键被按下
        jz key_loop               ;如若未发现有键按下则继续转至key_loop进行循环 

        mov si,offset table1      ;si为键盘扫描码表table1的首地址
        mov di,offset char        ;di为字符表char的首地址
        mov cx,16                 ;cx为待查表的表大小为16,0~F

key_tonext:                       ;开始定义key_tonext操作,用于查找扫描码,确定按下按键的位置
        cmp ax,[si]               ;逐个比较键盘扫描码表table1的首地址的值,计算行列差值,进而确定按下的键在键盘上的位置
        jz key_findkey            ;如果计算结果等于0,则跳转到key_findkey操作
        dec cx                    ;把cx中的值减一
        jz key_loop               ;未找到对应扫描码,则跳转到key_loop循环中,等待再次按下按键
        add si,2                  ;源变址寄存器si加2
        inc di                    ;字符表首地址di自增1,di指向字符表char中的下一个字符内容
        jmp key_tonext            ;跳转至key_tonext操作

key_findkey:                      ;开始定义key_findkey操作,用于查找键盘码,并在屏幕上显示
        mov dl,[di]               ;将di中的字符内容送入dl中
        mov ah,02                 ;调用DOS的2号功能,将功能号02H送入ah
        int 21h                   ;显示查找到的键盘码,进行单字符输出,入口是dl,在屏幕上输出di中的键盘码字符内容
        mov byte ptr key_in,dl    ;将dl中的键盘码送入key_in中

key_waitup:                       ;开始定义key_waitup操作,用于进行按键抬起的操作,用于防止抖动
        mov dx,k8255              ;初始化控制字,将控制字k8255送入端口dx
        mov al,81h                ;将控制字10000001(81h)送入al中,特征位D7默认置1,A组方式0,D6D5=00,端口A输出,D4=0,PC7~PC4输出,D3=0,B组方式0,D2=0,B端口输出,D1=0,PC3~PC0输入,D0=1
        out dx,al                 ;将al中的控制字送入端口dx中

        mov dx,c8255              ;设置端口C
        mov al,0fh                ;00001111(0fh)送入al中,端口C特殊控制方式:特征位D7置0,D6D5D4不使用,位选择为端口C的7位,D3D2D1均为1,置位D0=1
        out dx,al                 ;将al中的控制字送入端口dx中

        in al,dx                  ;进行读行扫描值
        and al,0fh                ;将al寄存器中的高四位内容清零
        cmp al,0fh                ;将al中高四位清零后的内容与控制字0fh进行比较,判断是否有键被按下
        jnz key_waitup            ;若按键未抬起,则继续跳转至key_waitup循环

        call delay                ;调用延时子程序
        ret                       ;用栈中的数据,修改IP的内容,从而实现近转移

exit:                             ;子程序key退出
        mov byte ptr key_in,'E'   ;'E'字符送入key_in中
        ret                       ;用栈中的数据,修改IP的内容,从而实现近转移

key endp                          ;结束子程序key伪指令

;==========================子程序key结束=========================;

;=========================子程序delay开始========================;

delay proc near                   ;开始定义子程序delay的伪指令,NEAR属性为段内近调用,调用程序和子程序在同一代码段中,只能被相同代码段的其他程序调用

        push ax                   ;延迟50ms~100ms
        mov ah,0                  ;调用DOS0号指令
        int 1ah                   ;返回DOS
        mov bx,dx                 ;将dx中内容送入bx

delay1:                           ;定义delay1操作
        mov ah,0                  ;调用DOS0号指令
        int 1ah                   ;返回DOS
        cmp bx,dx                 ;比较bx和dx中值的值是否相等,计算bx-dx的值是否为0
        jz delay1                 ;若bx-dx的值为0,则继续跳转至delay1
        mov bx,dx                 ;将dx中内容送入bx

delay2:                           ;定义delay2操作
        mov ah,0                  ;调用DOS0号指令
        int 1ah                   ;返回DOS
        cmp bx,dx                 ;比较bx和dx中值的值是否相等,计算bx-dx的值是否为0
        jz delay2                 ;若bx-dx的值为0,则继续跳转至delay2
        pop ax                    ;从栈顶取出数据送入ax
        ret                       ;用栈中的数据,修改IP的内容,从而实现近转移

delay endp                        ;结束子程序delay伪指令

;=========================子程序delay结束========================;

;========================子程序display开始=======================;

display proc near                 ;开始定义子程序diaplay的伪指令,NEAR属性为段内近调用,调用程序和子程序在同一代码段中,只能被相同代码段的其他程序调用

        push ax                   ;将寄存器ax中的数据送入栈中
        mov bx,offset led         ;bx为LED灯段码表led的首地址
        mov al,byte ptr key_in    ;将key_in中的内容送入al中
        sub al,30h                ;字符'0-9'所对应的ASCII码值为'30H-39H',故欲得到0~9的数值,只需用其ASCII码值减30H
        cmp al,09h                ;将al中的值与9进行比较,若等于9时则进行换码跳转dis2
        jng dis2                  ;跳转至dis2操作进行换码
        sub al,07h                ;字符'a-f'所对应的ASCII码值为'97H-102H',故欲得到a~f的数值,只需用其ASCII码值减07H

dis2:
        xlat                      ;换码指令,用于改变al中的数据
        mov dx,a8255              ;设置端口A,准备输出段码内容显示
        out dx,al                 ;输出显示数据,段码
        pop ax                    ;从栈顶取出数据送入ax
        ret                       ;用栈中的数据,修改IP的内容,从而实现近转移

display endp                      ;结束子程序display伪指令

;========================子程序display结束=======================;

code ends
end start

运行结果:

运行程序,按下薄膜键盘上的按键,数码管显示按键的值。效果如下图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 11
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jeron Zhou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值