FPGA控制的PS2接口电路设计

xiaoxiao 2019-3-28 5

 
FPGA控制的PS/2接口电路设计 
*** 
(电信科071班 ***********) 
摘要:介绍了FPGA控制的PS/2接口电路的设计。FPGA控制电路能够识别PS/2键盘按键,并将按键的扫描码与对应ASCII码显示在数码管上,且将上述所有内容按要求显示在1602液晶屏上。 
关键字:FPGA;键盘接口;键盘扫描;数码显示 
Design of PS/2 port circuit controlled by FPGA  
Zhang Lijuan 
Abstract:this paper introduces the design of PS/2 port circuit controled by FPGA.The circuit controled by FPGA can identify PS/2 push-button,and display it’s scan code corresponding ASCII on Nixie tube,and all above will be displayed in the LCD screen 1602 as required. 
Keywords: FPGA;keyboard port; keyboard scan; Nixie display 
引言:作为计算机最常用输入设备键盘,最早使用的是的PC/AT机的84键的键盘,现在使用的是增强型的,键盘是嵌入式系统的最重要的输入设备之一,是实现人机交互的重要途径。键盘接口的主要电路是用Intel 8042 单片机作键盘控制,该芯片能够实现键盘接口的全部功能,可以将键盘扫描码转换成系统ASCII码,同时还实现了键盘和CPU之间的双向传输功能。 
PS/2接口电路的工作原理:PS/2协议和接口最初是IBM公司开发并推广使用的一种应用于键盘/鼠标的协议和接口,PS/2键盘按键接口是6芯的插头与PC机的键盘相连接,插头、插座定义如图1所示。 
 
图1  PS/2键盘(鼠标)接口 
 
 
图2  键盘收发数据时序图 
 
实际上6芯中要使用的信号时4个管脚:电源和地各占一个,除了电源线VCC和地线GND之外,另外两个是键盘和键盘接口之间的两条双向通信线:时钟线CLK和数据线DATA。PS/2键盘(或鼠标)都采取双向串行同步传输方式。双向式指既可以发送数据到主机,主机也可以发送数据到设备。串行指的是每次
 
 
数据线上发送一位数据也要在时钟线上发一个脉冲数据才能被读入,在整个时钟脉冲作用下同步地收发数据,如图2所示。 
数据格式: 
从键盘/鼠标发送到主机的数据是在时钟的下降沿时被读取,而从主机发送到键盘/鼠标是在时钟的上升沿时被读取。主机要传送的数据包含了11"12位,组成一帧数据,格式如下: 1个起始位 8个数据位 1个校奇偶验位 1个停止位 1个应答位 总是逻辑0 (LSB)低位在前 奇校验 总是逻辑1 仅用在主机对设备的通讯中 表1键盘收发数据格式 表中,如果数据位中1的个数为偶数,校验位就为1;如果数据位中1的个数为奇数,校验位就为0;总之,数据位中1的个数加上校验位中1的个数总为奇数,因此总进行奇校验。 
PS口的5V供电由是源的待机电压5V提供,通过保险电阻、电感L5至PS/2接口的供电脚,为其供电。PS/2口的第一针与第七o针为数据脚,通过电容、电感至IO,第5脚与第11脚为时钟脚,同样通过电容电感至IO。 通信过程: 
设备到主机的通信过程: 
键盘/鼠标接口的数据线和时钟线采用集电极开路结构,平时都是高电平当这些设备等待发送数据时,它首先检查clock是否为高。如果为低,则认为PC抑制了通讯,此时它缓冲数据直到获得总线的控制权。如果clock为高电平,设备则开始向PC发送数据。一般都是由ps2设备产生时钟信号。发送按帧格式。数据位在clock为高电平时准备好,在clock下降沿被PC读入。图3所示是按下Q键的时序图“Q”键的扫描码从键盘发送到计算机(通道A是时钟信号,通道B是数据信号)。 
常用时钟频率为10"16.7时,由于主机在clock的下降沿读取数据,因此数据必须在半个时钟周期内转换完毕,并在锁存数据的下降沿前至少要5μs的保持时间,如果按最高20KHZ的时钟功率来算,数据变化到稳定的时间应该时钟clock下降沿出现前至少5μs,但不能大于25μs,这是由PS/2通讯协议的时序规定的。  
 
 
 
图3  按下Q键产生的扫描码时序 
1. 主机到设备的通信过程 
主机到设备的通信过程与设备到主机的通信过程有的不同。 
由于PS/2设备能提供串行同步时钟,如果主机要发送数据,就要先把时钟线和数据线置为请求发送的状态: 
●PC机通过下拉时钟线大于100μs来抑制通讯; 
●通过下拉数据线发出请求发送数据的信号,然后释放时钟。 
当PS/2设备检测到需要接收的数据时,它会产生时钟信号并记录下面8数据位和一个停止位。主机此时在时钟线变为低时准备数据到数据线,并在时钟上升沿锁存数据。主机可以再第11个时钟脉冲应答位前只要下拉时钟脉冲应答位前只要下拉时钟线至少100μs就可以终止一次传送。而PS/2设备则要配合PC机才能读到准确的数据。 
如果主机在第11个时钟后部释放数据线,设备将继续产生时钟脉冲直到数据被释放,然后设备将产生一个错误信息。 
程序设计流程 
一、键盘扫描过程 
键盘的处理器如果发现有键被按下或释放将发送扫描码的信息包到计算机。扫描码有两种不同的类型:通码和断码。当一个键被按下就发送通码,当一个键被释放就发送断码。每个按键被分配了唯一的通码和断码。这样主机通过查找唯一的扫描码就可以测定是哪个按键。每个键一整套的通断码组成了扫描码集。有
 
 
三套标准的扫描码集。现代所有的键盘默认使用第二套扫描码。     传输和转换的实现方法如下: 
第一部分是串并转换。由于键盘的有效端口为一个数据和一个时钟,芯片要接受键盘的时钟和数据,并进行串并转换把它转换成键盘要发送的扫描码,最后将扫描码转换成ASCII码,转换后的结果通过中断方式送给数据总线。 
串并转换部分在电路实现上用移位寄存器,并在数据转换部分采用一个随着时钟变化的计数器,在时钟的下降沿,首先把采样的数据值赋给相应的并行数据的某一位,然后计数器自增。使用计数器是由于转换成ASCII码时需要先去除一帧数据的起始位、校验位和停止位,需要进行串并转换的只是其中的8位数据。 
第二部分是将扫描码转换成ASCII码。首先要做到的是建立一个大的对照表。由于扫描码与ASCII码之间没有现成的对应公式。在此过程中的难点是键的按下与放开时的检测以及Shift键和Capslock键在不同的状态下的控制逻辑。下面的设计实例采用的是D触发器实现时需要记忆元件来保存这些特殊的键的状态。PS/2接口的设计中整合了并行接口数据的输入功能,主要包括:数据准备好后发出中断,读信号来后将中断置位,无读信号时数据线置高阻等。设计时没有使用非STB信号,而是根据PS/2接口传输数据的要求让逻辑来监测数据有没有准备好,是否需要发出中断信号。 
分解设计: 
1、接收键盘数据并转换位扫描码 
由于键盘的有效端口为一个数据和一个时钟,芯片要接受键盘的时钟和数据,并进行串并转换把它转换成键盘要发送的扫描码,最后将扫描码转换成ASCII码,转换后的结果通过中断方式送给数据总线。 
在数据转换部分采用一个随着时钟变化的计数器,在时钟的下降沿,首先把采样的数据值赋给相应的并行数据的某一位,然后计数器自增。使用计数器是由于转换成ASCII码时需要先去除一帧数据的起始位、校验位和停止位,即进行串并转换的只是其中的8位数据。 
具体在程序中的实现为: 
(1)在实体中包括一个复位键rst即高电平有效,一个系统时钟s_clk,键盘时钟k_clk,键盘发送的每一位数据k_data,输出端口则为:data键盘发送的有效数据,ZHJS扫描码转换结束信号即转换结束置为0,PA扫描码输出 
(2)结构体中,定义 tmp用来记录一帧串行数据;定义en为0,即为辅助信号,表示什么时候可以把串行数据输出到PA端 
(3)进程中,定义变量start,用来把en信号赋值;变量cnt,范围为0—11,是一个随着时钟信号变化的计数器。进程中k_clk为敏感信号量,在其下降沿进行数据操作,采样数据赋值到tmp的cnt位。如果cnt 为10,则ZHJS为0,表示扫描码转换结束,否则相反。若cnt为11,则下一个为1,否则自增;若1'0');   --记录每一帧的数据 
 signal p_kbclk,c_kbclk:std_logic; 
 signal en:std_logic;                                  --输出使能  begin 
 process(rst,s_clk,k_clk)                              --得到键盘发送的有效数据扫描码 
  variable cnt:integer range 0 to 11:=0; 
 
 
 
  variable start:std_logic:='0';  begin   if rst='0' then cnt:=0;ZHJSc_kbclk then                             tmp(cnt)=1 and cnt'0') when en='1' else   tmp(8 downto 1); end; 
二、扫描码转换成ASCII码 D触发器源程序代码: library ieee; 
use ieee.std_logic_1164.all; entity myd is 
port(clk,data:in std_logic; 
            q:out std_logic); end ; 
architecture one of myd is begin 
process(clk) begin 
if(rising_edge(clk)) then       q16#40#) and (tmpbtbtbtbtnull;  end case; end process; process(a)    begin 
 case a is 
  when \  when \  when \  when \  when \  when \  when \  when \  when \  when \  when \  when \  when \  when \  when \  when \  when others=>null;  end case;   end process ; end; 
四、液晶显示扫描码与ASCII码程序代码: library ieee; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; entity lcd1602 is 
port(clk,rst:in std_logic; 
 scan; ASC:in std_logic_vector(7 downto 0);   data:out bit_ vector (7 downto 0);  rs,rw,en:out bit); end; 
architecture one of lcd1602 is 
 signal b:integer range 0 to 25000000;  signal cp50:bit; 
 signal cnt_disp:integer range 0 to 50;  signal cnt_init:integer range 0 to 5;  
 
 
 signal sc_1tmp,sc_2tmp,ASC_1tmp,ASC_tmp2:integer range 0 to 16;  signal sc_1,sc_2,ASC_1,ASC_2: std_logic_vector(7 downto 0); begin    
 sc_1tmpsc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_1sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2sc_2ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_1ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2ASC_2<=x\  end case;  end process;  process(clk) 
 
 
 begin 
  if falling_edge(clk) then    if b=499999 then     b<=0; 
    cp50<=not cp50;    else b<=b 1;    end if;   end if;  end process; process(cp50)  begin 
  if cp50'event and cp50='1' then    if cnt_disp=26 then     cnt_disp<=0; 
   else cnt_disp<=cnt_disp 1;    end if;   end if;    
  if cp50'event and cp50='1' then    if cnt_init=3 then     cnt_init<=0; 
   else cnt_init<=cnt_init 1;    end if;   end if;  end process;   
 process(rst,cnt_disp,cnt_init,cp50,sc_1,sc_2,ASC_1,ASC_2)  begin 
  if (rst='0') then 
   if cnt_init=0 then     if cp50='0' then 
     rs<='0';rw<='0';data<=x\    end if; 
   elsif cnt_init=1 then     if cp50='0' then 
     rs<='0';rw<='0';data<=x\    end if; 
   elsif cnt_init=2 then     if cp50='0' then 
     rs<='0';rw<='0';data<=x\    end if; 
   elsif cnt_init=3 then     if cp50='0' then 
     rs<='0';rw<='0';data<=x\
 
 
                                            
 
                                              end if;  end if; else 
 if cnt_disp=0 then   if cp50='0' then 
   rs<='0';rw<='0';data<=x\  end if; 
 elsif cnt_disp=1 then   if cp50='0' then 
   rs<='1';rw<='0';data<=x\  end if; 
 elsif cnt_disp=2 then   if cp50='0' then 
   rs<='1';rw<='0';data<=x\  end if; 
 elsif cnt_disp=3 then   if cp50='0' then 
   rs<='1';rw<='0';data<=x\  end if; 
 elsif cnt_disp=4 then   if cp50='0' then 
   rs<='1';rw<='0';data<=x\  end if; 
 elsif cnt_disp=5 then   if cp50='0' then 
   rs<='1';rw<='0';data<=x\  end if; 
 elsif cnt_disp=6 then   if cp50='0' then 
   rs<='1';rw<='0';data<=x\  end if; 
 elsif cnt_disp=7 then   if cp50='0' then 
   rs<='1';rw<='0';data<=x\  end if; 
 elsif cnt_disp=8 then   if cp50='0' then 
   rs<='1';rw<='0';data<=x\  end if; 
 elsif cnt_disp=9 then   if cp50='0' then 
   rs<='1';rw<='0';data<=x\  end if; 
 elsif cnt_disp=10 then 
 
                                            
 
                                                                                         if cp50='0' then 
  rs<='1';rw<='0';data<=x\ end if; 
elsif cnt_disp=11 then  if cp50='0' then 
  rs<='1';rw<='0';data<=to_bitvector(sc_1);--*  end if; 
elsif cnt_disp=12 then  if cp50='0' then 
  rs<='1';rw<='0';data<=to_bitvector(sc_2);--*  end if; 
elsif cnt_disp=13 then  if cp50='0' then 
  rs<='0';rw<='0';data<=x\ end if; 
elsif cnt_disp=14 then  if cp50='0' then 
  rs<='1';rw<='0';data<=x\ end if; 
elsif cnt_disp=15 then  if cp50='0' then 
  rs<='1';rw<='0';data<=x\ end if; 
elsif cnt_disp=16 then  if cp50='0' then 
  rs<='1';rw<='0';data<=x\ end if; 
 elsif cnt_disp=17 then  if cp50='0' then 
  rs<='1';rw<='0';data<=x\ end if; 
elsif cnt_disp=18 then  if cp50='0' then 
  rs<='1';rw<='0';data<=x\ end if; 
elsif cnt_disp=19 then  if cp50='0' then 
  rs<='1';rw<='0';data<=x\ end if; 
elsif cnt_disp=20 then  if cp50='0' then 
  rs<='1';rw<='0';data<=x\ end if; 
elsif cnt_disp=21 then 
 
    if cp50='0' then 
     rs<='1';rw<='0';data<=x\    end if; 
   elsif cnt_disp=22 then     if cp50='0' then 
     rs<='1';rw<='0';data<=x\    end if; 
   elsif cnt_disp=23 then     if cp50='0' then 
     rs<='1';rw<='0';data<=x\    end if; 
   elsif cnt_disp=24 then     if cp50='0' then 
     rs<='1';rw<='0';data<=x\    end if; 
   elsif cnt_disp=25 then     if cp50='0' then 
     rs<='1';rw<='0';data<=to_bitvector(ASC_1);--*     end if; 
   elsif cnt_disp=26 then     if cp50='0' then 
     rs<='1';rw<='0';data<=to_bitvector(ASC_2);--*     end if;    end if;   end if;  end process;  en<=cp50; end; 
 

12345

[b]福利:打开支付宝首页搜索“608066754”即可领取红包,吃个早点,买杯饮料肯定够了,红包加倍最高可以领取99元红包![/b]
最新回复 (0)
返回
免责申明:本站点所有资源来自互联网网友发布,如侵犯您的合法权益,请联系zzjfuture@gmail.com,我们立刻处理。 @2010-2020 技术支持: 成都软件开发