新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 基于STEP FPGA的PS2鍵盤驅(qū)動(dòng)

基于STEP FPGA的PS2鍵盤驅(qū)動(dòng)

作者: 時(shí)間:2023-11-29 來源:電子森林 收藏

硬件說明

我們的STEP-BaseBoard底板上集成了PS2鍵盤的接口,可以供大家連接PS2鍵盤或PS2鼠標(biāo)完成相應(yīng)設(shè)計(jì),接下來我們來了解PS2接口的硬件連接及PS2鍵盤的驅(qū)動(dòng)方法。
PS2接口連線非常簡單,只需接4根線:

本文引用地址:http://2s4d.com/article/202311/453397.htm
  • 4號(hào)引腳VCC接供電電源,一般為5V供電,后經(jīng)測試3.3V也可以
  • 3號(hào)引腳GND接地即可
  • 5號(hào)引腳時(shí)鐘線和1號(hào)引腳數(shù)據(jù)線為兩條雙向的信號(hào)線
  • 2號(hào)引腳和6號(hào)引腳為保留引腳,不需要連接

當(dāng)PS2鍵盤上有按鍵按動(dòng)或操作的時(shí)候,鍵盤會(huì)發(fā)信號(hào)給主機(jī),PS2接口的時(shí)鐘信號(hào)和數(shù)據(jù)信號(hào)的時(shí)序如下圖:

FPGA或主機(jī)接收鍵盤發(fā)回的數(shù)據(jù),通過鍵盤的編碼規(guī)則判定鍵盤當(dāng)前的操作,掃描碼有兩種不同的類型:通碼(make code)和斷碼(break code)。當(dāng)一個(gè)鍵被按下或持續(xù)按住時(shí),鍵盤會(huì)將該鍵的通碼發(fā)送給主機(jī);而當(dāng)一個(gè)鍵被釋放時(shí),鍵盤會(huì)將該鍵的斷碼發(fā)送給主機(jī)。
根據(jù)鍵盤按鍵掃描碼的不同,在此可將按鍵分為如下幾類:

  • 第一類按鍵,通碼為1字節(jié),斷碼為0xF0+通碼形式。如A鍵,其通碼為0x1C,斷碼為0xF0 0x1C。
  • 第二類按鍵,通碼為2字節(jié)0xE0+0xXX形式,斷碼為0xE0+0xF0+0xXX形式。如right ctrl鍵,其通碼為0xE0 0x14,斷碼為0xE0 0xF0 0x14。
  • 第三類特殊按鍵有兩個(gè),print screen鍵通碼為0xE0 0x12 0xE0 0x7C,斷碼為0xE0 0xF0 0x7C 0xE0 0xF0 0x12; pause鍵通碼為0x E1 0x14 0x77 0xE1 0xF0 0x14 0xF0 0x77,斷碼為空。

組合按鍵的掃描碼發(fā)送按照按鍵發(fā)生的次序,如以下面順序按左SHIFT+A鍵:1按下左SHIFT鍵,2按下A鍵,3釋放A鍵,4釋放左SHIFT鍵,那么計(jì)算機(jī)上接收到的一串?dāng)?shù)據(jù)為0x12 0x1C 0xF0 0x1C 0xF0 0x12。
在驅(qū)動(dòng)程序設(shè)計(jì)中,就是根據(jù)這樣的分類來對不同的按鍵進(jìn)行不同處理的,當(dāng)前簡單程序只支持第一類按鍵的操作。
鍵盤中不同按鍵的編碼如下:

Verilog代碼

// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Module: Keyboard_PS2
// 
// Author: Step
// 
// Description: PS2 keyboard driver
// 
// --------------------------------------------------------------------
// Code Revision History :
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.0     |2016/04/20   |Initial ver
// --------------------------------------------------------------------
module Keyboard_PS2
(
input					clk_in,				//系統(tǒng)時(shí)鐘
input					rst_n_in,			//系統(tǒng)復(fù)位,低有效
input					key_clk,			//PS2鍵盤時(shí)鐘輸入
input					key_data,			//PS2鍵盤數(shù)據(jù)輸入
output	reg				key_state,			//鍵盤的按下狀態(tài),按下為1,松開為0
output	reg		[7:0]	key_ascii			//按鍵鍵值對應(yīng)的ASCII編碼); 
/*
這個(gè)模塊為FPGA驅(qū)動(dòng)PS2鍵盤的簡單程序,只能支持鍵盤中第一類按鍵的單鍵按動(dòng),不支持多個(gè)按鍵同時(shí)按動(dòng)
*/ 
reg		key_clk_r0 = 1'b1,key_clk_r1 = 1'b1; 
reg		key_data_r0 = 1'b1,key_data_r1 = 1'b1;
//對鍵盤時(shí)鐘數(shù)據(jù)信號(hào)進(jìn)行延時(shí)鎖存
always @ (posedge clk_in or negedge rst_n_in) begin
	if(!rst_n_in) begin
		key_clk_r0 <= 1'b1;
		key_clk_r1 <= 1'b1;
		key_data_r0 <= 1'b1;
		key_data_r1 <= 1'b1;
	end else begin
		key_clk_r0 <= key_clk;
		key_clk_r1 <= key_clk_r0;
		key_data_r0 <= key_data;
		key_data_r1 <= key_data_r0;
	endend //鍵盤時(shí)鐘信號(hào)下降沿檢測
	wire	key_clk_neg = key_clk_r1 & (~key_clk_r0);  
	reg				[3:0]	cnt; 
	reg				[7:0]	temp_data;
	//根據(jù)鍵盤的時(shí)鐘信號(hào)的下降沿讀取數(shù)據(jù),詳細(xì)參考PS2鍵盤數(shù)據(jù)的傳輸格式及時(shí)序
	always @ (posedge clk_in or negedge rst_n_in) begin
	if(!rst_n_in) begin
		cnt <= 4'd0;
		temp_data <= 8'd0;
	end else if(key_clk_neg) begin 
		if(cnt >= 4'd10) cnt <= 4'd0;
		else cnt <= cnt + 1'b1;
		case (cnt)
			4'd0: ;	//起始位
			4'd1: temp_data[0] <= key_data_r1;  //數(shù)據(jù)位bit0
			4'd2: temp_data[1] <= key_data_r1;  //數(shù)據(jù)位bit1
			4'd3: temp_data[2] <= key_data_r1;  //數(shù)據(jù)位bit2
			4'd4: temp_data[3] <= key_data_r1;  //數(shù)據(jù)位bit3
			4'd5: temp_data[4] <= key_data_r1;  //數(shù)據(jù)位bit4
			4'd6: temp_data[5] <= key_data_r1;  //數(shù)據(jù)位bit5
			4'd7: temp_data[6] <= key_data_r1;  //數(shù)據(jù)位bit6
			4'd8: temp_data[7] <= key_data_r1;  //數(shù)據(jù)位bit7
			4'd9: ;	//校驗(yàn)位
			4'd10:;	//結(jié)束位
			default: ;
		endcase
	end
end 
	reg						key_break = 1'b0;   
	reg				[7:0]	key_byte = 1'b0;//根據(jù)通碼和斷碼判定按鍵的當(dāng)前是按下還是松開
	always @ (posedge clk_in or negedge rst_n_in) begin 
	if(!rst_n_in) begin
		key_break <= 1'b0;
		key_state <= 1'b0;
		key_byte <= 1'b0;
	end else if(cnt==4'd10 && key_clk_neg) begin 
		if(temp_data == 8'hf0) key_break <= 1'b1;	//收到段碼(8'hf0)表示按鍵松開,設(shè)置斷碼標(biāo)示為1
		else if(!key_break) begin 	//當(dāng)斷碼標(biāo)示為0時(shí),表示當(dāng)前數(shù)據(jù)為按下數(shù)據(jù),輸出鍵值并設(shè)置按下標(biāo)示為1
			key_state <= 1'b1;
			key_byte <= temp_data; 
		end else begin	//當(dāng)斷碼標(biāo)示為1時(shí),標(biāo)示當(dāng)前數(shù)據(jù)為松開數(shù)據(jù),斷碼標(biāo)示和按下標(biāo)示都清零
			key_state <= 1'b0;
			key_break <= 1'b0;
		end
	endend //將鍵盤返回的有效鍵值轉(zhuǎn)換為按鍵字母對應(yīng)的ASCII碼值
	always @ (key_byte) begin
	case (key_byte)    //translate key_byte to key_ascii
		8'h15: key_ascii = "Q";//8'h51;   //Q
		8'h1d: key_ascii = "W";//8'h57;   //W
		8'h24: key_ascii = "E";//8'h45;   //E
		8'h2d: key_ascii = "R";//8'h52;   //R
		8'h2c: key_ascii = "T";//8'h54;   //T
		8'h35: key_ascii = "Y";//8'h59;   //Y
		8'h3c: key_ascii = "U";//8'h55;   //U
		8'h43: key_ascii = "I";//8'h49;   //I
		8'h44: key_ascii = "O";//8'h4f;   //O
		8'h4d: key_ascii = "P";//8'h50;   //P
		8'h1c: key_ascii = "A";//8'h41;   //A
		8'h1b: key_ascii = "S";//8'h53;   //S
		8'h23: key_ascii = "D";//8'h44;   //D
		8'h2b: key_ascii = "F";//8'h46;   //F
		8'h34: key_ascii = "G";//8'h47;   //G
		8'h33: key_ascii = "H";//8'h48;   //H
		8'h3b: key_ascii = "J";//8'h4a;   //J
		8'h42: key_ascii = "K";//8'h4b;   //K
		8'h4b: key_ascii = "L";//8'h4c;   //L
		8'h1a: key_ascii = "Z";//8'h5a;   //Z
		8'h22: key_ascii = "X";//8'h58;   //X
		8'h21: key_ascii = "C";//8'h43;   //C
		8'h2a: key_ascii = "V";//8'h56;   //V
		8'h32: key_ascii = "B";//8'h42;   //B
		8'h31: key_ascii = "N";//8'h4e;   //N
		8'h3a: key_ascii = "M";//8'h4d;   //M
		default: ;
	endcase
	end 
	endmodule

小結(jié)

本節(jié)主要為大家講解了PS2接口電路、PS2鍵盤編碼規(guī)則及使用FPGA簡單驅(qū)動(dòng)PS2鍵盤的方法,需要大家掌握的同時(shí)自己創(chuàng)建工程,通過整個(gè)設(shè)計(jì)流程,生成FPGA配置文件加載測試。



評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉