用 CPLD实现结构简单的键盘控制器
摘要:本文介绍了一种用 CPLD实现键盘控制器的崭新方法。该键盘控制器具有结构简单,通用性强等优点。
1. 引言
键盘作为单片机系统的一种主要输入设备被广泛使用,目前用于实现键盘控制的手段有很多,例如采用键盘专用控制芯片或软件扫描查询方式等。本人在制作 MP3 播放器的过程中使用 Altera 公司生产的 CPLD 芯片EPM7128SLC84-15 实现了包括键盘控制器在内的多个系统功能。本键盘控制器具有结构简单器件少、可与 51 系列单片机数据总线连接、能够发出中断请求等功能。经实际验证完全满足设计要求。此外它也可应用在单片机开发实验板、PDA、随身听等设备中。
2. 工作原理
本键盘控制器的每个键盘输入端口对应一个按键,并与一个独立工作的控制电路相连,每个控制电路由三个D触发器组成。第一个触发器主要用于键盘去抖,同时配合第二个触发器将键码转化为键码脉冲,最后一个触发器负责键码输出和中断请求。单片机响应中断请求后,读取键码并回写任意一个字节作为清除键码和中断请求的信号。键盘控制器与单片机的连接方式如图 1所示。
图 1 键盘控制器与单片机接口原理图
2.1. 键盘去抖
键盘在被按下和释放时通常会造成持续时间不大于 10ms 的信号抖动,这种抖动使系统无法正确识别按键操作次数。图 2是用D触发器实现键盘去抖功能的示意图。触发器的输入端D与下拉电阻R相连,时钟信号为50Hz,触发器在时钟的上升沿触发。当键盘未按下时,触发器输入端 D被电阻 R 下拉至低电平,触发器在 clk 的上升沿输出低电平。当键盘被按下后,D 变为高电平,触发器在 clk 的上升沿输出高电平。通过时序图可以推断出,在按键过程中可能有三种情况发生。
第一种:抖动发生在时钟信号的某个上升沿,并且此时的输入信号为高电平,则触发器在该上升沿输出高电平。
第二种:抖动同样发生在时钟信号的某个上升沿,但此时的输入信号为低电平,因为一般按键时间在 200ms 以上,所以触发器在下一个上升沿(20ms 后)输出高电平。
第三种:抖动发生在时钟信号的两个相邻上升沿之间,则触发器将在第二个上升沿输出高电平。释放键盘时的情况类似。可见,只要时钟信号周期大于抖动时间且小于按键时间,去抖电路就能正确识读按键次数。
图 2 去抖电路及时序图
2.2. 产生键码脉冲
去抖后得到的键码不能直接送到数据总线上等待单片机读取。因为当石英晶体频率为 12MHz 时,单片机AT89C52 可在几十微秒内完成键盘中断程序,在键盘被释放前键盘控制器已发出了多次中断请求,单片机也多次读取了相同的键码,所以要构造一个键码脉冲信号,使每一次按键操作对应一个键码脉冲,键盘控制器根据键码脉冲发出中断请求。如图 3所示,将第一个D触发器的输出作为第二个D触发器的输入,在同一个时钟信号(50Hz)的控制下,两个触发器构成移位寄存器,它们的输出 out1和 out2 相差一个时钟周期 T(20ms)。这两个输出信号经过非门和与门的逻辑组合,得到了脉宽为 20ms 的键码脉冲。
图 3 键码脉冲电路及时序图
2.3. 键码输出和中断请求
异步清除 D触发器在产生键码脉冲后的第一个时钟下降沿锁存键码脉冲信号,等待单片机读取键码,如图 4所示。因为单片机 AT89C52 使用下降沿或低电平触发中断,所以将键码反相后得到的低电平作为中断请求信号int 送出,该信号同时又使时钟信号无法通过与门进入触发器的时钟输入端,触发器保持锁存状态。当单片机响应了中断请求并读取了 out端口输出的键码后,发出中断清除信号给 clr端口,异步清除触发器的输出,中断请求信号 int 回到高电平,与门打开,时钟信号再次进入触发器的时钟输入端。因为在产生键码脉冲的时间内只会遇到一个时钟信号下降沿,触发器只锁存一次键码,并且只产生一次中断请求,所以不会使单片机发生在 1.2 中提到的重读键码问题。
图 4 键码输出电路及时序图
3. 程序设计
多数情况下键盘数量不止一个,考虑到还要与单片机数据总线相连,因此必须对上面介绍的单键控制加以改进。首先,键码输出要通过由片选信号(cs)和读信号(rd)控制的三态门连接到数据总线上。其次,锁存的键码经过或非门输出中断请求信号。最后,片选信号(cs)和写信号(wr)相或后产生中断清除信号。下面是键盘控制器的整体原理图、VHDL 程序和单片机程序。
图 5 整体原理图
3.1. 键盘控制器 VHDL程序
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity key_controler is
port
(
clk : in std_logic;--时钟信号
cs : in std_logic;--片选信号
rd : in std_logic;--读信号
wr : in std_logic;--写信号
key_in : in std_logic_vector(7 downto 0);--键盘输入
int : out std_logic;--中断请求
data : out std_logic_vector(7 downto 0)--数据输出
);
end entity;
architecture keyin of key_controler is
signal key_0 : std_logic_vector(7 downto 0);
signal key_1 : std_logic_vector(7 downto 0);
signal key_2 : std_logic_vector(7 downto 0);
signal key_3 : std_logic_vector(7 downto 0);
signal key_4 : std_logic;
signal clk_lock : std_logic;
signal read_data : std_logic;
signal int_clr : std_logic;
begin
process(clk)--去抖
begin
if rising_edge(clk) then
key_0<=key_in;
key_1<=key_0;
end if;
end process;
key_2<=(not key_1) and key_0;--键码脉冲
process(clk_lock,int_clr)--键码锁存,异步清除
begin
if int_clr='0' then
key_3<="00000000";
elsif falling_edge(clk_lock) then
key_3<=key_2;
end if;
end process;
key_4<=not (key_3(7) or key_3(6) or key_3(5) or key_3(4) or key_3(3) or key_3(2) or key_3(1) or key_3(0));
int<=key_4;--中断请求
clk_lock<=clk and key_4;
read_data<=cs or rd;--读键码
data<=key_3 when read_data='0' else "ZZZZZZZZ";--三态门输出控制
int_clr<=cs or wr;--清除中断
end architecture;
3.2. 单片机读键码程序
#include
#include
unsigned char key_code;
void display(char key_code)
{……}
void main(void)
{
IT0=1;//int0下降沿触发
EX0=1;//int0中断允许
EA=1;//开中断
4/5
while(1)
{
if(key_code!=0x00)
{
display_data(key_code);//显示键码
key_code=0x00;
}
}
}
void key_interrupt(void) interrupt 0
{
key_code=XBYTE[0x7fff];//读键码
XBYTE[0x7fff]=0x00;//清除键码和中断请求
}
4. 系统仿真和验证
键盘控制器 VHDL 程序经 MAX+PLUS II 10 仿真后的结果如图 6 所示。key_in 是键盘输入端口,控制器在按下键盘后的第一下降沿输出中断请求信号(int=0),单片机读键码时(rd=0),数据输出端口 data输出键码,单片机回写数据时(wr=0)清除中断请求(int=1)。经实验证实该设计完全正确。
图 6 仿真结果
5. 结语
本键盘控制器的最大特点就是结构简单。8 个按键的键盘控制器经过 MAX+PLUS II 10 编译后占用 34 个逻辑单元,如果使用 MAX+PLUS II Advanced Synthesis 综合后再编译则占用数量减少到 26个。这样的键盘控制器非常适合应用在一些对键盘数量要求不高的小系统中。
用 CPLD实现结构简单的键盘控制器相关推荐
- hook:实现简单的键盘记录器
说到hook技术,开始我真是一头雾水! 不久前看到一篇博客,实现 了一个简单的键盘记录器.我从中颇为受益!今天就来和大家分享一下我的一个小例子,并说说我的感悟! 首先就从main()函数开始吧,不过这 ...
- 6的变换_FPGA时序结构的LBT变换控制器设计
图像是信息传输的重要载体,随着社会科技进步,人们对图像质量要求越来越高,尤其是在航空航天.视频安防等领域,对图像传输与存储[1]的要求更高.因此在提高传输带宽的同时,对图像压缩的相关研究也同步开展,尤 ...
- Java的知识点6—— 强制类型转换、基本类型转化时常见错误和问题、 简单的键盘输入和输出
强制类型转换 强制类型转换,又被称为造型,用于显式的转换一个数值的类型.在有可能丢失信息的情况下进行的转换是通过造型来完成的,但可能造成精度降低或溢出. public class Test2 {pu ...
- 【运维程序】简单的命令控制器(支持定时命令执行、重复定时任务命令和进程管理,开发这个小程序主要是为了方便管理服务进程)【个人github项目】...
一.前言: command-controller 一个运维程序,简单的命令控制器(支持定时命令执行和重复定时命令,开发这个程序主要是为了方便管理服务进程) 本来是要用python做的,但是之前做ffm ...
- Ubuntu目录结构简单介绍笔记
一.Ubuntu目录结构简单介绍 Ubuntu目录结构简单介绍 /根目录 1.boot/启动文件.所有与启动有关的文件都保存在这里 ·grub/ Grub引导器相关的文件 2.dev/设备文件 ...
- ffplay.c函数结构简单分析(画图)
最近重温了一下FFplay的源代码.FFplay是FFmpeg项目提供的播放器示例.尽管FFplay只是一个简单的播放器示例,它的源代码的量也是不少的.之前看代码,主要是集中于某一个"点&q ...
- _EPROCESS结构简单了解!
_EPROCESS结构简单了解! lkd> dt _EPROCESSnt!_EPROCESS +0x000 Pcb : _KPROCESS +0x06c Pro ...
- C语言简单的键盘玩扫雷小游戏(完结)
1:这次我们会将前面的代码进行整合,和整理,最终使我们的程序可以有效的运行起来. [1]初始化函数. void GameInit() { //随机数种子 srand((unsigned ...
- android开发中Settings结构简单分析
Settings界面结构简单分析 Setting是android系统很重要的模块,这个模块并不是很复杂,这部分也一直在看,很多时候都是在看某个具体的选项,比如WLAN,蓝牙这样具体的源码,但是对于主界 ...
最新文章
- 黑计算机学校给的处分,学校处分通告格式
- [转]XPS转JPG转换器
- hybriddb mysql移植_HybridDB for MySQL 实现在线与离线数据分离的实践
- hdu 1163 ( 求n^n位根)
- Servlet—07—Cookie; Seesion;
- python读取txt文件写入-Python读写txt文本文件的操作方法全解析
- 【JQuery】将Json Object序列化成URL的QueryString
- 在 Linux 环境下,我用了这款端口扫描工具~
- leetcode162. 寻找峰值 变种二分见过吗
- Python语法的使用和简介
- fpga 输入信号除了1和0还有别的状态?
- 2010上半年网络工程师上午试题分析与解答
- 人员基础信息一体化采集系统平台
- 计算机硬盘应该什么格式化,电脑硬盘格式化方法总结 【图文】
- win7配置TomCat环境
- 用Qt图形视图框架开发拼图游戏
- 串口调试助手(CM野人版)4.0有严重Bug,已经跟作者反应,等候更新
- 电源芯片选择DC/DC还是LDO?及怎样选择LDO芯片
- 《WEB性能测试实战》之WEB性能测试分析
- 基于LC push的浏览器桌面提醒快速集成方案
热门文章
- Round Robin WRR DRR MiDRR WFQ
- form表单登陆人人网
- 头歌实践教学平台答案(Java实训作业答案)
- python闯关训练营怎么样3.0_【新升级】3周!0基础Python量化投资!闯关式学习打卡,解锁新技能!...
- overleaf使用技巧
- 【Java-Stream篇(groupingBycollectingAndThen)】
- http 502问题解决
- 日语学习日记之先导篇 20211130
- 有关苹果证书介绍(Certificates, Identifiers Profiles)
- python tushare库笔记(5)获取龙虎榜数据