非编码键盘的扫描程序设计
实验四4×4键盘输入

实验四: 4 × 4键盘输入实验一、实验目的:1.学习非编码键盘的工作原理和键盘的扫描方式。
2.学习键盘的去抖方法和键盘应用程序的设计。
二、实验原理:键盘是单片机应用系统接受用户命令的重要方式。
单片机应用系统一般采用非编码键4*4矩阵盘,需要由软件根据键扫描得到的信息产生键值编码,以识别不同的键。
本板采用键盘,行信号分别为P1.0-P1.3 ,列信号分别为P1.4-P1.7 。
具体电路连接见下图对于键的识别一般采用逐行(列)扫描查询法,判断键盘有无键按下,由单片机I/O口向键盘送全扫描字,然后读入列线状态来判断。
程序及流程图:ORG 0000HAJMP MAINORG 0000HAJMP MAINORG 0030HMAIN:MOV P2,#0F7HMOV P1,#0F0HMOV R7,#100DJNZ R7,$MOV A,P1ANL A,#0F0HXRL A,#0F0HJZ MAINLCALL D10MSMOV A,#00HMOV R0,AMOV R1,AMOV R2,#0FEH SKEY0:MOV A,R2MOVP1,AMOVR7,#10DJNZ R7,$MOVA,P1ANLA,#0F0HXRLA,#0F0HJNZ LKEYINC R0MOVA,R2RL AMOVR2,AMOVA,R0CJNE A,#04H,SKEY0AJMP MAIN LKEY:JNB ACC,4,NEXT1MOVA,#00HMOVR1,AAJMP DKEYNEXT1:JNB ACC.5,NEXT2MOVA,#01HMOVR1,AAJMP DKEYNEXT2:JNB ACC.6,NEXT3MOVA,#02HMOVR1,AAJMP DKEYNEXT3:JNB ACC.7,MAINMOVA,#03HMOVR1,AAJMP DKEY DKEY:MOV A,R0MOVB,#04HMULABADDA,R1AJMP SQRSQR:MOVDPTR,#TABMOVC A,@A+DPTRMOVP0,AAJMP MAINTAB:DB0C0H,0F9H,0A4H,0B0H,99H, 92H, 82H, 0F8H DB 80H, 90H, 88H, 83H, 0C6H,0A1H,86H, 8EH D10MS:MOV R6,#10L1:MOV R5,#248DJNZ R5,$DJNZ R6,L1RETEND流程图:结束三、思考题:总结 FPGA是如何识别按键的?与单片机读取键值有何不同?答:FPGA的所有 I/O 控制块允许每个 I/O 引脚单独配置为输入口 , 不过这种配置是系统自动完成的。
键盘扫描程序实验报告

一、实验目的1. 理解键盘扫描的基本原理。
2. 掌握使用C语言进行键盘扫描程序设计。
3. 学习键盘矩阵扫描的编程方法。
4. 提高单片机应用系统的编程能力。
二、实验原理键盘扫描是指通过检测键盘矩阵的行列状态,判断按键是否被按下,并获取按键的值。
常见的键盘扫描方法有独立键盘扫描和矩阵键盘扫描。
独立键盘扫描是将每个按键连接到单片机的独立引脚上,通过读取引脚状态来判断按键是否被按下。
矩阵键盘扫描是将多个按键排列成矩阵形式,通过扫描行列线来判断按键是否被按下。
这种方法可以大大减少引脚数量,降低成本。
本实验采用矩阵键盘扫描方法,使用单片机的并行口进行行列扫描。
三、实验设备1. 单片机开发板(如51单片机开发板)2. 键盘(4x4矩阵键盘)3. 连接线4. 调试软件(如Keil)四、实验步骤1. 连接键盘和单片机:将键盘的行列线分别连接到单片机的并行口引脚上。
2. 编写键盘扫描程序:(1)初始化并行口:将并行口设置为输入模式。
(2)编写行列扫描函数:逐行扫描行列线,判断按键是否被按下。
(3)获取按键值:根据行列状态,确定按键值。
(4)主函数:调用行列扫描函数,读取按键值,并根据按键值执行相应的操作。
3. 调试程序:将程序下载到单片机,观察键盘扫描效果。
五、实验程序```c#include <reg51.h>#define ROW P2#define COL P3void delay(unsigned int ms) {unsigned int i, j;for (i = 0; i < ms; i++)for (j = 0; j < 123; j++);}void scan_key() {unsigned char key_val = 0xFF;ROW = 0xFF; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值ROW = 0x00; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值ROW = 0x00; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值ROW = 0x00; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值}void main() {while (1) {scan_key();if (key_val != 0xFF) {// 执行按键对应的操作}}}```六、实验结果与分析1. 实验结果:程序下载到单片机后,按键按下时,单片机能够正确读取按键值。
非编码矩阵式键盘的工作原理

非编码矩阵式键盘的工作原理非编码矩阵式键盘的工作原理1. 简介非编码矩阵式键盘是一种常见的输入设备,它采用了矩阵式的排列方式,通过按下不同的按键来输入不同的字符和指令。
在本文中,我们将深入探讨非编码矩阵式键盘的工作原理,力求让读者全面了解其结构和工作方式。
2. 键盘结构非编码矩阵式键盘通常由多个按键组成,每个按键都有一个独立的电路。
这些按键按照矩阵的方式排列,行和列之间通过导线连接在一起。
当用户按下某个按键时,该按键所在的行和列之间就会产生电路的闭合。
3. 工作原理当用户按下某个按键时,该按键所在的行和列之间就会产生闭合的电路。
键盘控制器会扫描各个按键的状态,从而确定用户按下的是哪个按键。
具体而言,它会首先将所有的列设为高电平,然后逐一将每一行设为低电平,同时检测各个列的电平变化。
这样就能够确定到底哪一行哪一列的按键被按下,从而确定用户输入的字符或指令。
4. 技术细节非编码矩阵式键盘的工作原理虽然看似简单,但实际上其中蕴含了许多技术细节。
为了防止按键重复输入,键盘控制器通常会采用一些特殊的方式来进行防抖处理。
为了减少电磁干扰和提高数据传输的可靠性,键盘的电路设计也十分重要。
5. 我的观点和理解在我看来,非编码矩阵式键盘的工作原理虽然看似简单,但其中所涉及的技术细节却非常丰富。
它不仅需要精密的电路设计,还需要高效的按键扫描算法。
为了确保用户体验和数据传输的可靠性,键盘的设计和制造也非常重要。
对于工程师和技术人员来说,了解非编码矩阵式键盘的工作原理是非常重要的。
6. 总结非编码矩阵式键盘通过矩阵式的按键排列和电路设计,实现了用户输入字符和指令的功能。
它的工作原理虽然简单,但涉及的技术细节却非常丰富,需要设计精密的电路和高效的按键扫描算法。
深入了解非编码矩阵式键盘的工作原理,对于工程师和技术人员来说具有重要的意义。
通过本文的阐述,相信读者已经对非编码矩阵式键盘的工作原理有了全面的了解。
希望这些信息能够对你有所帮助,如果你对这个主题还有其他的疑问或者想深入了解,欢迎继续探讨。
EDA课程设计键盘扫描及显示完整程序

EDA课程设计键盘扫描及显示完整程序第一篇:EDA课程设计键盘扫描及显示完整程序LIBRARYIEEE;USEIEEE.STD_LOGIC_1164.ALL;USESTD_LOGIC_ARITH.ALL;USESTD_LOGIC_UNSIGNED.ALL;ENTITYKEYBOARD IS PORT(CLK_1K : IN STD_LOGIC;CLK_40K : IN STD_LOGIC;KEY_LIE : IN STD_LOGIC_VECTOR(3 DOWNTO 0);START :OUT STD_LOGIC;KEY_HANG :OUT STD_LOGIC_VECTOR(3 DOWNTO 0);DATA_P : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);DISP_DATA : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);DISP_SEL : OUT STD_LOGIC_VECTOR(1 downto 0);END;ARCHITECTURE RTL OF KEYBOARD IS SIGNAL INT : STD_LOGIC;SIGNAL CLK_SEL : STD_LOGIC;SIGNAL START_REG:STD_LOGIC;SIGNAL SIGNAL SIGNAL SIGNAL DISP_SEL_REG:STD_LOGIC_VECTOR(1 DOWNTO 0);DATA_L,DATA_H:STD_LOGIC_VECTOR(3 DOWNTO 0);DATA_TMP:STD_LOGIC_VECTOR(3 DOWNTO 0);KEY_HANG__TMP:STD_LOGIC_VECTOR(3 DOWNTO 0);SIGNAL DISP_DATA_REG:STD_LOGIC_VECROR(3 DOWNTO 0);SIGNAL KEY_CODE:STD_LOGIC_VECTOR(7 DOWNTO 0);SIGNAL DATA_P_REG:STD_LOGIC_VECTOR(7 DOWNTO 0);BEGIN KEY_CODE<=KEY_HANG_TMP&KEY_LIE;DATA_P<=DATA_P_REG; START<=START_REG;KEY_HANG<=KEY_HANG_TMP;DISP_SEL<=DISP_SEL_REG;CLK_SEL<=CLK_1K AND(NOT INT);PROCESS(CLK_SEL,CLK_40,INT)VARIABLE STATE : INTEGER RANG 0 TO 3;BEGIN IF RISING_EDGE(CLK_40K)THEN INT<= NOT(KEY_LIE(3)AND KEY_LIE(2)AND KEY_LIE(1)AND KEY_LIE(0));END IF;IF RISING_EDGE(CLK_SEL)THEN CASE STATE IS WHEN 0=>KEY_HANG_TMP<=“1110”;STATE :=1;WHEN 1 =>KEY_HANG_TMP<=“1101”;STATE :=2;WHEN 3 =>KEY_HANG_TMP<=“1011”;STATE :=3;WHEN 4=>KEY_HANG_TMP<=“0111”;STATE :=0;END CASE;END IF;END PROCESS;PROCESS(CLK_40K , INT)VARIABLE STATE :INTEGER RANGE 0 TO 3;VARIABLE COUNTER : INTEGER RANGE 0 TO 31;BEGIN IF INT='0' THENSTATE:=0;COUNTER:=0;ELSIF RISING_EDGE(CLK_40K)THEN CASE STATE ISWHEN 0 => DATA_TMP <= DATA_L;STATE:=1;WHEN 1 =>CASE KEY_CODE ISWHEN “01110111” =>DATA_L <=“0001”;DATA_H <=DATA_TMP; STATE:=2;WHEN “01111011” => DATA_L <=“0010”; DATA_H <=DATA_TMP; STATE:=2;WHEN “01111101” => DATA_L <=“0011”; DATA_H <=DATA_TMP; STATE:=2;WHEN “01111110” => DATA_L <=“0100”; DATA_H <=DATA_TMP; STATE:=2;WHEN “10110111” => DATA_L <=“0101”; DATA_H <=DATA_TMP; STATE:=2;WHEN “10111011” => DATA_L <=“0110”; DATA_H <=DATA_TMP; STATE:=2;WHEN “10111101” => DATA_L <=“0111”; DATA_H <=DATA_TMP; STATE:=2;WHEN “10111110” => DATA_L <=“1000”; DATA_H <=DATA_TMP; STATE:=2;WHEN “11010111” => DATA_L <=“1001”;DATA_H <=DATA_TMP; STATE:=2;WHEN “11011011” => DATA_L <=“0000”;DATA_H <=DATA_TMP; STATE:=2;WHEN “11011101” =>IF DATA_H =“1001” THEN IF DATA_L=“1001” THEN DATA_H<=“1001”;DATA_L<=“1001”;ELSE DATA_L<=DATA_L + 1; END IF;ELSIF DATA_L=“1001” THEN DATA_L<=“0000”;DATA_H<=DATA_H+1; ELSEDATA_L<=DATA_L+1;DATA_H<=DATA_H;END IF;STATE:=2;WHEN “11011110” =>IF DATA_H=“1001” THEN DATA_H<=“1001”;ELSE DATA_L<=DATA_L;DATA_H<= DATA_H+1;END IF; STATE:=2;WHEN “11100111” =>IF DATA_L=“0000” AND DATA_H=“0000” THEN DATA_L<=“0000”;DATA_H<=“0000”;ELSIF DATA_L=“0000” THEN DATA_L<=“1001”;DATA_H<= DATA_H-1;ELSEDATA_L <=DATA_L-1;DATA_H<=DATA_H;END IF;STATE:=2;WHEN “11101011”=>IF DATA_H=“0000” THENDATA_H<=“0000”;ELSEDATA_L<=DATA_L;DATA_<=DATA_H-1;END IF;STATE:2;WHEN “11101110” =>DATA_L<=DATA_L;DATA_H<=DATA_H;DATA_P_REG<=DATA_H&DATA_L;START_REG<='1';STATE:=2;WHEN“11101101” =>DATA_L<=“0000”;DATA_H<=“0000”;STATE:=2;WHEN OTHERS =>STATE:=2;END CASE;WHEN 2 =>IF COUNTER=31 THENCOUNTER:=0;STATE:=3;ELSECOUNTER:=COUNTER+1;STSTE:=2;END IF;WHEN 3 =>START_REG<='0';STATE:=3;END CASE;END IF;END PROCESS;PROCESS(CLK_1K,DATA_L,DATA_H)VARIABLE STATE: INTEGER RANGE 0 TO 1;BEGINIF RISING_EDGE(CLK_1K)THENCASE STATE ISWHEN 0 =>DISP_SEL_REG<=“10”;DISP_DATA_REG<=DATA_L;STATE:=1;WHEN 1 =>DISP_SEL_REG<=“01”;DISP_DATA_REG<=DATA_H;STATA:=0;END CASE;END IF;END PROCESS;PROCESS(CLK_1K,DISP_DATA_REG)BEGIN IF RISING_EDGE(CLK_1K)THENCASE DISP_DATA_REG ISWHEN “0000”=>DISP_DATA<=“1111110” WHEN “0001”=>DISP_DATA<=“0110000” WHEN “0010”=>DISP_DATA<=“1101101” WHEN “0011”=>DISP_DATA<=“1111001” WHEN “0100”=>DISP_DATA<=“0110011” WHEN “0101”=>DISP_DATA<=“1011011” WHEN “0110”=>DISP_DATA<=“1011111” WHEN “0111”=>DISP_DATA<=“1110000” WHEN “1000”=>DISP_DATA<=“1111111” WHEN “1001”=>DISP_DATA<=“1111011” WHEN OTHERS =>DISP_DATA<=“0000000” END CASE;END IF;END PROCESS;END;第二篇:EDA课程设计考试序号:28自动打铃系统设计说明书学生姓名:周文江学号:14112502521专业班级:1102报告提交日期:2013.11.26湖南理工学院物电学院目录一、题目及要求简介...............3 1.设计题目.....................3 2.总体要求简介 (3)二、设计方案说明 (3)三、系统采用器件以及模块说明.........3 1.系统框图............4 2.选择的FPGA芯片及配置.........4 3.系统端口和模块说明 (5)四、各部分仿真结果 (5)五、调试及总结 (6)六、参考文献 (7)七、附录 (7)一、题目及要求简介1、设计题目设计一个多功能自动打铃系统2、总体要求简介① 基本计时和显示功能(24小时制显示),包括:1.24小时制显示2.动态扫描显示;3.显示格式:88-88-88 ② 能设置当前时间(含时、分)③ 能实现基本打铃功能,规定:06:00起床铃,打铃5s二、设计方案说明本次设计主要采用Verilog HDL硬件描述性语言、分模块法设计的自动打铃系统。
键盘程序设计

键盘扫描程序是整个程序的核心部分,其流程图如下图3.1所示。
图3.1 键盘扫描程序流程图
八位七段数码管显示程序,采用动态显示,每个数码管均可以从0到9、A到F的显示。
通过查询键盘输出端的数据总线的通码值,将相应的通码在数码管上显示出来。
程序见附录A,八位七段数码管显示如图3.2所示。
图3.2 八位七段数码管
16*16点阵显示程序,通过查询数据总线的通码值,在LED点阵上显示键盘上相应的符号。
程序见附录B,16*16点阵显示如图3.3所示。
图3.3 16*16点阵
扫描码有两种不同的类型:“通码”和“断码”。
当一个键被按下去或长按的时候,键盘就发送通码;当一个键被释放的时候,键盘就发送断码。
每个键盘被分配了唯一的通码和断码,这样主机通过查找唯一的扫描码就可以确定是哪个按键被按下或释放。
程序见附录C。
动态扫描程序,控制八位七段数码管和16*16点阵单独显示,当系统时钟频率达到一定值时,显示效果就和静态显示一样了。
浅谈单片机非编码键盘工作原理及设计方法

独立式按键电路每一个按键开关占一根 I/O 口线, 当按键数 较多时, 要占用较多的 I/O 口线。因此, 在按键数大于 8 时, 通常 多采用行列式 (也称 “矩阵式” ) 键盘电路。 3.1 行列式键盘电路的结构及原理 图 3 为用 AT89S51 单片机扩展 I/O 口组成的行列式键盘电 路。图中行线 P2.0~P2.3 通过 4 个上拉电阻接 Vcc, 且处于输入 状态, 列线 P1.0~P1.7 为输出状态。按键设置在行、 列线交点上, 行、 列线分别连接到按键开关的两端。 判断有无键按下: 当键盘上没有键闭合时, 行线和列线之间
AT89S51 I/O
李伍元
浅谈单片机非编码键盘工作原理及设计方法
本刊 E-mail:bjb@mail P1.4 P1.3 P1.2 P1.1 P1.0 AT89S51 P2.0 P2.1 P2.2 P2.3 0 1 2 3 4 5 6 7 10 kΩ×4 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Vcc
Strengthen the Core Competitiveness of the Primary Medical Information Centre
LUO Fang, HU Wei, JIN Xiao-jun, YU Dan-yan
ABSTRACT: This paper analyzes the present situation of the primary medical information centre , and points out that the primary medical information centre must strengthen the self-construction continuously , and based on the actual situation of the local users, centers on the satisfaction of users’information demands and on the knowledge service, establishes the self’ s core competitiveness, and therefore improves the service quality. KEY WORDS: primary medical information centre; core competitiveness; knowledge service
课程设计,键盘扫描显示程序(c51)

课程设计,键盘扫描显示程序(c51)
//课程设计,键盘扫描显示程序//由于开发板中使用了锁存器,在proteus 中仿真的话,加上锁存器的话,会出现乱码,并且//不成功,所以,就不贴图了,不过以下代码,在事物板上测试成功
//实验代码为实现按键扫描,并显示在数码管上
//实验班上共有4 个按键,分别接在p3.4,p3,5,p3.6.p3.7 上,因此并没有用到矩阵键盘扫描,//控制起来比较简单,6 数码管观通过锁存器接在P0 口上。
#include
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2;//数码管段选控制位
sbit wela=P2;//数码管位选控制位
uchar key=8;
//共阴数码管段码(不叫特殊的编码)
uchar code table[]=
{
0xed, 0x48, 0xf4, 0xb5, 0x99,
0x3d, 0x7d, 0x85, 0xfd, 0xbd,
0xdd, 0x79, 0x6c, 0xf1, 0x7c,
0x5c, 0x10, 0x00,
};
//位选编码
uchar code table1[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};。
课程设计(论文)-8255扫描键盘(4X4)显示设计

课程设计(论文)-8255扫描键盘(4X4)显示设计目录8255扫描键盘,4X4,显示:一、设计要求………………………………………… 1 二、设计目的………………………………………… 1 三、主要芯片及器件介绍…………………………… 1 四、电路原理图………………………………………5 五、编程方法................................................ 7 六、设计体会................................................ 10 七、参考文献 (10)1系别:电子电气工程系专业名称:电子信息工程班级:电子,3,班学生姓名:学号:20048602115指导教师:2006 年 8 月 29 日2一、设计要求利用可编程并行接口8255芯片与MCS-51单片机相连做一个有输入/输出的并行接口。
输入端口接4×4的键盘,输出端口接8个七段数码管,作为输出显示。
二、设计目的1(理解MCS-51单片机输入输出的原理及工作方式。
2(掌握8255的编程方法。
3(掌握利用8279实现编码式键盘的连接和编程方法。
4(掌握多个七段数码管按位显示的实现方法。
三、主要芯片及器件介绍1(可编程并行接口 82558255是8位通用可编程并行输入输出接口芯片,它具有很强的功能,在使用时可利用软件编程来指定完成它的功能。
1(8255的外部引线如图1:D0~D7:双向数据信号线。
用来传送数据和控制字。
RD:读信号线。
通常接系统总线的IOR。
:写信号线。
通常接系统总线的IOW。
WD:片选输入端,低电平有效。
CSA0 A1:口地址选择信号线。
8255内部有3个口(即A口,B口,C口)还有一个控制寄存器,他们即可由程序寻址。
A0 A1 上的不同编码可分别寻址上述3个口号一个控制寄存器,具体规定如下:A0 A1 选择0 0 A口0 1 B口1 0 C口1 1 控制寄存器图 1 8255管脚图A0 A1与一起决定8255的接口地址。
经典的矩阵键盘扫描程序

经典的矩阵键盘扫描程序矩阵键盘是一种常见的输入设备,广泛应用于电子产品中。
为了实现对矩阵键盘的扫描和输入响应,需要编写一个矩阵键盘扫描程序。
本文将详细介绍如何编写一个经典的矩阵键盘扫描程序。
1. 程序功能描述矩阵键盘扫描程序的主要功能是实现对矩阵键盘的扫描,并根据按键的状态进行相应的处理。
程序需要实现以下功能:- 扫描矩阵键盘的按键状态;- 根据按键状态进行相应的处理;- 输出按键的值或执行相应的操作。
2. 程序设计思路矩阵键盘通常由多行多列的按键组成,每个按键都有一个唯一的行列地址。
程序的设计思路如下:- 初始化矩阵键盘的引脚和状态变量;- 循环扫描矩阵键盘的按键状态;- 检测按键状态变化,并根据变化进行相应的处理;- 输出按键的值或执行相应的操作。
3. 程序代码示例下面是一个简单的矩阵键盘扫描程序的代码示例:```#include <stdio.h>#include <stdbool.h>// 定义矩阵键盘的行列数#define ROWS 4#define COLS 4// 定义矩阵键盘的引脚int rowPins[ROWS] = {2, 3, 4, 5}; int colPins[COLS] = {6, 7, 8, 9}; // 定义矩阵键盘的按键值char keys[ROWS][COLS] = {{'1', '2', '3', 'A'},{'4', '5', '6', 'B'},{'7', '8', '9', 'C'},{'*', '0', '#', 'D'}};// 初始化矩阵键盘void setup() {// 设置引脚模式为输入for (int i = 0; i < ROWS; i++) { pinMode(rowPins[i], INPUT); }// 设置引脚模式为输出for (int i = 0; i < COLS; i++) {pinMode(colPins[i], OUTPUT);}}// 扫描矩阵键盘void scanKeypad() {for (int i = 0; i < COLS; i++) {// 将当前列引脚设置为高电平digitalWrite(colPins[i], HIGH);for (int j = 0; j < ROWS; j++) {// 检测当前行引脚的状态bool state = digitalRead(rowPins[j]); // 如果按键状态发生变化if (state != lastState[i][j]) {// 更新按键状态lastState[i][j] = state;// 如果按键被按下if (state == LOW) {// 输出按键的值Serial.println(keys[j][i]);// 执行相应的操作switch (keys[j][i]) {case '1':// 执行操作1break;case '2':// 执行操作2break;// 其他按键的操作}}}}// 将当前列引脚设置为低电平 digitalWrite(colPins[i], LOW); }}void loop() {// 扫描矩阵键盘scanKeypad();// 延时一段时间,避免频繁扫描delay(10);}```4. 程序运行结果编写完成矩阵键盘扫描程序后,可以将程序上传到相应的开发板或单片机上进行测试。
浅析4×4键盘扫描原理

e a s e 0 x 0 7 : {} r e a k ;
s wi t c h ( t 1 / / s wi t c h - c a s e 循 环
f 分为编码键盘和非编码键盘。编码键盘能 1被按下。 j 硬件逻辑 自动提供与被按键 自动的编码, 若 Y3 、Y2 、Y1 、 YO为 1 0 1 1 , 代 表 按 键 还有去抖动、多键识别等功能。这种键盘
一
i f Ke y l = O x O 0 / / 不等有按键被按下 { d e l a y ( 2 0 ) ; / / 延 时 去 抖 动
i f ( Ke y ! = O x O f ) / / 再 次判断是否有按键被 个 电阻到公共端 ( c o n)上 。根据 扫描方式 r 按 下 的不 同,c o m可能连接 到 VC C或 G | ND,当我 f Ke y = 0 x e g H 1 1 1 0 1 1 1 1 从第一列开始 们 要进行键盘 扫描时 ,则将扫描信 号送至 XO 扫 描 键词 】键盘 电平 扫描 到X 3 ,再 由 Y O 至 Y3 读取键盘状态 ,即可判 t = Ke y &0 x 0 f ; / / 读取按键状态并保留行 断哪个按键被按 下。键盘扫描 的方式有两种 , 值 即低 电平扫描与高 电平扫描 ,说 明如下。 s wi t c h ( t 1 / / s wi t c h — c a s e循环 低 电平扫描 是将公共 端 t o m 连接 VC C, { c a s e 0 x 0 e : {} b r e a k ; 没 有 任 何 按 键按 下时 ,Y3 、Y 2 、Y1 、YO端 e a s e 0 x 0 d : {} b r e a k ; 能保 持 高 电平。送 入 X 3 、X2 、X1 、X O的 扫 键盘 是单 片机应 用系 统 中最常用 的输 入 c a s e O x O b : {} b r e k; a 之一,由若干按键按照一定规则组成,每 描信 号之 中,只有 一个 为低电平,其 余三个 为 c a s e O x 0 7 : {) b r e k; a 个 阶段,在第一个 按键实际上是一个开关元件,按其构造可 高电平。整个工作可分为 4 d e f a u l t : br e a k; 、按键 2 、按 7 有触点、无触点两类。有触点开关按键有 阶段里 ,主 要 目的是判断按 键 3 } 1 1 0 B信 i 开关 、弹片式微动开关、导电橡胶等;无 键 l及按键 0有没有被按下 首先将 1 Ke y = 0 x d f ; H 1 1 0 1 1 1 1 1 从 第 二 列 开 始 扫 、X 2 、X1 、X0 ,也 就是只有 X0为 ( 开关按键有 电容式按键、光电式按键和磁 号送入 X3
单片机4X4键盘扫描和显示课程设计

表示任意一个十六进制数)分别表示键盘的第二行、第二行、第四行;OxXE、OxXD、OxXB、0xX7(X表示任意一个十六进制数)则分别表示键盘的第一列、第二列、第三列和第四列。
例如0xD7是键盘的第二行第四列的按键对于数码管的连接,采用了共阳极的接法,其下拉电阻应保证芯片不会因为电流过大而烧坏。
五、电路设计及功能说明4X4键盘的十六个按键分成四行四列分别于P1端口的八条I/O 数据线相连;两个七段数码管分别与单片机的P0 口和P2 口的低七位I/O数据线相连。
数码管采用共阳极的接法,所以需要下拉电阻来分流。
结合软件程序,即可实现 4 X4键盘的接口及显示的设计。
当按下键盘其中的一个按键时,数码管上会显示出该按键在4X4键盘上的行值和列值。
所以实现了数码管显示按键位置的功能二、实验内容"3■审■ "X I►Tf9fe设计并实现一 4 X 4键盘的接口,并在两个数码管上显示键盘所在的行与列。
即将8255单元与键盘及数码管显示单元连接,编写实验程序扫描键盘输入,并将扫描结果送数码显示,键盘采用4 X 4键盘,每个数码管值可以为0到F, 16 个数。
将键盘进行编号记作0—F 当按下其中一个按键时将该按键对应的编号在 一个数码管上显示出来,当按下下一个按键时便将这个按键的编号在下一个数码 管上显示出来,且数码管上可以显示最近 6次按下按键的编号。
基本原理1•电路设计及功能说明2•硬件原理框图及电路图(包括接口芯片简介) 电路图:叫"11I —0 - 0E E可编辑2・q 戟r :fQfiWElFQ^IS六、实验步骤(1) . 把实验平台与PC机串行口连起来,根据实验连线提示在实验台上连线,之后打开电源。
(2) . 在PC机上用鼠标点击“ Wave ”图标,进入 WINDOWS 调试环境,而后进行初始化设置。
点击[仿真器仿真器设置]出现“仿真器设置”窗,进行仿真器的设置。
⑶. 用鼠标点一下[文件打开文件],输入文件名*asm,创建新文件,在该窗口中输入事先编好的程序。
4X4键盘扫描程序

4X4键盘扫描程序,采用查表方式,适用于AVR单片机。
此处为4X4键盘软件部分,硬件部分设计请参照:4X4键盘扫描电路分析。
此程序对应的键盘电路为:键盘状态扫描函数/*键盘扫描函数读取当前键盘的状态有按键按下返回相应按键值无按键按下返回"0x00"*/unsigned char key_read(void){unsigned char i;DDRA = 0x00;/*获取列地址*/PORTA = 0x0F;DDRA = 0xF0;此处应加入几uS延时;i = PINA;DDRA = 0x00;/*获取行地址*/PORTA = 0xF0;DDRA = 0x0F;此处应加入几uS延时;i |= PINA;DDRA = 0x00;/*输出复位*/PORTA = 0xFF;switch (i) {/*将按键码转换成键值*/ case 0x00: return 0x00;case 0xEE: return '1';case 0xDE: return '2';case 0xBE: return '3';case 0x7E: return 'A';case 0xED: return '4';case 0xDD: return '5';case 0xBD: return '6';case 0x7D: return 'B';case 0xEB: return '7';case 0xDB: return '8';case 0xBB: return '9';case 0x7B: return 'C';case 0xE7: return '*';case 0xD7: return '0';case 0xB7: return '#';case 0x77: return 'D';default : return 0x00;}}键盘读取函数/*按键获取函数获取按键信号,其中包含有状态记录及按键去颤抖。
键盘扫描-分类

一、概述键盘在单片机应用系统中,实现输入数据、传送命令的功能,是人工干预的主要手段。
键盘分两大类:编码键盘和非编码键盘。
编码键盘:由硬件逻辑电路完成必要的键识别工作与可靠性措施。
每按一次键,键盘自动提供被按键的读数,同时产生一选通脉冲通知微处理器,一般还具有反弹跳和同时按键保护功能。
这种键盘易于使用,但硬件比较复杂,对于主机任务繁重之情况,采用8279可编程键盘管理接口芯片构成编码式键盘系统是很实用的方案。
非编码键盘:只简单地提供键盘的行列与矩阵,其他操作如键的识别,决定按键的读数等仅靠软件完成,故硬件较为简单,但占用CPU较多时间。
有:独立式按键结构、矩阵式按键结构。
二、键盘系统设计首先,确定键盘编码方案:采用编码键盘或非编码键盘。
随后,确定键盘工作方式:采用中断或查询方式输入键操作信息。
然后,设计硬件电路。
非编码键盘系统中,键闭合和键释放的信息的获取,键抖动的消除,键值查找及一些保护措施的实施等任务,均由软件来完成。
(一)非编码键盘的键输入程序应完成的基本任务1.监测有无键按下;键的闭合与否,反映在电压上就是呈现出高电平或低电平,所以通过电平的高低状态的检测,便可确认按键按下与否。
2.判断是哪个键按下。
一.编程扫描方式:当单片机空闲时,才调用键盘扫描子程序,反复的扫描键盘,等待用户从键盘上输入命令或数据,来响应键盘的输入请求。
二.定时扫描工作方式:单片机对键盘的扫描也可用定时扫描方式,即每隔一定的时间对键盘扫描一次。
三.中断工作方式:只有在键盘有键按下时,才执行键盘扫描程序并执行该按键功能程序,如果无键按下,单片机将不理睬键盘3.完成键处理任务。
(二)从电路或软件的角度应解决的问题1.消除抖动影响。
键盘按键所用开关为机械弹性开关,利用了机械触点的合、断作用。
由于机械触点的的弹性作用,一个按键开关在闭合和断开的瞬间均有一连串的抖动、抖动时间的长短由按键的机械特性决定,一般为5~10m s,这是一个很重要的参数。
C语言-4x4键盘扫描程序

C语言 4*4键盘扫描电路模块#include <reg51.h>#define uchar unsigned char //byte#define uint unsigned int //wordvoid keyscan(); //函数声明void fun0(); //定义每个按键的功能函数void fun1();void fun2();void fun3();void fun4();void fun5();void fun6();void fun7();void fun8();void fun9();void fun10();void fun11();void fun12();void fun13();void fun14();void fun15();/**************************************************************************** 主程序****************************************************************************/void main(void){while(1) //循环扫描{keyscan();}}/**************************************************************************** 按键功能函数 fun0~fun15****************************************************************************/ void fun0(void){ P3=0x00; }void fun1(void){ P3=0x01; }void fun2(void){ P3=0x02; }void fun3(void){ P3=0x03; } //fun4~fun15 略/**************************************************************************** 键盘扫描子程序 keyscan(); void keyscan(); //函数声明***** 无返回值,直接执行子函数功能fun0(); void fun0();//函数声明****************************************************************************/void keyscan(void){ unsigned char i,j;unsigned char n;P1=0xfe; n=P1; n&=0xf0; //扫描第一行if(n!=0xf0){ for(i=0;i<20;i++) for(j=0;j<250;j++); //延时P1=0xfe; n=P1; n&=0xf0;if(n!=0xf0){switch(n){case(0x70): fun0(); break;//按键 0 的函数功能 - 替换P3=0x00;case(0xb0): fun1(); break;//按键 1 的函数功能- 替换case(0xd0): fun2(); break;//按键 2 的函数功能- 替换case(0xe0): fun3(); break;//按键 3 的函数功能- 替换}}}P1=0xfd; n=P1; n&=0xf0; //扫描第二行if(n!=0xf0){ for(i=0;i<20;i++) for(j=0;j<250;j++);//延时P1=0xfd; n=P1; n&=0xf0;if(n!=0xf0){switch(n){case(0x70): P3=0x04; break;//按键 4 的函数功能- 替换 P3=0x04;case(0xb0): P3=0x05; break;//按键 5 的函数功能- 替换case(0xd0): P3=0x06; break;//按键 6 的函数功能- 替换case(0xe0): P3=0x07; break;//按键 7 的函数功能- 替换}}}P1=0xfb; n=P1; n&=0xf0; //扫描第三行if(n!=0xf0){ for(i=0;i<20;i++) for(j=0;j<250;j++); //延时P1=0xfb; n=P1; n&=0xf0;if(n!=0xf0){switch(n){case(0x70): P3=0x08; break;//按键 8 的函数功能- 替换P3=0x08;case(0xb0): P3=0x09; break;//按键 9 的函数功能- 替换case(0xd0): P3=0x0A; break;//按键 A 的函数功能- 替换case(0xe0): P3=0x0B; break;//按键 B 的函数功能- 替换}}}P1=0xf7; n=P1; n&=0xf0; //扫描第四行if(n!=0xf0){ for(i=0;i<20;i++) for(j=0;j<250;j++); //延时P1=0xf7; n=P1; n&=0xf0;if(n!=0xf0){switch(n){case(0x70): P3=0x0C; break;//按键 C 的函数功能- 替换 P3=0x0C; case(0xb0): P3=0x0D; break;//按键 D 的函数功能- 替换case(0xd0): P3=0x0E; break;//按键 E 的函数功能- 替换case(0xe0): P3=0x0F; break;//按键 F 的函数功能- 替换}}}}。
非编码键盘工作流程

非编码键盘工作流程
非编码键盘工作流程:
①按键按下:用户按下键盘上的某个键,触发机械开关闭合;
②产生键扫描码:键盘内部电路根据闭合开关的位置,生成对应的键扫描码;
③键扫描码发送:键盘控制器将键扫描码通过数据线传输给计算机;
④操作系统接收:计算机硬件接口接收到键扫描码,传递给操作系统;
⑤转换为ASCII码:操作系统根据当前键盘布局,将键扫描码转换为对应的ASCII字符码;
⑥应用程序响应:操作系统将ASCII码传递给活跃的应用程序,触发相应字符输入事件;
⑦显示字符:应用程序根据接收到的字符码,在屏幕上显示相应的字符或执行相关命令;
⑧按键释放:用户松开按键,机械开关断开,键盘停止发送该键的扫描码。
带FIFO存储的FPGA键盘扫描器设计(仿真+代码)

带FIFO存储的键盘扫描器设计一、模块结构:1、Keypad:顶层模块,负责调用其他模块;2、clock_divider:将50MHZ系统时钟分频,产生clk_slow(500HZ)和clk_display(1KHZ);3、keypad_scaner:扫描键盘,并产生编码值,测试时连续写入键盘值;4、code_fifo:将键盘值存入FIFO;5、rd_toggle:对read信号去抖动;6、decode_display:将键盘编码值映射成数码管编码值,并产生驱动数码管信号;7、row_signal:产生row,用于测试;二、模块仿真结果:1、clock_divider:clk_slow为500HZ;clk_sidplay为1KHZ,数码管的刷新频率1KHZ就可避免数码管闪烁;2、keypad_scaner:黄色信号为{col,row}的组合信号和对应的编码输出code,红色信号valid_o为FIFO的写使能信号;3、code_fifo:写进FIFO的数据;两条红线rd_en与valid分别为FIFO的读使能和写使能,黄色信号线为FIFO的输出,在读使能有效时,读出0001、0010、0011、0100、0101、0110;4、rd_toggle:两条红线分别为rd_up_cnt、rd_lw_cnt,用于消抖时read高低电平的计数,规定大于10ms可认为按键稳定。
黄线为稳定的read输出。
5、decode_display:三条红线分别为两个数码管的驱动信号left_code、right_code以及两个数码管的位选信号cathode。
6、row_signal:7、顶层仿真:当read有效时,读出“00”,“01”,“02”,“03”,“04”;三、综合-布局布线综合布局布线通过;四、模块代码:1、Keypad:`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company:// Engineer://// Create Date: 21:37:47 05/13/2015// Design Name:// Module Name: keypad// Project Name:// Target Devices:// Tool versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments:////////////////////////////////////////////////////////////////////////////////////module keypad(clk,reset,read,row,col,left_code,right_code,cathode,empty,full);input clk;input reset;input read;input[3:0] row;output[3:0] col;output[6:0] left_code;output[6:0] right_code;output empty;output full;output[1:0] cathode;wire[3:0] code;wire[3:0] code_out;wire[1:0] cathode;keypad_scaner u_keypad_scaner(.clk(clk_slow),.reset(reset),.row(row),.col(col),.code(code),.valid_o(valid));clock_divider u_clock_divider(.clk(clk),.reset(reset),.clk_slow(clk_slow),.clk_display(clk_display));code_fifo u_code_fifo(.clk(clk_slow),.reset(reset),.code(code),.valid(valid),.rd_en(read_fifo),.dout(code_out),.full(full),.empty(empty));rd_toggle u_rd_toggle(.clk(clk),.reset(reset),.read(read),.read_fifo(read_fifo));decode_display u_decode_display(.clk(clk_display),.reset(reset),.code(code_out),.left_code(left_code),.right_code(right_code),.cathode(cathode));endmodule2、keypad_scaner:`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company:// Engineer://// Create Date: 16:05:31 05/13/2015// Design Name:// Module Name: keypad_scaner// Project Name:// Target Devices:// Tool versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://////////////////////////////////////////////////////////////////////////////////// module keypad_scaner(clk,reset,row,col,code,valid_o);input clk ;input reset ;input[3:0] row ;output valid_o ;output[3:0] col ;output[3:0] code;reg valid;reg valid_tmp;reg[3:0] row_tmp;reg[3:0] num;reg[3:0] row_tmp1;reg[3:0] row_tmp2;reg[3:0] col ;reg[3:0] code ;reg[1:0] cnt ;wire valid_o;wire[7:0] key_sample;assign key_sample = {col,row};//列扫描信号always @(posedge clk or posedge reset)if(reset)begincnt <= 2'b0;col <= 4'b0000;endelsebegincnt <= cnt + 2'b01;case(cnt)2'b00 : col <= 4'b1000;2'b01 : col <= 4'b0100;2'b10 : col <= 4'b0010;2'b11 : col <= 4'b0001;endcaseendalways @(posedge clk or posedge reset) if(reset)code <= 4'b0000;elsebegincase(key_sample)//第一列扫描8'b1000_0001 : code <= 4'b0000;8'b1000_0010 : code <= 4'b0001;8'b1000_0100 : code <= 4'b0010;8'b1000_1000 : code <= 4'b0011;//第二列扫描8'b0100_0001 : code <= 4'b0100;8'b0100_0010 : code <= 4'b0101;8'b0100_0100 : code <= 4'b0110;8'b0100_1000 : code <= 4'b0111;//第三列扫描8'b0010_0001 : code <= 4'b1000;8'b0010_0010 : code <= 4'b1001;8'b0010_0100 : code <= 4'b1010;8'b0010_1000 : code <= 4'b1011;//第四列扫描8'b0001_0001 : code <= 4'b1100;8'b0001_0010 : code <= 4'b1101;8'b0001_0100 : code <= 4'b1110;8'b0001_1000 : code <= 4'b1111;default:code <= code;endcaseendalways @(posedge clk or posedge reset)if(reset)num <= 4'd0;else if(row == 4'b0000)num <= num + 4'd1;elsenum <= 4'd0;always @(posedge clk or posedge reset)if(reset)row_tmp <= 4'b0000;elserow_tmp <= row;always @(posedge clk or posedge reset)if(reset)valid <= 1'b0;else if(num > 4'd4)valid <= 1'b0;else if(row_tmp)valid <= 1'b1;elsevalid <= valid;always @(posedge clk or posedge reset)if(reset)valid_tmp <= 1'b0;elsevalid_tmp <= valid;assign valid_o = valid & (~valid_tmp);endmodule3、clock_divider`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company:// Engineer://// Create Date: 09:09:00 05/16/2015// Design Name:// Module Name: clock_divider// Project Name:// Target Devices:// Tool versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://////////////////////////////////////////////////////////////////////////////////// module clock_divider(clk,reset,clk_slow,clk_display);input clk;input reset;output clk_slow;output clk_display;reg clk_slow;reg clk_display;reg[17:0] divide_cnt1;reg[19:0] divide_cnt2;always @(posedge clk or posedge reset)if(reset)divide_cnt1 <= 18'd0;else if(divide_cnt1 == 17'd100000)divide_cnt1 <= 18'd0;elsedivide_cnt1 <= divide_cnt1 + 18'd1;always @(posedge clk or posedge reset)if(reset)divide_cnt2 <= 20'd0;else if(divide_cnt2 == 20'd50000)divide_cnt2 <= 20'd0;elsedivide_cnt2 <= divide_cnt2 + 20'd1;always @(posedge clk or posedge reset)if(reset)clk_slow <= 1'b0;else if(divide_cnt1 <= 18'd50000)clk_slow <= 1'b1;elseclk_slow <= 1'b0;always @(posedge clk or posedge reset)if(reset)clk_display <= 1'b0;else if(divide_cnt2 <= 20'd25000)clk_display <= 1'b1;elseclk_display <= 1'b0;endmodule4、code_fifo`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company:// Engineer://// Create Date: 10:47:48 05/14/2015// Design Name:// Module Name: key_fifo// Project Name:// Target Devices:// Tool versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments:////////////////////////////////////////////////////////////////////////////////////module code_fifo(clk,reset,code,valid,rd_en,dout,full,empty);input clk;input reset;input valid;input rd_en;input[3:0] code;output[3:0] dout;output full;output empty;key_fifo u_key_fifo(.clk(clk),.rst(reset),.din(code),.wr_en(valid),.rd_en(rd_en),.dout(dout),.full(full),.empty(empty));Endmodule5、rd_toggle:`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company:// Engineer://// Create Date: 16:59:34 05/13/2015// Design Name:// Module Name: rd_toggle// Project Name:// Target Devices:// Tool versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://////////////////////////////////////////////////////////////////////////////////// module rd_toggle(clk,reset,read,read_fifo);input clk;input reset;input read;output read_fifo;reg read_fifo;reg[23:0] rd_up_cnt; //按键输入高电平计数器reg[23:0] rd_lw_cnt; //按键输入低电平计数器//对输入进行采样、计数always @(posedge clk or posedge reset)if(reset)rd_up_cnt <= 24'd0;else if(read)rd_up_cnt <= rd_up_cnt + 24'd1;elserd_up_cnt <= 24'd0;always @(posedge clk or posedge reset)if(reset)rd_lw_cnt <= 24'd0;else if(!read)rd_lw_cnt <= rd_lw_cnt + 24'd1;elserd_lw_cnt <= 24'd0;always @(posedge clk or posedge reset)if(reset)read_fifo <= 1'b0;else if(rd_up_cnt == 24'h7A120) //大于10ms认为按键稳定read_fifo <= 1'b1;else if(rd_lw_cnt == 24'h7A120)read_fifo <= 1'b0;elseread_fifo <= read_fifo;endmodule6、decode_display:`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company:// Engineer://// Create Date: 17:19:56 05/13/2015// Design Name:// Module Name: decode_display// Project Name:// Target Devices:// Tool versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments:////////////////////////////////////////////////////////////////////////////////////module decode_display(clk,code,reset,left_code,right_code,cathode);input clk;input reset;input[3:0] code;output[6:0] left_code;output[6:0] right_code;output[1:0] cathode;reg[6:0] left_code;reg[6:0] right_code;reg[15:0] cnt; //动态扫描计数器reg[1:0] cathode; //片选信号;//七段数码管段选(共阳极)parameter ZERO = 7'b100_0000; parameter ONE = 7'b111_1001; parameter TWO = 7'b010_0100; parameter THREE = 7'b011_0000; parameter FOUR = 7'b001_1001; parameter FIVE = 7'b001_0010; parameter SIX = 7'b000_0010; parameter SEVEN = 7'b111_1000; parameter EIGHT = 7'b000_0000; parameter NINE = 7'b001_0000;always @(posedge clk or posedge reset)if(reset)cathode <= 2'b00;elsecase(cathode)2'b00 : cathode <= 2'b01;2'b01 : cathode <= 2'b10;2'b10 : cathode <= 2'b01;endcasealways @(code)case(code)4'b0000 : beginright_code <= ZERO;left_code <= ZERO;end4'b0001 : right_code <= ONE;4'b0010 : right_code <= TWO;4'b0011 : right_code <= THREE;4'b0100 : right_code <= FOUR;4'b0101 : right_code <= FIVE;4'b0110 : right_code <= SIX;4'b0111 : right_code <= SEVEN;4'b1000 : right_code <= EIGHT;4'b1001 : right_code <= NINE;4'b1010 : beginright_code <= ZERO;left_code <= ONE;end4'b1011 : beginright_code <= ONE;left_code <= ONE;end4'b1100 : beginleft_code <= ONE;right_code <= TWO;end4'b1101 : beginleft_code <= ONE;right_code <= THREE;end4'b1110 : beginleft_code <= ONE;right_code <= FOUR;end4'b1111 : beginleft_code <= ONE;right_code <= FIVE;enddefault : beginleft_code <= ZERO;right_code <= ZERO;endendcaseendmodule7、row_signal:`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company:// Engineer://// Create Date: 20:00:46 05/14/2015// Design Name:// Module Name: row_signal// Project Name:// Target Devices:// Tool versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments:////////////////////////////////////////////////////////////////////////////////////module row_signal(row,key,col);input[15:0] key;input[3:0] col;output[3:0] row;reg[3:0] row;always @(posedge key or col)beginrow[0] = key[0]&&col[3] || key[4]&&col[2] || key[8]&&col[1] || key[12]&&col[0];row[1] = key[1]&&col[3] || key[5]&&col[2] || key[9]&&col[1] || key[13]&&col[0];row[2] = key[2]&&col[3] || key[6]&&col[2] || key[10]&&col[1] || key[14]&&col[0];row[3] = key[3]&&col[3] || key[7]&&col[2] || key[11]&&col[1] || key[15]&&col[0];endendmodule8、keypad_tst:`timescale 1ns / 1ps////////////////////////////////////////////////////////////////////////////////// Company:// Engineer://// Create Date: 19:16:02 05/14/2015// Design Name: keypad// Module Name: D:/FPGAProject/Xilinx/keypad_design/keypad_tst.v // Project Name: keypad_design// Target Device:// Tool versions:// Description://// Verilog Test Fixture created by ISE for module: keypad//// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://////////////////////////////////////////////////////////////////////////////////module keypad_tst;// Inputsreg clk;reg reset;reg read;wire[3:0] row;reg[39:0] pressed;reg[15:0] key_s;// Outputswire[3:0] col;wire[6:0] left_code;wire[6:0] right_code;wire empty;wire full;wire[1:0] cathode;wire[15:0] key;integer j;integer k;// Instantiate the Unit Under Test (UUT)keypad uut (.clk(clk),.reset(reset),.read(read),.row(row),.col(col),.left_code(left_code),.right_code(right_code),.cathode(cathode),.empty(empty),.full(full));parameter[39:0] key_0 = "key_0"; parameter[39:0] key_1 = "key_1"; parameter[39:0] key_2 = "key_2"; parameter[39:0] key_3 = "key_3"; parameter[39:0] key_4 = "key_4"; parameter[39:0] key_5 = "key_5"; parameter[39:0] key_6 = "key_6"; parameter[39:0] key_7 = "key_7"; parameter[39:0] key_8 = "key_8"; parameter[39:0] key_9 = "key_9"; parameter[39:0] key_A = "key_A"; parameter[39:0] key_B = "key_B"; parameter[39:0] key_C = "key_C"; parameter[39:0] key_D = "key_D"; parameter[39:0] key_E = "key_E"; parameter[39:0] key_F = "key_F"; parameter[39:0] none = "none";row_signal u_row_signal(.row(row),.key(key),.col(col));initialbeginclk = 0;reset = 1;read = 0;//row = 0;#20 reset = 0;endalways @(key)case(key)16'h0000 : pressed = none;16'h0001 : pressed = key_0;16'h0002 : pressed = key_1;16'h0004 : pressed = key_2;16'h0008 : pressed = key_3;16'h0010 : pressed = key_4;16'h0020 : pressed = key_5;16'h0040 : pressed = key_6;16'h0080 : pressed = key_7;16'h0100 : pressed = key_8;16'h0200 : pressed = key_9;16'h0400 : pressed = key_A;16'h0800 : pressed = key_B;16'h1000 : pressed = key_C;16'h2000 : pressed = key_D;16'h4000 : pressed = key_E;16'h8000 : pressed = key_F;default : pressed = none;endcasealways #10 clk = ~clk;initialbeginfor(k=0; k<=1; k=k+1)beginkey_s=0;#50 for(j=0; j<=16; j=j+1)begin#40000000 key_s[j] = 1;#50000000 key_s = 0; //50msendendendassign key = key_s;initialbegin#400000000 read = 1;#200000000 read = 0; // 60ms#400000000 read = 1;// #200000000 read = 0;// #100000000 read = 1; // #200000000 read = 0; // #100000000 read = 1; // #700000000 read = 0; endendmodule。
基于FPGA的键盘扫描模块的设计与实现

基于FPGA的键盘扫描模块的设计与实现在产品中,键盘是最基本的输入设备,然而在应用中都采纳通用的键盘扫描器件是不现实的,需要单独设计成专用的小键盘。
现代(电子设计)技术提供了一种很好的途径,利用硬件描述语言和器件可以很便利地构建键盘扫描模块。
经过实际操作检验,该模块可以很好地对每一次按键动作举行扫描和响应,实现预先设计的功能。
1 概述1.1 通用键盘和专用键盘在现代个人计算机系统中,普通都采纳通用的标准键盘(如:标准101/102键盘或Microsoft自然PS/2键盘)来实现人与计算机之间的接口交互,所需要的各种数据和命令等信息都通过键盘来输入计算机。
但是,在各种系统(如手机、微波炉、电风扇等)中,所需要的键盘按键个数十分有限,通常为几个到十几个不等(而标准键盘通常为一百多个按键),并且每个按键所代表的功能含义也各不相同。
所以,针对每一种嵌入式系统都应对键盘(包括键盘扫描模块和相关控制信号等)举行特地设计,结合工程实际状况充分利用该系统已有的各种资源,使所设计的键盘恰如其分地融合到嵌入式系统中,成为其不行分割的一部分。
1.2 编码键盘和扫描键盘在数字中,可以利用实现按键键值的挺直编码。
将每个按键的输出信号对应衔接到编码器的每个输入端,通过编码规律就可以在编码器的输出端得到对应每个按键的码值,早期称这种键盘为编码键盘。
但是,当按键较多时数码规律的成本较高,挺直编码的办法也不够灵括,一旦编码规律固定就难以更改。
在通用键盘上或当按键数量较多时,普遍采纳扫描方式产生键值。
将按键衔接成矩阵,每个按键位于某行、某列的交点上,1所示,先通过扫描方式确定按下键的行和列位,即位置码或扫描码。
再查表将位置码转换为按键码值或者挺直用法扫描码,有些参考书称此为“非编码键盘”。
但这种名称简单让人误会为没有对应的键值,因此又称为第1页共4页。
实验一 矩阵键盘检测

实验一矩阵键盘检测一、实验目的:1、学习非编码键盘的工作原理和键盘的扫描方式。
2、学习键盘的去抖方法和键盘应用程序的设计.二、实验设备:51/AVR实验板、USB连接线、电脑三、实验原理:键盘接口电路是单片机系统设计非常重要的一环,作为人机交互界面里最常用的输入设备。
我们可以通过键盘输入数据或命令来实现简单的人机通信。
1、按键的分类一般来说,按键按照结构原理可分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关等;另一类是无触点式开关按键,如电气式按键,磁感应按键等。
前者造价低,后者寿命长。
目前,微机系统中最常见的是触点式开关按键(如本学习板上所采用按键).按键按照接口原理又可分为编码键盘与非编码键盘两类,这两类键盘的主要区别是识别键符及给出相应键码的方法。
编码键盘主要是用硬件来实现对键的识别,非编码键盘主要是由软件来实现键盘的识别。
全编码键盘由专门的芯片实现识键及输出相应的编码,一般还具有去抖动和多键、窜键等保护电路,这种键盘使用方便,硬件开销大,一般的小型嵌入式应用系统较少采用。
非编码键盘按连接方式可分为独立式和矩阵式两种,其它工作都主要由软件完成。
由于其经济实用,较多地应用于单片机系统中(本学习板也采用非编码键盘)。
2、按键的输入原理在单片机应用系统中,通常使用机械触点式按键开关,其主要功能是把机械上的通断转换成为电气上的逻辑关系。
也就是说,它能提供标准的TTL 逻辑电平,以便与通用数字系统的逻辑电平相容.此外,除了复位按键有专门的复位电路及专一的复位功能外,其它按键都是以开关状态来设置控制功能或输入数据。
当所设置的功能键或数字键按下时,计算机应用系统应完成该按键所设定的功能。
因此,键信息输入是与软件结构密切相关的过程。
对于一组键或一个键盘,通过接口电路与单片机相连. 单片机可以采用查询或中断方式了解有无按键输入并检查是哪一个按键按下,若有键按下则跳至相应的键盘处理程序处去执行,若无键按下则继续执行其他程序。
键盘扫描程序开始

# include<reg52.h># include<stdio.h># include<intrins.h># define uchar unsigned char# define uint unsigned int# define ulong unsigned longdouble tempcost;bit apflag=0;float danjia;uchar key,flag;long tempadd;ulonga=0,b=0,count0=0,count1=0,count2=0,speed=0,zhouchang=1,distance,cost,n,zongfen,j unfen;uchar dispspeed[3]={0,0,0},dispcost[3]={0,0,0},dispdist[4]={0,0,0,0};sbit playl=P2^2;sbit csda=P2^1;//键盘扫描程序开始void keyscan(){ uchar temp;uint i;P1=0XFF;P1=0XF0;while(P1==0XF0);for(i=1;i<=5;i++){switch(i){ case 1:P1=0XFE;key=0; break;case 2:P1=0XFD;key=0;key+=4; break;case 3:P1=0XFB;key=0;key+=8; break;case 4:P1=0XF7;key=0;key+=12; break;case 5:i=0; break;}temp=P1;temp|=0X0F;switch(temp){ case 0XEF: key+=0; i=40; break;case 0XDF: key+=1; i=40; break;case 0XBF: key+=2; i=40; break;case 0X7F: key+=3; i=40; break;}}P1=0XF0;while(P1!=0XF0);//松开键盘再显示数}//键盘扫描程序结束//lcd的准备程序,里面包含lcd显示初试化等子函数//////////开始////////////// sbit dc=P2^4; /*P2.0 LCD 的RS 21*/sbit rw=P2^5; /*P2.1 LCD 的R/W 22*/sbit cs=P2^6; /*P2.4 LCD 的E 25*/sfr lcdbus=0x80; /*p0LCD 数据 D0=P0.0*///unsigned int sys10mscounter;//unsigned char syslimitcounter;void soft_nop(){}void soft_10ms()/***********12MHZ 提供10MS 软件延时************/{ register int i; // 使用CPU内部寄存的变量for(i=0;i<711;i++);}void soft_20ms()/***********12MHZ 提供20MS 软件延时************/{ soft_10ms();soft_10ms();}//bit lcdusing1,lcdusing2;bit lcd_checkbusy()/*检查LCD 忙*/{ register lcdstate;dc=0; /*dc=1为数据,=0 为命令.*/rw=1; /*rw=1为读,=0为写.*/cs=1; /*cs=1选通.*/soft_nop();lcdstate=lcdbus;cs=0;return((bit)(lcdstate&0x80));}void lcd_wrcmd(unsigned char lcdcmd) /*写LCD命令*/{ //lcdusing1=1;while(lcd_checkbusy());lcdbus=lcdcmd;dc=0; /*dc=1为数据,=0 为命令.*/rw=0; /*rw=1为读,=0为写.*/cs=1; /*cs=1选通.*/soft_nop();cs=0;lcdbus=0xff;}void lcd_wrdata(char lcddata) /*在当前显示位置显示数据*/{while(lcd_checkbusy());lcdbus=lcddata;dc=1; /*dc=1为数据,=0 为命令.*/rw=0; /*rw=1为读,=0为写.*/cs=1; /*cs=1选通.*/soft_nop();cs=0;lcdbus=0xff;}void lcd_init()/*初始化*/{ lcd_wrcmd(0x38); /*设置8 位格式,2行,5*7*/lcd_wrcmd(0x0c); /*整体显示,关光标,不闪烁*/lcd_wrcmd(0x06); /*设定输入方式,增量不移位*/lcd_wrcmd(0x01); /*清除显示*/}void lcd_cls()/*清除显示*/{ lcd_wrcmd(0x01);}void lcd_string(char *strpoint) /*在当前显示位置显示LCD 字符串*/ { register i=0;while(strpoint[i]!=0){lcd_wrdata(strpoint[i]);i++;}}/////lcd的准备程序,里面包含lcd显示初试化等子函数//////////结束//////////////void delay2s(){uint m;for(m=0;m<100;m++){soft_20ms();}}void timer0(void) interrupt 1 //T0负责计算脉冲的个数{ EA=0;TR0=0;TH0=0x00;TL0=0x00;TR0=1;count1++; //T0溢出,用于计算路程count2++; //T0溢出,用于计算速度EA=1;}void timer1(void) interrupt 3 //T1负责1S的计时{ EA=0;TR1=0;TH1=0x3c;TL1=0xb0;TR1=1;count0++; //T1溢出if(count0==20){ a=a+TH0;b=b+TL0;speed=(count2*65536+TH0*256+TL0)*zhouchang; //车轮的周长,待查dispspeed[0]=speed%10;dispspeed[1]=(speed/10)%10;dispspeed[2]=(speed/100)%10;lcd_wrcmd(0x86); //显示速度模块lcd_wrdata('v');lcd_wrdata(dispspeed[2]+48);lcd_wrdata(dispspeed[1]+48);lcd_wrdata(dispspeed[0]+48);distance=(count1*65536+a*256+b)*zhouchang/100; //车轮的周长,待查dispdist[0]=distance%10;dispdist[1]=(distance/10)%10;dispdist[2]=(distance/100)%10;dispdist[3]= (distance/1000)%10; lcd_wrcmd(0xc0); //显示路程模块 lcd_string("s:");lcd_wrdata(dispdist[3]+48);lcd_wrdata(dispdist[2]+48);lcd_wrdata(dispdist[1]+48);lcd_wrdata(dispdist[0]+48);count0=0;count2=0;TH0=0;TL0=0;}EA=1;}void freqcount(){TMOD=0X15;count0=0;count1=0;count2=0;TH1=0x3c;TL1=0xb0;TH0=0x00;TL0=0x00;EA=1;ET0=1;ET1=1;TR0=1;TR1=1;a=0;b=0;}void main(){ uint x,m;n=0;csda=0;P0=0;csda=1;P0=0xff;zongfen=0;TMOD=0X15;for(;;){ lcd_init();soft_20ms();lcd_string("w..");TR0=0;TR1=0;EA=0;ET0=0;ET1=0;if(apflag==0){lcd_wrcmd(0x8d);lcd_string("day");}else{lcd_wrcmd(0x8d);lcd_string("nig");}keyscan();if(key==7){apflag=!apflag;}else if(key==12) //开始键为C{P0=0x68;playl=0;delay2s();playl=1;lcd_init();soft_20ms();lcd_wrcmd(0x80);lcd_string("onway:");if(apflag==0){lcd_wrcmd(0x8d); lcd_string("day"); }else{lcd_wrcmd(0x8d); lcd_string("nig"); }freqcount();//控制电机csda=0;P0=0;csda=1;for(;;){ keyscan();if(key==14) //E键控制加tempadd+=30;if(tempadd>250){tempadd=240;}csda=0;P0=tempadd;csda=1;if(key==15) //F键控制减tempadd-=30;if(tempadd<0){tempadd=0;}csda=0;P0=tempadd;csda=1;if(key==13)break;}csda=0;P0=0;csda=1;for(;;){keyscan();if(key==13){EA=0;TR0=0;TR1=0;P0=0x70;playl=0;delay2s();playl=1;if(apflag==0)danjia=1.2;elsedanjia=1.8;if(distance<=3)cost=5;else if(distance>3&&distance<=7){tempcost=5+(distance-3)*danjia; //费用处理模块,有待细化cost=tempcost; //将浮点型费用化为整形(不知道对否?)lcd_wrcmd(0xcd);if(apflag==0)lcd_string("1.2");elselcd_string("1.8");}else{tempcost=9.8+(distance-7)*1.5;cost=tempcost;lcd_wrcmd(0xcd);lcd_string("1.5");}dispcost[0]=cost%10;dispcost[1]=(cost/10)%10;dispcost[2]=(cost/100)%10;lcd_wrcmd(0xc6); //显示费用playl=0;delay2s();delay2s();playl=1;lcd_wrcmd(0x80); //打分显示lcd_string(" ");lcd_wrcmd(0x80);lcd_string("pingfen..");keyscan();n++;if(key>=0 && key<=5){zongfen+=key; junfen=zongfen/n; }lcd_wrcmd(0x80);lcd_string("reputation");lcd_wrdata(junfen+48);for(;;){keyscan();if(key==6)break;}//此处做结束报时用EA=0;TR0=0;TR1=0;break;}}}}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录1设计任务及要求 (1)1.1初始条件 (1)1.2要求完成的主要任务 (1)2方案比较及认证 (1)3键盘扫描原理 (3)4系统硬件设计 (4)4.1选用元器件 (4)4.1.1 8031单片机 (4)4.1.2 8155芯片 (7)4.2 硬件电路 (10)4.2.1矩阵式键盘电路 (10)4.2.2时钟电路和复位电路 (11)4.2.3非编码键盘的总电路 (12)5系统软件设计 (13)5.1软件思想 (13)5.2 程序流程图 (14)5.3源程序 (15)6调试记录及结果分析 (18)心得体会 (19)参考文献 (20)附录 (21)附录1 8031单片机资料 (21)附录2 8155芯片资料 (21)附录3 程序清单 (22)非编码键盘的扫描程序设计1设计任务及要求1.1初始条件1.通过8155扩展I/O口组成6×6行列式键盘2.利用8031微控制器1.2要求完成的主要任务1.技术指标:对键盘按键能够正确识别,去抖动2.工作原理:键盘扫描3.课程设计说明书应包括(1)设计任务及要求(2)方案比较及认证(3)键盘扫描原理(4)硬件原理,电路图,采用器件的功能说明(5)软件思想,流程,源程序(6)调试记录及结果分析(7)参考资料(8)附录:芯片资料,程序清单(9)总结2方案比较及认证(1)键盘去抖动方案的选择键盘采用机械弹性开关来反映一个电压信号的开、断。
由于机械触点的弹性作用,在闭合和断开的瞬间会有抖动发生。
抖动时间的长短由按键的机械特性决定,一般在5~10ms之间。
抖动会造成被查询的开关状态无法准确读到。
例如开关刚刚断开,只是因为抖动误认为开关又发生第二次闭合,这显然是不允许的。
为此必须采取一些去抖动的措施,以免误读。
去抖动措施有硬件和软件两种方法。
硬件去抖动的办法,就是不把开关直接接到接口,而是如图2-1那样,加接一个RS触发器,只有开关脱离a而接到b 时,触发器才能翻转,才能输出一个稳定的电平。
软件去抖动是在检测到有按键按下时,执行一个10~20ms的延时程序,避开抖动信号,然后再次检测该键是否确实闭合,如果再次检测时,查不到有键按下,说明并非有效按键信号,应放弃初测结果,以免误动作。
硬件去抖动方式一般用在对按键操作过程比较严格的场合。
采用硬件去抖动电路将导致系统硬件电路设计复杂化,会增加设计成本。
软件去抖动方式可以简单地通过编程实现,降低了设计成本。
通过以上分析,决定采用软件去抖动方式。
(2)扫描方式的选择通常,键盘扫描方式有三种,及编程扫描、定时扫描和中断扫描。
编程扫描就是CPU对键盘的扫描采取程序控制方式,一旦进入键扫描状态,则反复的扫描键盘,等待用户从键盘上输入命令或数据。
而在执行键入命令或处理键入数据过程中,CPU将不再响应键入要求,直到CPU返回重新扫描键盘为止。
定时扫描就是CPU每隔一定的时间(如10ms)对键盘扫描一遍。
当发现有键按下时,便进行读入键盘操作,以求出键值,并分别经行处理。
定时时间间隔由单片机内部定时器/计数器来完成,这样可以减少计算机扫描键盘的时间,以减少CPU的开销。
具体做法是,当定时时间一到,定时器便自动输出一脉冲信号,使CPU转去执行扫描程序。
但有一点需要指出,即采用定时扫描法时,必须在其初始化程序中,对定时器写入相应的命令,使之能定时产生中断,以完成定时扫描的任务。
中断扫描的工作过程如下:当无键按下时,CPU不对键盘进行扫描以节省出大量的时间对系统经行监控和数据处理,当有键按下时,产生中断请求,CPU 转去执行键盘扫描子程序,并识别键号。
无论是编程扫描还是定时扫描,均占用CPU大量的时间。
无论有没有输入操作,CPU总要在一定的时间内进行扫描,这对于单片机控制系统是很不利的。
中断扫描更进一步的节省了CPU的时间,由于本次课程设计只是设计一个行列式键盘,所以不用去考虑节省CPU的时间,而且编程扫描比定时扫描的控制程序简单,所以选用编程扫描方式。
图2-1 RS触发器去抖动电路3键盘扫描原理行列式键盘又称为矩阵式键盘,适用于按键数量较多的场合,它由行线和列线组成。
按键位于行线和列线的交叉点上,行线、列线分别接到按键开关的两端。
行线通过上拉电阻接到+5V上。
平时无按键动作时,行线处于高电平状态,而当有按键按下时,行线电平状态由与此行线相连的列线电平决定。
列线电平如果为低,则行线电平为低;列线电平如果为高,则行线电平亦为高。
这一点是识别矩阵键盘按键是否被按下的关键所在。
由于矩阵键盘中行线、列线为多键共用,各按键均影响该键所在的行和列的电平。
因此各按键彼此将相互发生影响,所以必须将行线、列线信号配合起来并作适当的处理,才能确定闭合键的位置。
扫描法是非编码键盘常用的方法。
用扫描法来识别矩阵键盘按键分两步经行。
(1)识别有无按键被按下:让所有列线均置为零电平,检查各行线电平是否有变化。
如果有变化,则说明有按键被按下;如果没有变化,则说明无键被按下。
(2)识别具体按键的方法:首先逐列置零电平,其余各列置为高电平,然后检查各行线电平的变化,如果某行电平由高电平变为零电平,则可确定此行此列交叉点处的按键被按下。
4系统硬件设计4.1选用元器件4.1.1 8031单片机8031单片机共有40条引脚,其中有2条专用于主电源的引脚,2条外接晶体的引脚,4条控制或与其它电源复用的引脚,32条输入/输出(I/O)引脚。
其引脚图如图4-1所示。
图4-1 8031单片机引脚图下面按其引脚功能分为四部分叙述这40条引脚的功能。
(1)主电源引脚VCC和VSSVCC——(40脚)接+5V电压;VSS——(20脚)接地。
(2)外接晶体引脚XTAL1和XTAL2XTAL1(19脚)接外部晶体的一个引脚。
在单片机内部,它是一个反相放大器的输入端,这个放大器构成了片内振荡器。
当采用外部振荡器时,对HMOS 单片机,此引脚应接地;对CHMOS单片机,此引脚作为驱动端。
XTAL2(18脚)接外晶体的另一端。
在单片机内部,接至上述振荡器的反相放大器的输出端。
采用外部振荡器时,对HMOS单片机,该引脚接外部振荡器的信号,即把外部振荡器的信号直接接到内部时钟发生器的输入端;对XHMOS,此引脚应悬浮。
(3)控制或与其它电源复用引脚RST/VPD、ALE/PROG、PSEN和EA/VPP①RST/VPD(9脚)当振荡器运行时,在此脚上出现两个机器周期的高电平将使单片机复位。
推荐在此引脚与VSS引脚之间连接一个约8.2k的下拉电阻,与VCC引脚之间连接一个约10μF的电容,以保证可靠地复位。
VCC掉电期间,此引脚可接上备用电源,以保证内部RAM的数据不丢失。
当VCC主电源下掉到低于规定的电平,而VPD在其规定的电压范围(5±0.5V)内,VPD就向内部RAM提供备用电源。
②ALE/PROG(30脚):当访问外部存贮器时,ALE(允许地址锁存)的输出用于锁存地址的低位字节。
即使不访问外部存储器,ALE端仍以不变的频率周期性地出现正脉冲信号,此频率为振荡器频率的1/6。
因此,它可用作对外输出的时钟,或用于定时目的。
然而要注意的是,每当访问外部数据存储器时,将跳过一个ALE脉冲。
ALE端可以驱动(吸收或输出电流)8个LS型的TTL输入电路。
对于EPROM单片机(如8751),在EPROM编程期间,此引脚用于输入编程脉冲(PROG)。
③PSEN(29脚):此脚的输出是外部程序存储器的读选通信号。
在从外部程序存储器取指令(或常数)期间,每个机器周期两次PSEN有效。
但在此期间,每当访问外部数据存储器时,这两次有效的PSEN信号将不出现。
PSEN同样可以驱动(吸收或输出)8个LS型的TTL输入。
④EA/VPP(引脚):当EA端保持高电平时,访问内部程序存储器,但在PC(程序计数器)值超过0FFFH(对851/8751/80C51)或1FFFH(对8052)时,将自动转向执行外部程序存储器内的程序。
当EA保持低电平时,则只访问外部程序存储器,不管是否有内部程序存储器。
对于常用的8031来说,无内部程序存储器,所以EA脚必须常接地,这样才能只选择外部程序存储器。
对于EPROM型的单片机(如8751),在EPROM编程期间,此引脚也用于施加21V的编程电源(VPP)。
(4)输入/输出(I/O)引脚P0、P1、P2、P3(共32根)①P0口(39脚至32脚):是双向8位三态I/O口,在外接存储器时,与地址总线的低8位及数据总线复用,能以吸收电流的方式驱动8个LS型的TTL负载。
②P1口(1脚至8脚):是准双向8位I/O口。
由于这种接口输出没有高阻状态,输入也不能锁存,故不是真正的双向I/O口。
P1口能驱动(吸收或输出电流)4个LS型的TTL负载。
对8052、8032,P1.0引脚的第二功能为T2定时/计数器的外部输入,P1.1引脚的第二功能为T2EX捕捉、重装触发,即T2的外部控制端。
对EPROM编程和程序验证时,它接收低8位地址。
③P2口(21脚至28脚):是准双向8位I/O口。
在访问外部存储器时,它可以作为扩展电路高8位地址总线送出高8位地址。
在对EPROM编程和程序验证期间,它接收高8位地址。
P2可以驱动(吸收或输出电流)4个LS型的TTL负载。
④P3口(10脚至17脚):是准双向8位I/O口,在MCS-51中,这8个引脚还用于专门功能,是复用双功能口。
P3能驱动(吸收或输出电流)4个LS型的TTL 负载。
作为第一功能使用时,就作为普通I/O口用,功能和操作方法与P1口相同。
作为第二功能使用时,各引脚的定义如表4-1所示。
P3口的每一条引脚均可独立定义为第一功能的输入输出或第二功能。
表4-1 P3各口线的第二功能定义4.1.2 8155芯片8155芯片是为8086系列微机开发出的系列通用可编程I/O接口芯片。
8155不仅可以提供三个并行的I/O端口,在其内部还集成有256个字节的RAM存储空间、一个14位的定时/计数器,因此非常适合与MCS-51单片机连接实现系统功能的扩展。
8155的引脚图如图4-2所示:图4-2 8155引脚图(1)8155各引脚功能说明如下:RST:复位信号输入端,高电平有效。
复位后,3个I/O口均为输入方式。
AD0~AD7:三态的地址/数据总线。
与单片机的低8位地址/数据总线(P0口)相连。
单片机与8155之间的地址、数据、命令与状态信息都是通过这个总线口传送的。
RD:读选通信号,控制对8155的读操作,低电平有效。
WR:写选通信号,控制对8155的写操作,低电平有效。
CE:片选信号线,低电平有效。
IO/M :8155的RAM存储器或I/O口选择线。
当IO/M =0时,则选择8155的片内RAM,AD0~AD7上地址为8155中RAM单元的地址(00H~FFH);当IO/M =1时,选择 8155的I/O口,AD0~AD7上的地址为8155 I/O口的地址。