微机系统 第九章 人机接口 (包含了第四章的题)
人机交互接口:
是用户与计算机进行交流的接口,即用户如何将信息输入计算机,计算机如何将处理后的信息告诉用户
键盘:
两种基本类型:编码键盘、非编码键盘。
• 编码键盘:
能够由硬件逻辑自动提供与被按键对应的ASCII码或其它编码。编码键盘中的某一键按下后,能够提供与该键相对应的编码信息。
• 非编码键盘:
仅仅简单地提供被按键行和列的矩阵,其它工作都靠程序实现,这样,非编码键盘就为系统软件在定义键盘的某些操作上提供了更大的灵活性。
对于非编码键盘,我们需要:
(1)清除键接触时产生的抖动干扰。
(2)防止键盘操作的重键错误。
(3)键盘的结构及被按键的识别。
(4)产生被按键相应的编码。
下面我们来一个一个的解决以上问题:
--消除抖动
抖动:抖动的产生是当机械开关的触点闭合时,在达到稳定之前需要短暂抖动或弹跳几下,即反复闭合、断开几次之后,才能达到可靠地闭合在一起。抖动也存在于开关断开时,其情形与开关闭合时相同
根据键的质量,抖动的时间可为10~20ms,会导致一次按键多次读入
解决办法:
硬件滤波:
对每一个键加上R-C滤波电路,或加上RS去抖电路。
软件去抖动技术:
采用20ms左右延迟子程序,等待键的输出达到完全稳定后才去读取代码
从按键连接方式,键盘分为:线性键盘、矩阵键盘
线性键盘:
线性键盘:采用独立式按键,直接用I/O口线构成单个按键电路
例题:
假设8255A的A口、B口、C口、控制口的端口地址分别是60H、61H、62H、63H,采用软件消抖技术(只考虑前沿消抖),编程实现对按键K3~K0的识别,假设按键K3~K0的对应编码为3~0,识别按键后,将对应的编码存到AH寄存器中。有D20ms延时子程序可以调用。
(初始化程序段+8255A)
(判断+延迟+真正取数)
依次判断按下的按键单个?(思路:是0?1?2?3?类似c的switch)
重键我们认为是缺省值,AH已经存储了我们的案件类型,A6可以跳转程序
进入是code->key->start,退出是key->code->start
矩阵键盘
又叫行列式键盘,用I/O口线组成行、列结构。按键设置在行列的交点上
扫描方式:行扫描法,线反转法。
行扫描法:
是步进扫描方式,每次向键盘的某一行发出扫描信号,同时通过检查列线的输出来确定闭合键的位置
例题:
假设行输出端口1的地址为200H,列输入端口2的地址为201H,采用软件消抖技术(只考虑前沿消抖),编程实现对0键~F键的识别,识别按键后,将按键的键号(即0~F)存到AH寄存器中,若为重键,则将0FFH存到AH寄存器中。有D20ms延时子程序可以调用。
一个字节的前4位是行号,后四位是列号
数据段:
下面是代码段:
两次检验判断是否抖动
扫描(xx0x)表示找第一行,AH是行号,AL是读取的列,如果列什么都没有就是(00001111)
(前行后列形成位置码)
从0->16查表,第几个存入到AH,A6是处理程序
线反转法:
键盘的工作方式
(1)程序控制扫描方式:这种方式是利用CPU工作的空余时间,调用键盘扫描子程序,响应键盘的输入请求。
(2)定时扫描方式:这种方式是利用定时器产生定时中断,CPU响应中断后对键盘进行扫描,并在有键按下时转入键功能处理程序。定时扫描方式在本质上是中断方式,但不是实时响应,而是定时响应。
(3)中断扫描方式:当应用系统工作时,并不经常需要键的输入,因此,无论键盘是工作于程控方式还是定时方式,CPU都经常处于空扫描状态。为了进一步提高CPU效率,可以采用中断扫描方式,当键盘上有键闭合时便产生中断请求,CPU响应中断,执行中断服务程序,对闭合键进行识别,并作相应的处理。
--PC键盘和接口
PC机的键盘都是非编码矩阵键盘
• 主要的键盘类型:
1)83键PC/XT键盘(已淘汰)(一般称作标准键盘)
2)84键PC/AT键盘(已淘汰)
3)101键键盘(386、486机型)
4)104键Windows键盘(Pentium机型)
5)108键Windows键盘:在104键盘的基础上又增加了Windows 98功能键Power(关机)、Sleep(休眠)、WakeUp(唤醒)和Fn组合键。
• 早期的PC机、PC/XT机和一些增强型扩展键盘使用的是5针电缆插,后来使用6针微型电缆插头,现在键盘多数使用USB接口。
PC键盘扫描码与键盘的对应关系: (83)
扫描码 :键盘输出的数据信号 (16位里面高8位是ascii,低8位才是扫描码)
但是**:在系统缓冲区中,高八位是扫描码,第八位才是ascii
)
扫描码反映键的位置和键的接通或断开状态。1个键的接通与断开分别输出接通扫描码和断开扫描码
标准键盘的扫描码用1个字节表示。接通扫描码是键号的二进制数,断开扫描码由接通扫描码的最高位置1形成。如f键的接通扫描码为21H,而断开扫描码为21H+80H=A1H。
增强型扩展键盘接口逻辑示意图
数据转换逻辑:键盘扫描码->系统扫描码->键盘缓冲区格式
从8259A->CPU,响应INT 9H
BIOS键盘中断及DOS键盘功能调用
BIOS键盘中断及DOS键盘功能调用有三种方式:
• 中断类型码09H
• 中断类型码16H
• 中断类型码21H
09H的处理过程
INT 9H:
向键盘缓冲区写入数据,写入队尾(大体)
(1)从键盘接口的输出缓冲寄存器(60H)读取系统扫描码。
(2)判断该键的分类,并写入键盘缓冲区队尾
• 键盘缓冲区:建立在系统主存的BIOS数据区中。
• 占用32个字节,可存放16次击键产生的ASCII码和扫描码。
• 以先进先出的方式工作,输入的键盘代码在其中形成循环队列。
• 中断09H输入的地址指针总指向队尾,从队尾写入数据
中断16H的功能
INT 16H:
读取键盘缓冲区的数据。
以先进先出的方式工作,INT 16H的输出指针总指向队首。
(--)AH=0
• 功能:从键盘读入字符送AL寄存器,当无键按下时,处于等待状态。
• 入口参数:AH=0
• 出口参数:AL中为键盘输入的字符的ASCII码值,AH中为扫描码。
(==)AH=1
• 功能:从键盘缓冲器中读入字符送给AL,并设置ZF标志,若按过任一键(即键盘缓冲区不空)置ZF=0,否则ZF=1。
• 入口参数:AH=1
• 出口参数:若ZF=0,则AL中为输入的字符的ASCII码。
• 由于该功能是从键盘缓冲区读数,当无键按下时,不等待,常通过检测
中断21H的功能
在DOS功能调用中,也有多个功能调用号用于获得所需要的键盘信息。常用的键盘操作功能如下:
(1)AH=1
• 功能:从键盘输入一个字符并回显在屏幕上。
入口参数:AH=1
出口参数:AL=字符
(2)AH=7
• 功能:从键盘输入一个字符,不回显。
入口参数:AH=7
出口参数:AL=字符
发光二极管显示器组成与显示方式
显示方式:静态显示、动态显示。
静态显示:
当显示器显示某一个字符时,相应的发光二极管恒定地导通或截止。
静态显示方式电路每一显示位可独立显示,在同一时刻不同的显示位可以显示不同的字
动态显示:
一位一位地轮流点亮各位显示器(扫描)。对于某一位显示器来说,每隔一段时间点亮一次
硬件译码,软件译码。
举例软件译码+静态显示:
设置8255A的工作方式:也就是链接控制口,
从A口输入,
BX 指向表首地址,XLAT 指令根据 AL 中的按键值(0~F),自动查表取出对应的段码
输出到端口b
200次延迟
继续读入下一个
软件译码动态显示接口:
-动态显示程序设计中显示程序的要点:
(1)解决显示译码问题,因为要显示的数字与其对应的段选码并没有有机的联系和转换规律,所以要用查表的方法完成这种译码功能。
(2)在进入显示程序之前,为保持显示的数据,专门开辟几个单元作为显示缓冲区,用以存放要显示的数字(十六进制数)
-采用软件译码方法一般有两种表格设置方案:
(1)顺序表格排列法,即按一定的顺序排列显示段码。通常显示的字形数据就是该段码在段码表中相对表头的偏移量。
(2)数据结构法,即按字形和段码的关系,自行设计一组数据结构。该方法设计灵活,但程序运行速度较慢
8 位七段发光二极管显示器接口电路
8个显示器重复显示(50次)8位十六进制数13579BDF的源程序
50外循环,8个内循环 输出B是显示的内容1->3.......,输出A是片选;+1递增
(这里的是阳极发光二极管)
assume关联code到cs,data到ds
AX装配DATA到DS
从1开始,选择最左边的通道
取出断码,送到B端口,取出位码送到A端口(A是选通,B是内容)
下一个断码,下一个位码(注意清空上位,)
停顿
判断是不是到了7F,如果没到,继续这轮循环,如果到了,就去判断是不是已经重复50次了
最后退出
题目:
给定字符串“Do not lose faith, as long as the unremittingly, you will get some fruits.”试以EXE程序结构编写只统计其中英文字母个数的程序。
DATA SEGMENTX DB 'Do not lose faith, as long as the unremittingly, you will get some fruits.$'N DW 0STR DB 0AH, 0DH, 'Valid Characters: $'
DATA ENDSCODE SEGMENTASSUME CS:CODE, DS:DATAMAIN PROC FARMOV AX, DATAMOV DS, AXCALL COUNT_CHARS ; 调用字符计数子程序CALL DISPLAY_RESULT ; 调用结果显示子程序MOV AH, 4CHINT 21H
MAIN ENDP; 子程序1:计数非标点字符(跳过',', ' ', '.')
COUNT_CHARS PROC NEARPUSH AXPUSH BXPUSH CXLEA BX, X ; BX指向字符串首地址XOR CX, CX ; 计数器清零NEXT_CHAR:MOV AL, [BX]CMP AL, '$' ; 遇到结束符则退出JE EXIT_COUNTCMP AL, ',' ; 跳过逗号JE SKIP_CHARCMP AL, ' ' ; 跳过空格JE SKIP_CHARCMP AL, '.' ; 跳过句号JE SKIP_CHARINC CX ; 有效字符计数加1SKIP_CHAR:INC BX ; 指向下一个字符JMP NEXT_CHAREXIT_COUNT:MOV N, CX ; 保存计数值到NPOP CXPOP BXPOP AXRET
COUNT_CHARS ENDP; 子程序2:显示计数结果(简化版,仅输出提示)
DISPLAY_RESULT PROC NEARPUSH AXPUSH DXLEA DX, STRMOV AH, 9INT 21H ; 输出提示字符串; 此处可扩展数值转ASCII并输出的逻辑(原代码未涉及)POP DXPOP AXRET
DISPLAY_RESULT ENDPCODE ENDS
END MAIN
(
INT 21H
- AH=01H:从键盘读字符并回显,结果存 AL。
- AH=02H:向屏幕输出 DL 中的字符。
- AH=06H:直接控制台输入 / 输出,DL=0FFH 时检查输入。
- AH=07H:无回显键盘输入,常用于密码场景。
- AH=09H:输出以
$
结尾的字符串(DS:DX 指向首地址)。 - AH=0AH:读取一行字符到缓冲区(需预先定义缓冲区格式)。
- AH=3CH-46H:文件操作(创建、打开、读写等)。
- AH=4CH:终止程序,AL 可设返回码。
)
试编写由键盘输入一个以回车(0x0D)作为结束的字符串,将其按ASCII码由大到小的顺序输出到显示器上的源程序。
DATA SEGMENTRESULT DB 100 DUP(1) ; 输入字符缓冲区N DB 0 ; 字符计数器PROMPT DB 0AH, 0DH, 'Input characters (Enter to sort):$'
DATA ENDSCODE SEGMENTASSUME CS:CODE, DS:DATAMAIN PROC FAR; 初始化数据段MOV AX, DATAMOV DS, AX; 显示输入提示CALL DISPLAY_PROMPT; 输入字符CALL INPUT_CHARS; 排序字符CALL SORT_CHARS; 显示排序结果CALL DISPLAY_RESULT; 退出程序MOV AH, 4CHINT 21H
MAIN ENDP; 子程序1:显示输入提示
DISPLAY_PROMPT PROC NEARPUSH DXLEA DX, PROMPTMOV AH, 9INT 21HPOP DXRET
DISPLAY_PROMPT ENDP; 子程序2:输入字符
INPUT_CHARS PROC NEARPUSH SIPUSH CXMOV CL, 0 ; 计数器清零LEA SI, RESULT ; SI指向缓冲区INPUT_LOOP:MOV AH, 1 ; 键盘输入INT 21HCMP AL, 0DH ; 检查是否按下回车JE INPUT_ENDMOV [SI], AL ; 保存字符到缓冲区INC SIINC CL ; 计数器加1JMP INPUT_LOOPINPUT_END:MOV N, CL ; 保存字符个数到NPOP CXPOP SIRET
INPUT_CHARS ENDP; 子程序3:排序字符(冒泡排序)
SORT_CHARS PROC NEARPUSH DXPUSH CXPUSH BXMOV DL, N ; DL = 字符个数DEC DX ; 外层循环次数 = 个数-1OUTER_LOOP:LEA BX, RESULT ; BX指向缓冲区首地址MOV CX, DX ; 内层循环次数 = 当前外层循环次数INNER_LOOP:MOV AL, [BX] ; 取当前字符CMP AL, [BX+1] ; 与下一个字符比较JNC NO_SWAP ; 若不小于则不交换; 交换字符XCHG AL, [BX+1]MOV [BX], ALNO_SWAP:INC BX ; 指向下一个字符LOOP INNER_LOOP ; 内层循环DEC DX ; 外层循环次数减1JNZ OUTER_LOOP ; 若未完成所有轮次,继续循环POP BXPOP CXPOP DXRET
SORT_CHARS ENDP; 子程序4:显示排序结果
DISPLAY_RESULT PROC NEARPUSH CXPUSH BXMOV CH, 0 ; CH清零MOV CL, N ; CL = 字符个数LEA BX, RESULT ; BX指向缓冲区首地址DISPLAY_LOOP:MOV DL, [BX] ; 取字符MOV AH, 2 ; 显示字符INT 21HINC BX ; 指向下一个字符LOOP DISPLAY_LOOP ; 循环直到显示所有字符POP BXPOP CXRET
DISPLAY_RESULT ENDPCODE ENDS
END MAIN
(10分)编写从键盘输入十进制数(0~99 范围),输入的十进制数值乘以 2 后,保存到变量 X 中,并以十进制方式输出显示 X 值的程序。要求以 EXE 源程序结构编写程序,并带有输入和输出的提示字符串。
显示举例:Please input two decimal number: 99
The result is: 198
.MODEL SMALL
.STACK 100H.DATAINPUT_PROMPT DB 'Please input a decimal number (0-99):$' ; 输入提示字符串OUTPUT_PROMPT DB 0DH, 0AH, 'The result after *2 is: $' ; 输出提示字符串X DB 0 ; 存储计算结果的变量.CODE
MAIN PROCMOV AX, @DATAMOV DS, AX ; 初始化数据段; 显示输入提示并读取数字CALL DISPLAY_INPUT_PROMPTCALL READ_DECIMAL_NUMBER; 数值乘以2并保存CALL MULTIPLY_BY_TWO; 显示结果CALL DISPLAY_RESULT; 退出程序MOV AH, 4CHINT 21H
MAIN ENDP; 子程序1:显示输入提示
DISPLAY_INPUT_PROMPT PROC NEARPUSH DXLEA DX, INPUT_PROMPTMOV AH, 09HINT 21HPOP DXRET
DISPLAY_INPUT_PROMPT ENDP; 子程序2:读取十进制数(0-99)
READ_DECIMAL_NUMBER PROC NEARPUSH AXPUSH BXPUSH CXMOV BL, 0 ; 存储十位数字MOV CL, 0 ; 存储个位数字; 读取十位数字MOV AH, 01HINT 21HCMP AL, 0DH ; 检查是否按下回车(非法输入)JE READ_ENDSUB AL, '0' ; 转换为数值(0-9)CMP AL, 9 ; 检查是否为有效数字JA READ_ENDMOV BL, AL; 读取个位数字MOV AH, 01HINT 21HCMP AL, 0DHJE READ_ENDSUB AL, '0'CMP AL, 9JA READ_ENDMOV CL, AL; 组合十位和个位为十进制数(0-99)MOV AL, BLMOV AH, 0MOV CL, 10MUL CL ; 十位*10ADD AL, CL ; 加上个位CMP AL, 99 ; 检查是否超过99JA READ_END ; 超过则不处理MOV X, AL ; 保存有效数值到X
READ_END:POP CXPOP BXPOP AXRET
READ_DECIMAL_NUMBER ENDP; 子程序3:数值乘以2
MULTIPLY_BY_TWO PROC NEARPUSH AXMOV AL, XADD AL, AL ; 乘以2MOV X, ALPOP AXRET
MULTIPLY_BY_TWO ENDP; 子程序4:显示结果(十进制)
DISPLAY_RESULT PROC NEARPUSH AXPUSH BXPUSH CXPUSH DXLEA DX, OUTPUT_PROMPTMOV AH, 09HINT 21H ; 显示输出提示MOV AL, XMOV BL, 10 ; 除数MOV CX, 0 ; 位数计数器; 分解数值并压栈
DIVIDE_LOOP:MOV AH, 0DIV BLPUSH AX ; 保存商和余数INC CXCMP AL, 0JNE DIVIDE_LOOP; 弹出并显示各位数字
DISPLAY_LOOP:POP AXMOV DL, AH ; 余数为当前位ADD DL, '0' ; 转换为ASCIIMOV AH, 02HINT 21HLOOP DISPLAY_LOOPPOP DXPOP CXPOP BXPOP AXRET
DISPLAY_RESULT ENDPEND MAIN
设从BUFFER开始存放若干个以$为结束标志的带符号字节数据,试编写将其中的正数按由大到小的顺序存入PLUS开始的缓冲区中的完整源程序。
(编程注意四个环节:段的定义;数据定义;提取带符号字节数据中的正数;由大到小排序。)
答:
找正数==>排序==>输出
DATA SEGMENTBUFFER DB 11H,12H,0FEH,0EAH,32H,0A3H,22H,14H,54H,0C3H,09H,45H,53H,37H,38H,'$'PLUS DB 15 DUP(0) ; 用于存储筛选出的正数STR DB 0AH,0DH,"PLUS==>$" ; 输出提示字符串
DATA ENDS
SUB1 PROC NEARPUSH AXPUSH BXLEA SI,PLUS ; SI指向PLUS缓冲区LEA BX,BUFFER ; BX指向源缓冲区XOR AX,AXXOR DX,DX ; DX用于计数正数个数AA1:MOV AL,[BX]CMP AL,24H ; 检查是否为结束标记$JZ AA3TEST AL,80H ; 测试最高位(符号位)JNZ AA2 ; 若为负数(最高位为1),跳转到AA2MOV [SI],AL ; 若为正数,存入PLUS缓冲区INC SIINC BXINC DX ; 正数计数器加1JMP AA1AA2:INC BX ; 跳过负数JMP AA1AA3: POP BXPOP AXRET
SUB1 ENDP
SUB2 PROC NEARPUSH DXDEC DX ; 排序次数为n-1(n为元素个数)L1: MOV CX,DXLEA BX,PLUS ; BX指向PLUS缓冲区L2: MOV AL,[BX]CMP AL,[BX+1] ; 比较当前元素与下一个元素JNC L3 ; 若当前元素≤下一个元素,不交换XCHG AL,[BX+1] ; 否则交换两个元素MOV [BX],ALL3: INC BX ; 指向下一对元素LOOP L2 ; 内层循环DEC DX ; 外层循环计数减1JNZ L1 ; 未完成所有轮次,继续循环POP DXRET
SUB2 ENDP
SUB4 PROC NEARPUSH AXPUSH CXPUSH DXMOV DL,[BX] ; 获取当前要输出的数MOV CL,4SHR DL,CL ; 右移4位,获取高4位OR DL,30H ; 转换为ASCII码(0-9)CMP DL,3AH ; 检查是否大于'9'JC BB1ADD DL,7 ; 如果是A-F,再加7(转换为大写字母)BB1: MOV AH,2INT 21H ; 输出高4位MOV DL,[BX]AND DL,0FH ; 获取低4位OR DL,30H ; 转换为ASCII码CMP DL,3AHJC BB2ADD DL,7 ; 如果是A-F,再加7BB2: MOV AH,2INT 21H ; 输出低4位MOV DL,48H ; 输出'H'表示十六进制INT 21HMOV DL,20H ; 输出空格分隔INT 21HPOP DXPOP CXPOP AXRET
SUB4 ENDP
注意十进制-==>16进制
CONVERT_LOOP:
MOV DX, 0 ; 清空 DX(用于 DIV 操作)
MOV BX, 16 ; 除数 16
DIV BX ; AX / 16 → AX = 商,DX = 余数
; 处理余数(0-15)→ 转换为 ASCII
CMP DX, 9
JBE NUMBER ; ≤9 直接加 30H
ADD DX, 7 ; >9 则加 37H(A-F)
NUMBER:
ADD DX, 30H ; 转换为 ASCII 码
PUSH DX ; 压栈保存(低位在前)
INC CX ; 位数计数器 + 1
CMP AX, 0 ; 商是否为 0?
JNE CONVERT_LOOP ; 不为 0 则继续分解
; 输出十六进制字符(从栈中弹出)
PRINT_LOOP:
POP DX ; 弹出栈顶元素(高位优先)
MOV AH, 2 ; DOS 功能调用:显示字符
INT 21H
LOOP PRINT_LOOP ; 循环直到所有位输出完毕
找最大/小值,如需要,可以用一个pos记录位置
DATA SEGMENTARRAY DB 80 DUP(?) ; 定义80个元素的数组MAX DB ? ; 存储最大值
DATA ENDSCODE SEGMENTASSUME CS:CODE, DS:DATAMAIN PROC FARMOV AX, DATAMOV DS, AX ; 初始化数据段; 初始化最大值为数组第一个元素LEA SI, ARRAYMOV AL, [SI]MOV MAX, AL; 遍历数组寻找最大值MOV CX, 79 ; 剩余79个元素
NEXT:INC SICMP AL, [SI] ; 比较当前元素与最大值JGE CONTINUE ; 如果≥则继续MOV AL, [SI] ; 否则更新最大值MOV MAX, AL
CONTINUE:LOOP NEXT; 程序结束MOV AH, 4CHINT 21H
MAIN ENDP
CODE ENDS
END MAIN
DATA SEGMENTARRAY DB 100 DUP(?) ; 定义100个元素的数组SUM DW ? ; 存储总和(16位)AVG DB ? ; 存储平均值POS DB ? ; 存储最接近平均值的位置
DATA ENDSCODE SEGMENTASSUME CS:CODE, DS:DATAMAIN PROC FARMOV AX, DATAMOV DS, AX ; 初始化数据段; 初始化总和为0MOV AX, 0MOV SUM, AX; 计算总和LEA SI, ARRAYMOV CX, 100
SUM_LOOP:ADD AL, [SI]ADC AH, 0 ; 处理进位INC SILOOP SUM_LOOPMOV SUM, AX ; 保存总和; 计算平均值(除以100)MOV AX, SUMMOV BL, 100DIV BL ; AL=商(平均值), AH=余数MOV AVG, AL; 寻找最接近平均值的元素及其位置LEA SI, ARRAYMOV CX, 100MOV BL, 0 ; 当前位置MOV AL, [SI] ; 第一个元素MOV DL, AL ; 暂存最接近值MOV POS, 0 ; 初始位置为0FIND_NEXT:MOV AL, [SI]CMP AL, AVG ; 比较当前元素与平均值JGE CALC_HIGH; 当前元素<平均值MOV AH, AVGSUB AH, AL ; 计算差值JMP COMPARE
CALC_HIGH:; 当前元素≥平均值SUB AL, AVG ; 计算差值
COMPARE:MOV AH, DLCMP AH, AVG ; 比较暂存值与平均值JGE CHECK_LOW; 暂存值≥平均值SUB AH, AVG ; 计算差值JMP CHECK_DIFF
CHECK_LOW:; 暂存值<平均值MOV AH, AVGSUB AH, DL ; 计算差值
CHECK_DIFF:CMP AL, AH ; 比较当前差值与暂存差值JGE NEXT_ELEMENT ; 如果当前差值≥暂存差值,则不更新MOV DL, [SI] ; 否则更新最接近值MOV POS, BL ; 更新位置
NEXT_ELEMENT:INC SIINC BLLOOP FIND_NEXT; 程序结束MOV AH, 4CHINT 21H
MAIN ENDP
CODE ENDS
END MAIN
什么是键盘的行扫描法和线反转法?其实现过程有哪些区别?
行扫描法是步进扫描方式,行输出,列输入。每次输出的值中只有一位是0,其它都是1,每次输出的0位置是移动的,以低电平扫描行输出。
每扫描输出一行,同时通过检查列线的输入, 如果输入是全1,说明本行没有按键,则输出下一个行扫描值, 再进行检查列输入值,如果输入值不是全1, 则当前行扫描值对应的非0的行有按键,当前列值非0对应列有按键,由此时的行值和列值可以定出按键的位置。
线反转法
- 第一次扫描(行输出、列输入):
- 将所有行线设为输出模式并置低电平,列线设为输入模式。
- 若某列输入为低电平,说明该列存在按键按下。
- 第二次扫描(列输出、行输入):
- 将所有列线设为输出模式并置低电平,行线设为输入模式。
- 若某行输入为低电平,说明该行存在按键按下。
- 交叉定位:结合两次扫描的行号和列号,确定具体按键位置。
行扫描法只要求行输出,列输入,接口简单,但是软件复杂;线反转法要求接口具有方向可变功能,硬件复杂,而软件实现简单。
设有14个按键组成矩阵键盘,识别这14个按键最少需要(B)根线。 4+4
A. 14 B.8 C. 7 D. 6
键盘行扫描法与线反转法的原理及区别
行扫描法(逐行扫描法)
原理:通过逐行输出低电平,检测列线输入状态来定位按键位置。
实现过程:
- 硬件连接:行线接输出端口,列线接输入端口。
- 扫描过程:
- 逐行输出低电平(如第一行输出 0,其余行输出 1);
- 读取列线状态,若某列输入为低电平,说明该行该列交叉处有按键按下;
- 若所有列输入为高电平,继续扫描下一行,直到找到按键或扫描完所有行。
线反转法(两次扫描法)
原理:通过两次 I/O 方向反转,结合行列电平状态定位按键。
实现过程:
- 第一次扫描(行输出、列输入):
- 行线输出全 0,列线读取状态,若某列输入为 0,记录该列值;
- 第二次扫描(列输出、行输入):
- 列线输出第一次读取的列值,行线读取状态,若某行输入为 0,记录该行值;
- 交叉定位:行值和列值的交点即为按键位置
LED 显示器工作原理与类型
工作原理
LED(发光二极管)通过正向偏置导通发光,多个 LED 组成段码(如 7 段码),通过控制各段的通断显示数字或字符。
- 段选线:控制每个 LED 段的通断(如 a、b、c 段);
- 位选线:控制多个 LED 中哪一个被点亮(多位显示时)
类型 | 公共极连接 | 段引脚点亮条件 | 应用场景小细节 |
---|---|---|---|
共阴极 | 阴极 → GND | 段引脚 → 高电平 | 适合与输出高电平有效的电路(如直接接 MCU 引脚) |
共阳极 | 阳极 → +5V | 段引脚 → 低电平 | 适合与输出低电平有效的电路(如译码器、驱动芯片) |
LED 显示器接口方式

8255A 控制两位 LED 动态显示接口设计(困困,不写了,3点了,唉)