0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

FPGA基礎(chǔ)設(shè)計(jì)_PS2鍵盤(pán)控制及短按、長(zhǎng)按

Hx ? 作者:工程師陳翠 ? 2018-06-26 10:06 ? 次閱讀

PS2鍵盤(pán)也是一個(gè)經(jīng)典的實(shí)驗(yàn),可能很多人接觸如何對(duì)通信協(xié)議、時(shí)序編程就是從這個(gè)實(shí)驗(yàn)開(kāi)始學(xué)習(xí)的。USB鍵盤(pán)已經(jīng)很普及,現(xiàn)在市場(chǎng)上還是有一些USB轉(zhuǎn)PS2的轉(zhuǎn)接頭,還有一些轉(zhuǎn)換芯片。這個(gè)實(shí)驗(yàn)雖然簡(jiǎn)單,不過(guò)不知道您有考慮過(guò)單按一次輸出一個(gè)有效脈沖、短按、長(zhǎng)按等這些是如何實(shí)現(xiàn)的么?這就涉及到一些時(shí)鐘、邊沿檢測(cè)等設(shè)計(jì)問(wèn)題。

PS2協(xié)議實(shí)現(xiàn)

我們見(jiàn)到的PS2的接口電路應(yīng)該都是這樣的:

FPGA基礎(chǔ)設(shè)計(jì)_PS2鍵盤(pán)控制及短按、長(zhǎng)按

一根時(shí)鐘線、一根數(shù)據(jù)線完成通信,PS2通信的幀格式如下所示,時(shí)鐘的下降沿?cái)?shù)據(jù)有效:

FPGA基礎(chǔ)設(shè)計(jì)_PS2鍵盤(pán)控制及短按、長(zhǎng)按

按鍵在被按下時(shí),會(huì)發(fā)送一個(gè)字節(jié),這個(gè)碼就是通碼;按鍵在釋放時(shí),會(huì)發(fā)送兩個(gè)字節(jié),這個(gè)碼就做斷碼(當(dāng)然也有例外)。每一個(gè)按鍵都有唯一的通碼和斷碼,據(jù)此進(jìn)行判斷按下的是哪個(gè)鍵,從而執(zhí)行對(duì)應(yīng)的功能。如一部分按鍵的通碼和斷碼如下所示:

FPGA基礎(chǔ)設(shè)計(jì)_PS2鍵盤(pán)控制及短按、長(zhǎng)按

可以看出斷碼其實(shí)就是在通碼前加了一個(gè)F0,比如A的通碼是1C,則它的斷碼是F01C。另外一些特殊功能的按鍵,在通碼和斷碼前都會(huì)加個(gè)E0。PS2解碼的代碼如下所示:

//-----------------ps2_clk下降沿捕獲--------------------

//clk相當(dāng)于中間采樣點(diǎn)的作用,第一個(gè)下降沿到來(lái)說(shuō)明起始位開(kāi)始

reg ps2_clk0, ps2_clk1, ps2_clk2;//緩沖寄存器

wire ps2_clk_neg; //1表示檢測(cè)到下降沿

reg ps2_state;

always @ (posedge clk or negedge rst_n)

if (!rst_n)

{ps2_clk0, ps2_clk1, ps2_clk2} 《= 3‘d0;

else

begin

ps2_clk0 《= ps2_clk;

ps2_clk1 《= ps2_clk0;

ps2_clk2 《= ps2_clk1;

end

assign ps2_clk_neg = ~ps2_clk1 & ps2_clk2;

//----------------------數(shù)據(jù)接收----------------------------

reg [3:0]num; //移位控制

reg [7:0]data_temp;//當(dāng)前接收的數(shù)據(jù)

always @ (posedge clk or negedge rst_n)

if (!rst_n)

begin

num 《= 4’d0;

data_temp 《= 8‘d0;

end

else if (ps2_clk_neg)

begin

if (num == 0) num 《= num + 1’b1;//跳過(guò)起始位

else if (num 《= 8) //數(shù)據(jù)位賦值

begin

num 《= num + 1‘b1;

data_temp[num-1] 《= ps2_data;

end

else if (num == 9) num 《= num + 1’b1;//跳過(guò)校驗(yàn)位

else num 《= 4‘d0; //清0

end

//--------------------按鍵按下/松開(kāi)檢測(cè)-------------------------

reg ps2_loosen;//1表示按鍵松開(kāi)

reg [7:0]ps2_byte;//ps2一個(gè)字節(jié)數(shù)據(jù)

always @ (posedge clk or negedge rst_n)

if (!rst_n)

begin

ps2_state 《= 1’b0;

ps2_loosen《= 1‘b0;

end

//每接收完一個(gè)數(shù)據(jù)就進(jìn)行按鍵檢測(cè)

else if (num == 4’d10)

if (data_temp == 8‘hf0) ps2_loosen 《= 1’b1;//斷碼標(biāo)識(shí)符

else

begin

if (ps2_loosen) //1表示按鍵松開(kāi),下一次接收數(shù)據(jù)后清0

begin

ps2_state 《= 1‘b0;

ps2_loosen《= 1’b0;

end

else //loosen變0后的下一個(gè)數(shù)據(jù)表示按鍵被按下

begin

ps2_state 《= 1‘b1;

ps2_byte 《= data_temp; //把讀取到的值賦給ps2_out

end

end

由于PS2通信是在PS2時(shí)鐘的下降沿有效,因此第一個(gè)always使用三個(gè)寄存器對(duì)PS2的CLK做一個(gè)下降沿捕獲,并輸出一個(gè)ps2下降沿的有效信號(hào)。

捕捉到了ps2時(shí)鐘的下降沿,第二個(gè)always便是使用一個(gè)計(jì)數(shù)器在下降沿信號(hào)有效時(shí)讀取并存儲(chǔ)數(shù)據(jù)線上的數(shù)據(jù)。計(jì)數(shù)器的值正好對(duì)應(yīng)著一幀中的通信格式,因此在計(jì)數(shù)器為0時(shí)為通信的起始位,1~8為數(shù)據(jù)位,9為校驗(yàn)位,10為停止位。計(jì)數(shù)器處于數(shù)據(jù)位期間內(nèi),將數(shù)據(jù)位依次存儲(chǔ)到一個(gè)寄存器中。

得到了數(shù)據(jù),第三個(gè)always進(jìn)行的便是通信數(shù)據(jù)的判斷,這里進(jìn)行的是斷碼的判斷。每當(dāng)完成一幀通信時(shí),即計(jì)數(shù)器計(jì)數(shù)到10(停止位)時(shí),便對(duì)通信數(shù)據(jù)做判斷,如果是f0,則為斷碼的第一個(gè)碼,那么下一次通信來(lái)的必然是按鍵的鍵值碼。因此將收到f0后的下一個(gè)通信數(shù)據(jù)作為按鍵的鍵值碼存到一個(gè)寄存器中,同時(shí)將按鍵有效信號(hào)ps2_state置高,表示按下一次按鍵。

這樣便完成了PS2的通信。

PS2按鍵判斷

設(shè)想一個(gè)問(wèn)題,假設(shè)兩個(gè)模塊,他們的時(shí)鐘是一樣的,模塊一用來(lái)進(jìn)行PS2鍵盤(pán)檢測(cè),模塊二根據(jù)按鍵按下的有效信號(hào)來(lái)決定是否執(zhí)行對(duì)應(yīng)的操作。如果模塊二采用同步設(shè)計(jì),即由時(shí)鐘來(lái)控制(通常也是這么做的),如果模塊一輸出的按鍵有效信號(hào)不能做到恰好只維持一個(gè)時(shí)鐘的脈沖寬度,那么模塊二就會(huì)多次檢測(cè)到按鍵按下并觸發(fā)多次對(duì)應(yīng)的控制操作。這也是新手常遇到的問(wèn)題。

如果模塊一的時(shí)鐘是模塊二時(shí)鐘的兩倍呢?如果這個(gè)時(shí)候模塊一輸出的按鍵有效信號(hào)仍然只有一個(gè)脈沖,那么模塊二就會(huì)恰好檢測(cè)不到。因此模塊一輸出的按鍵有效信號(hào)應(yīng)該維持兩個(gè)時(shí)鐘的脈沖寬度。而這可以用一個(gè)計(jì)數(shù)器來(lái)控制。

我這里舉一個(gè)只輸出一個(gè)時(shí)鐘長(zhǎng)度的有效信號(hào)的例子:

reg ps2state_reg;

wire flag;

always @ (posedge clk)

ps2state_reg 《= ps2_state;

assign flag = (ps2state_reg) & (~ps2_state);

//---------------------根據(jù)鍵盤(pán)掃描碼輸出按鍵有效信號(hào)?--------------------------

always @ (posedge clk or negedge rst_n)

if (!rst_n)

begin left 《= 0; right 《= 0; up 《= 0; down 《= 0; end

else if (flag) //每當(dāng)松開(kāi)按鍵時(shí)才進(jìn)行輸出

case (ps2_byte)

8’h1C: begin left 《= 1; end //a

8‘h23: begin right 《= 1; end //d

8’h1D: begin up 《= 1; end //w

8‘h1B: begin down 《= 1; end //s

default: begin left 《= 0; right 《= 0; up 《= 0; down 《= 0; end

endcase

else if (left) left 《= 0; //有按鍵有效信號(hào)輸出一個(gè)脈沖后馬上清零

else if (right) right 《= 0;

else if (up) up 《= 0;

else if (down) down 《= 0;

首先對(duì)按鍵狀態(tài)ps2_state做一級(jí)寄存,然后進(jìn)行邊沿檢測(cè),那么在alwasy中檢測(cè)到邊沿有效時(shí)則表示按鍵按下了一次,根據(jù)鍵碼將相應(yīng)的按鍵有效信號(hào)置1。而當(dāng)檢測(cè)到有效信號(hào)為高時(shí),在下一個(gè)時(shí)鐘馬上就拉低,從而實(shí)現(xiàn)只輸出一個(gè)時(shí)鐘的脈沖寬度。這樣就不會(huì)引起錯(cuò)誤的檢測(cè)到多次按下的問(wèn)題。

我們?cè)谕嬗螒虻臅r(shí)候還會(huì)碰到這種情況,需要長(zhǎng)按一個(gè)鍵幾秒鐘才會(huì)有相應(yīng)的反應(yīng),其實(shí)解決了上面的問(wèn)題后我們對(duì)這種短按、長(zhǎng)按的控制思路就很清楚了。簡(jiǎn)而言之,在模塊一中使用計(jì)數(shù)器來(lái)控制輸出的有效信號(hào)的時(shí)鐘長(zhǎng)度,在模塊二中使用相同的計(jì)數(shù)器對(duì)這個(gè)有效信號(hào)的時(shí)鐘長(zhǎng)度進(jìn)行判斷,進(jìn)而識(shí)別這個(gè)鍵到底是短按還是長(zhǎng)按,以選擇不同的操作。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1625

    文章

    21620

    瀏覽量

    601232
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    簡(jiǎn)單解碼PS2鍵盤(pán)

    簡(jiǎn)單的解碼PS2鍵盤(pán)的W/A/S/D四個(gè)按鍵,用來(lái)控制H橋,從而控制小車(chē)行進(jìn)的方向
    發(fā)表于 07-08 19:02

    ps2鍵盤(pán) 協(xié)議

    我想請(qǐng)教下ps2協(xié)議如果鍵盤(pán)一直不按的話 ps2協(xié)議中時(shí)鐘一直是高電平嗎
    發(fā)表于 01-27 10:25

    【小梅哥FPGA進(jìn)階教程】第六章 PS2鍵盤(pán)驅(qū)動(dòng)設(shè)計(jì)與驗(yàn)證

    的信息。在pc機(jī)上,我們經(jīng)常使用104鍵的鍵盤(pán),這種鍵盤(pán)與pc機(jī)的接口,可分為USB接口和PS2接口,我們FPGA要實(shí)現(xiàn)USB接口比較困難,因?yàn)閁SB的接口線路,不是標(biāo)準(zhǔn)的TTL電平,
    發(fā)表于 02-04 23:01

    使用FPGA驅(qū)動(dòng)采用PS2接口的pc機(jī)鍵盤(pán)

    小梅哥和你一起深入學(xué)習(xí)FPGAPS2鍵盤(pán)驅(qū)動(dòng) 在我們的電子系統(tǒng)中,當(dāng)需要用到大量的按鍵輸入時(shí),普通的獨(dú)立按鍵和矩陣鍵盤(pán)已經(jīng)無(wú)法滿足我們的輸入需求,這個(gè)時(shí)候,我們需要使用一種功能更加強(qiáng)
    發(fā)表于 04-28 06:06

    USB1口數(shù)據(jù)線上的PS2鍵盤(pán)有問(wèn)題該怎么解決

    在A40i核心板的USB1口的數(shù)據(jù)線上,通過(guò)WIT122U芯片實(shí)現(xiàn)一個(gè)PS2接口。在該PS2接口上接PS2鍵盤(pán),發(fā)現(xiàn)按下鍵盤(pán)不松手的情況下,
    發(fā)表于 12-31 06:08

    PS2鍵盤(pán)接口引腳定義圖

    PS2鍵盤(pán)接口引腳定義圖 PS/2 鍵盤(pán)接口為 6 針母插,外觀為: 
    發(fā)表于 11-27 12:36 ?4.3w次閱讀
    <b class='flag-5'>PS2</b><b class='flag-5'>鍵盤(pán)</b>接口引腳定義圖

    基于FPGAPS2鍵盤(pán)鼠標(biāo)控制電子琴

    基于 FPGAPS2鍵盤(pán)鼠標(biāo)控制電子琴論文
    發(fā)表于 10-29 17:18 ?31次下載

    PS2鍵盤(pán)接口,通過(guò)串口打印

    PS2鍵盤(pán)接口,通過(guò)串口打印,有興趣的同學(xué)可以下載學(xué)習(xí)
    發(fā)表于 04-27 15:51 ?11次下載

    PS2鍵盤(pán)控制程序

    Xilinx FPGA工程例子源碼:PS2鍵盤(pán)控制程序
    發(fā)表于 06-07 14:45 ?17次下載

    華清遠(yuǎn)見(jiàn)FPGA代碼-PS2接口控制

    華清遠(yuǎn)見(jiàn)FPGA代碼-PS2接口控制
    發(fā)表于 10-27 18:07 ?8次下載

    PS2鍵盤(pán)轉(zhuǎn)USB鍵盤(pán)源碼

    PS2鍵盤(pán)轉(zhuǎn)USB鍵盤(pán)
    發(fā)表于 05-04 11:52 ?11次下載

    關(guān)于PS2鍵盤(pán)與單片機(jī)通信

      PS2鍵盤(pán)與單片機(jī)通信的方法與原理說(shuō)明。
    發(fā)表于 08-30 15:21 ?25次下載
    關(guān)于<b class='flag-5'>PS2</b><b class='flag-5'>鍵盤(pán)</b>與單片機(jī)通信

    MCU驅(qū)動(dòng)PS2鍵盤(pán)

    MCU驅(qū)動(dòng)PS2鍵盤(pán)
    發(fā)表于 10-27 14:39 ?17次下載
    MCU驅(qū)動(dòng)<b class='flag-5'>PS2</b><b class='flag-5'>鍵盤(pán)</b>

    PS2鍵盤(pán)在單片機(jī)系統(tǒng)中的應(yīng)用

    PS2鍵盤(pán)在單片機(jī)系統(tǒng)中的應(yīng)用
    發(fā)表于 10-27 14:41 ?17次下載
    <b class='flag-5'>PS2</b><b class='flag-5'>鍵盤(pán)</b>在單片機(jī)系統(tǒng)中的應(yīng)用

    FPGA DIY開(kāi)發(fā)板的PS2鍵盤(pán)控制

    hahaolinux 的PS2鍵盤(pán)控制。
    的頭像 發(fā)表于 06-22 00:29 ?4326次閱讀