FPGA模拟PS2协议,丢掉4x4键盘,来用标准键盘吧!
本来以为模拟PS2协议相当的麻烦,今天下了一本PS2协议手册看了半天,原来读键盘值相当简单嘛,比模拟SPI、I2C简单多了呵呵。下面介绍一下具体过程
1.明确接线关系,只需接4根线,VCC要+5V,刚刚又测试过,3.3V也可以用。时钟和数据线要用bidir双向口线,FPGA可以不用外接上拉电阻。另外,USB键盘也可以用,只要用一个转接头转成PS2即可。
http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_193392.jpg
2.读取基本的键盘数据,不需要FPGA发送任何数据,只需读取键盘发回来的数据即可
如下面的时序图,每次键盘发送11个clock信号,我们需要做的事情就是在时钟的下降沿读取数据
http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_193393.JPG
3.如何来采样CLK低电平?
这里可以用一个FIFO来储存数据,如下面的程序,当ps2_clk信号处于下降沿时,ps2_clk_fallingedge值将被置高
reg ps2_clkr;//用一个fifo来采样ps2_clk信号;
always @(posedge clk)
ps2_clkr <= {ps2_clkr, ps2_clk};
wire ps2_clk_risingedge = (ps2_clkr==2'b01); // now we can detect ps2_clk rising edges
wire ps2_clk_fallingedge = (ps2_clkr==2'b10); // and falling edges
4.当检测到第一个低电平时,我们只需要连续读取11个周期值就可以了,这里用一个变量i来控制
always @(posedge clk)
if(rst)
i <= 0;
else
begin
if(ps2_clk_fallingedge)
begin
data2 <= data;
data <= ps2_data;
if(i<10) i <= i+1;
else i <= 0;
end
end
最后来解释下这11个数据的功能,如下表
http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_193394.jpg
5.如果想进一步区分键值,就需要查表了,如下表
http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_193395.jpg
基本按键,键盘会发送“F0”+“键码”
扩展按键,则发送“E0”+“F0”+“键码”
大家都来试一下吧,一个下午就能搞定!
附程序,晶振频率降至1MHz,用LED输出键值
//==============================================================
module ps2(clk, rst, ps2_clk, ps2_data, data ,data2);
input clk, rst;
inout ps2_clk, ps2_data;
output data;
output data2;
reg i;
reg data;//another fifo
reg data2;
reg ps2_clkr;//用一个fifo来采样ps2_clk信号;
always @(posedge clk)
ps2_clkr <= {ps2_clkr, ps2_clk};
wire ps2_clk_risingedge = (ps2_clkr==2'b01); // now we can detect ps2_clk rising edges
wire ps2_clk_fallingedge = (ps2_clkr==2'b10); // and falling edges
always @(posedge clk)
if(rst)
i <= 0;
else
begin
if(ps2_clk_fallingedge)
begin
data2 <= data;
data <= ps2_data;
if(i<10) i <= i+1;
else i <= 0;
end
end
endmodule
//========================================================
点击此处打开ourdev_193396.JPG(文件大小:562K,只有300K以内的图片才能直接显示)
最后送上PS2协议中英文文档,非常详细
点击此处打开ourdev_193397.pdf(文件大小:667K) 感谢,先收藏了! 谢谢!楼主这方面很牛啊! 不错,看来真不复杂,回头在avr上搞一个 谢谢 好样的,先做个记号,等有用时再看。 PS2键盘我也在用,感觉还是用2个I/O口(最好有一个外中断引脚)简单,实在没有必要劳烦CPLD。添加不了多少代码。另外楼主提到的都是断码信息,我认为最好识别通码信息。这样敲打键盘的感觉会好一些。另外没有用到部分比如扩展键EO开头的,或者E1开头的,以及键盘的检测信息AA等都要处理否则,容易出错,起始位的判别对抑制干扰也很重要,不可忽略。 还有一点要说的就是外中断里面读PS2数据,最好设置FIFO,这样就可以在主程序里面解码。 http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_193453.jpg
http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_193454.jpg 楼上的,什么是FIFO? First In, First Out. 最近在学FPGA才做的,以前玩AVR还真没有想过用PS2键盘,心里上以为很难
AVR用中断控制,应该也相当简单
要考虑到纠错,扩展键码,就要处理键值了 做上就知道了,疯狂的按键盘测试,比如shift,Ctrl,Alt,按下不释放,让后按扩展键,总之疯狂按多个按键。我用的ARM7,有时数据会错位,后来我把头尾和校验都加入了,疯狂测试了几天没有发现问题。但是我还是觉得超时也是非常有必要加入的。 恩,这样测试,漏掉一个沿触发,数据就不对拉,要加上校验 我的同【6楼】 appleboy
直接用avr io模拟也很好用 收藏备用 记号 我原来也用CPLD解码PS2键盘,问题多多呢,后来用一片专用的82C42,基本上没问题了 这么费劲?太费劲了,FPGA都用上了。
用BASCOM-AVR,里面直接提供的就有 PS2 键盘和鼠标 的通用软件接口,一个语句就搞定了。 http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_193593.gif to 18楼
请认清楚学习的本质,不要一味图方便
学习简单的时序是处理复杂问题的基础,难道你拿到FPGA一开始就搞DDR2、MPG解码?
FPGA只是学习的工具,其原理照样可以用在十几元钱的CPLD上 顶一下 。。。。 楼主强人,做个记号先... 呵呵楼主用的 VERILOG我也来发一个 VHDL的献丑老~~~~~
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity key_ps2 is
Port ( clk : in std_logic;
res : in std_logic;
clk_ps : in std_logic;
date_ps : in std_logic;
date_out : out std_logic_vector(7 downto 0));
end key_ps2;
architecture Behavioral of key_ps2 is
signal clk_f :std_logic;
signal date_r : std_logic_vector(10 downto 0);
begin
fen: process(clk,res)
variable cnt : integer range 0 to 512;
begin
if(res='1') then
clk_f<='0';
cnt:=0;
elsif(clk'event and clk='1') then
if(cnt=511) then
clk_f<='1';
else
clk_f<='0';
end if;
cnt:=cnt+1;
end if;
end process fen;
aa:process(clk_f,clk_ps,date_ps,res)
variable check : std_logic;
variable n : integer range 0 to 12;
variable delay : std_logic_vector(6 downto 0);
variable over :std_logic;
begin
if(res='1') then
check:='0';
over:='0';
date_r<=(others=>'0');
delay:="1100001";
elsif(clk_ps'event and clk_ps='0' and delay="0000000") then
date_r<=date_ps&date_r(10 downto 1);
n:=n+1;
check:=check xor date_ps;
if(n=11) then
n:=0;
over:='1';
else
over:='0';
end if;
end if;
if(over='1') then
if(date_r(0)='0' and date_r(10)='1' and check='0') then
date_out<=date_r(8 downto 1);
end if;
delay:="1100001";
over:='0';
check:='0';
end if;
if(delay>0) then
delay:=delay-1;
end if;
end process aa;
end Behavioral; 记号 在AVR上我是这样纠错的:
首先用示波器测量下相邻两个脉冲的时间T0和相邻两个帧的时间T1,使用定时器做一个时间介于T1和T0超时计数器,并且每次发生外部中断后就清零计数器,当计数器超时立即将PS2的时钟脉冲计数器清零.
我用这种方法进行了2天的不断自动测试,没有发生一次错误.将此献给大家. 好帖!收藏了 ps2 还要涉及到通码断码。在单片机上做没有必要吧做得这么麻烦吧 路过,顶了,以后有时间漫漫研究 记号,谢谢。 VHDL语言用UE编辑,怎么关键字不突出啊?大家一般是用什么编辑的啊? 看了一下图发现楼主的AVR板跟我的一模一样! 学习了! 支持 楼主光顾的板子都很熟悉嘛,呵呵 正在学习,可能以后用到 学习! 好资料,顶一个 顶一下,以后会用到的 强悍啊!!先记下来! 收藏,慢慢研究~~ mark 标记!
以前看师兄们玩过,有空也去弄一个玩:) ... 做个记号! 有些鼠标识别不了?是不是电平不兼容的原因??可以同时兼容两种电平的电路图怎么样的? 做个记号 好厉害,学习一下 学习了 学习啦,呵呵 记号 这论坛咋没收藏功能呢。。只好记号一下。。 很好,收藏待试验。 没时间看了,做个记号下次看了。。。。
以前做过键盘的,就是扩展键没搞定~ mark mark 很好,有增强信心作用 好,FPGA模拟PS2键盘 我也要一个 好东西 mark 收藏备用! 多谢.. 记号。 PS/2是好,但也用不着丢掉4X4吧。
各有各的用途。 mark 好! mark 看看我写的PS2通信程序....
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=2167690&bbs_page_no=1&bbs_id=1029 标记 呵呵,极品 不错,记一个 ok,记号。 嘿嘿,真的是个学习的好素材 好东西,收藏 mark mark 收藏 mark 好东西,不过从实用的角度来说没啥用,楼主再接再劢加油啊,做点更猛烈的东西出来 mark mark mark 顶顶 记号,感谢楼主的分享 好东西 mark thanks 我顶~ MARK 顶之 Good!Mark.... 看看.. mark . 加盖一楼! 楼主或其他各位大大,问个问题,我怎么知道我现在用的鼠标或键盘是5V的还是3.3V的? 幻想要是有中国人能用FPGA模拟个X86通用CPU出来就好了 Mark! mark 马克一下。 好贴