引言
當(dāng)前嵌入式系統(tǒng)技術(shù)已得到了廣泛應(yīng)用,但傳統(tǒng)嵌入式系統(tǒng)的人機(jī)接口多采用小鍵盤操作的文本菜單方式,用戶操作較為不便。本設(shè)計(jì)利用FPGA實(shí)現(xiàn)對(duì)PS/2接口鼠標(biāo)的控制,是在以VGA作為輸出設(shè)備的單片機(jī)系統(tǒng)上初步實(shí)現(xiàn)圖形化用戶界面的方案,它成本低、效果好,并且有很強(qiáng)的實(shí)用性。
FPGA(Field Programmable Gate Array)是 20世紀(jì)80年代中期出現(xiàn)的高密度、可編程邏輯器件,F(xiàn)PGA及其軟件系統(tǒng)是開發(fā)數(shù)字電路的最新技術(shù),它利用EDA技術(shù),以電路原理圖、硬件描述語(yǔ)言及狀態(tài)機(jī)等形式輸入設(shè)計(jì)邏輯,提供功能模擬、時(shí)序仿真等模擬手段,在功能模擬和時(shí)序仿真度滿足要求后,經(jīng)過一系列變換,將輸入邏輯轉(zhuǎn)換成FPGA器件的編程文件,以實(shí)現(xiàn)專用集成電路。本設(shè)計(jì)選用Altera公司推出的CyclONe II系列的EP2C5T144C8 FPGA來設(shè)計(jì)PS/2接口,體積減小,可靠性提高。
PS/2接口和協(xié)議
接口的物理特性
PS/2接口用于許多現(xiàn)代的鼠標(biāo)和鍵盤,由IBM最初開發(fā)和使用。物理上的PS/2接口有兩種類型的連接 器 :5腳的DIN和6腳的MINI-DIN。圖1就是兩種連接器的引腳定義。使用中,主機(jī)提供+5V電源給鼠標(biāo),鼠標(biāo)的地連接到主機(jī)電源地上。
接口協(xié)議原理
PS/2鼠標(biāo)接口采用一種雙向同步串行協(xié)議,即每在時(shí)鐘線上發(fā)一個(gè)脈沖,就在數(shù)據(jù)線上發(fā)送一位數(shù)據(jù)。在相互傳輸中,主機(jī)擁有總線控制權(quán),即它可以在任何時(shí)候抑制鼠標(biāo)的發(fā)送,方法是把時(shí)鐘線一直拉低,鼠標(biāo)就不能產(chǎn)生時(shí)鐘信號(hào)并發(fā)送數(shù)據(jù)。在兩個(gè)方向的傳輸中,時(shí)鐘信號(hào)都由鼠標(biāo)產(chǎn)生,主機(jī)不產(chǎn)生通信時(shí)鐘信號(hào)。
如果主機(jī)要發(fā)送數(shù)據(jù),就必須控制鼠標(biāo)產(chǎn)生時(shí)鐘信號(hào),方法如下:主機(jī)首先下拉時(shí)鐘線至少100μS抑制通信,然后再下拉數(shù)據(jù)線,最后釋放時(shí)鐘線。鼠標(biāo)檢測(cè)到這個(gè)時(shí)序狀態(tài)后,會(huì)在10mS內(nèi)產(chǎn)生時(shí)鐘信號(hào)。如圖3中(A)時(shí)序段。主機(jī)和鼠標(biāo)之間,傳輸數(shù)據(jù)幀的時(shí)序如圖2、圖3所示。
PS/2鼠標(biāo)的工作模式和協(xié)議數(shù)據(jù)包格式
PS/2鼠標(biāo)的四種工作模式
PS/2鼠標(biāo)的四種工作模式分別是:Reset模式,當(dāng)鼠標(biāo)上電或主機(jī)發(fā)復(fù)位命令(0xFF)給它時(shí),進(jìn)入這種模式;STream模式,鼠標(biāo)的默認(rèn)模式,當(dāng)鼠標(biāo)上電或復(fù)位完成后,自動(dòng)進(jìn)入此模式,鼠標(biāo)基本上以此模式工作;Remote模式,只有在主機(jī)發(fā)送了模式設(shè)置命令(0xF0)后,鼠標(biāo)才進(jìn)入這種模式;Wrap模式,這種模式只用于測(cè)試鼠標(biāo)與主機(jī)連接是否正確。
數(shù)據(jù)包結(jié)構(gòu)
PS/2鼠標(biāo)在工作過程中,會(huì)及時(shí)把它的狀態(tài)數(shù)據(jù)發(fā)送給主機(jī)。發(fā)送的數(shù)據(jù)包格式如表1所示。
Byte1中的Bit0、Bit1、Bit2分別表示左、右、中鍵的狀態(tài),狀態(tài)值0表示釋放,1表示按下;Byte2和Byte3分別表示X軸和Y軸方向的移動(dòng)計(jì)量值,是二進(jìn)制補(bǔ)碼值;Byte4的低四位表示滾輪的移動(dòng)計(jì)量值,也是二進(jìn)制補(bǔ)碼值,高四位作為擴(kuò)展符號(hào)位。這種數(shù)據(jù)包由帶滾輪的三鍵三維鼠標(biāo)產(chǎn)生,若是不帶滾輪的三鍵鼠標(biāo),產(chǎn)生的數(shù)據(jù)包沒有Byte4,其余的相同。
VGA信號(hào)時(shí)序
圖4所示是計(jì)算機(jī)VGA(640×480,60Hz)圖像格式的信號(hào)時(shí)序圖,其點(diǎn)時(shí)鐘DCLK為25.175MHz,場(chǎng)頻為59.94Hz。圖中,Vsync為場(chǎng)同步信號(hào),場(chǎng)周期Tvsync為16.683mS,每場(chǎng)有525行,其中480行為有效顯示行,45行為場(chǎng)消隱期。場(chǎng)同步信號(hào)Vs每場(chǎng)有一個(gè)脈沖,該脈沖的低電平寬度twv為63μS(2行)。場(chǎng) 消隱期包括場(chǎng)同步時(shí)間twv、場(chǎng)消隱前肩tHV(13行)和場(chǎng)消隱后肩tVH(30行),共45行。行周期THSYNC為31.78μS,每顯示行包 括800點(diǎn),其中640點(diǎn)為有效顯示,160點(diǎn)為行消隱期(非顯示 區(qū))。行同步信號(hào)Hs每行有一個(gè)脈沖,該脈沖的低電平寬度tWH為3.81μS(即96個(gè)DCLK);行消隱期包括行同步時(shí)間tWH,行消隱前肩tHC(19個(gè)DCLK)和行消隱后肩tCH(45個(gè)DCLK),共160個(gè)點(diǎn)時(shí)鐘。復(fù)合消隱信號(hào)是行消隱信號(hào)和場(chǎng)消隱信號(hào)的邏輯與,在有效顯示期復(fù)合消隱信號(hào)為高電平,在非顯示區(qū)域它是低電平。
設(shè)計(jì)實(shí)現(xiàn)
實(shí)現(xiàn)功能
1、 用FPGA實(shí)現(xiàn)PS/2鼠標(biāo)接口。
2、鼠標(biāo)左鍵按下時(shí)十字形鼠標(biāo)圖象的中間方塊改變顏色,右鍵按下時(shí)箭頭改變顏色。
3、 Reset按鍵:總復(fù)位。
設(shè)計(jì)原理
主機(jī)復(fù)位后,首先向鼠標(biāo)發(fā)送初始化命令(0xf4)。當(dāng)鼠標(biāo)收到命令字后會(huì)給出一個(gè)應(yīng)答字節(jié)(0xfa),主機(jī)根據(jù)應(yīng)答字節(jié)來判斷鼠標(biāo)是否正確應(yīng)答。如果應(yīng)答正確則接收鼠標(biāo)數(shù)據(jù)包,然后從接收到的數(shù)據(jù)包中獲得鼠標(biāo)位置及狀態(tài)數(shù)據(jù),并輸出給顯示模塊。顯示模塊在CRT上顯示出當(dāng)前鼠標(biāo)的狀態(tài)和位置,否則,停止處理。如圖5。
如圖6,當(dāng)狀態(tài)機(jī)m2_state復(fù)位時(shí),即進(jìn)入m2_reset狀態(tài),并在 一個(gè)clk周期后進(jìn)入m2_hold_clk_l狀態(tài),當(dāng)ps2_clk_hi_z(時(shí)鐘線)被拉低并保持400μS后進(jìn)入m2_data_low_1狀態(tài),此時(shí)向鼠標(biāo) 發(fā)送起始 位和d[0]、d[1](d[0]=d[1]=0)。完成后進(jìn)入m2_data_high_1狀態(tài), 發(fā)送d[2](d[2]=1)并進(jìn)入m2_data_low_2狀態(tài),此時(shí)向鼠標(biāo)發(fā)送d[3]位(d[3]=0), 完成發(fā)送進(jìn)入m2_data_high_2狀態(tài),向鼠標(biāo)發(fā)送d[4]、d[5]、d[6]、d[7](d[4]=d[5]=d[6]=d[7]=1),完成發(fā)送進(jìn)入m2_data_low_3狀 態(tài),向鼠標(biāo)發(fā)送奇偶校驗(yàn)位,然后進(jìn)入m2_data_high_3狀態(tài),將數(shù)據(jù)線拉高,等待鼠標(biāo)返回應(yīng)答信號(hào)。若PS/2時(shí)鐘信號(hào)下降沿來臨時(shí),數(shù)據(jù)線仍未變?yōu)楦唠娖?,則進(jìn)入m2_error_no_ack狀態(tài),此時(shí)握手失敗,系統(tǒng)將保持m2_error_no_ack狀態(tài)直到下一次復(fù)位,否則進(jìn)入m2_await_response狀態(tài)接收應(yīng)答字,接收完成進(jìn)入m2_verify數(shù)據(jù)校驗(yàn),然后進(jìn)入m2_use狀態(tài),鎖存輸出數(shù)據(jù),并進(jìn)入m2_wait狀態(tài),等待接收數(shù)據(jù)。當(dāng)檢測(cè)到時(shí)鐘下降沿后進(jìn)入m2_gather狀態(tài),接收鼠標(biāo)數(shù)據(jù)包,接收完成進(jìn)入m2_verify狀態(tài),此時(shí)便形成了數(shù)據(jù)接收循環(huán)。
PS/2程序源碼
entity mouse is
Port (clk : in std_logic; reset : in std_logic; ps2_clk : inout std_logic; ps2_data : inout std_logic; left_button : out std_logic; right_button : out std_logic; mousex: buffer std_logic_vector(9 downto 0); mousey: buffer std_logic_vector(9 downto 0); data_ready : out std_logic; error_no_ack : out std_logic);
end mouse;
architecture Behavioral of mouse is
--變量、信號(hào)定義(略)
begin
ps2_clk 《= ‘0’ when ps2_clk_hi_z=‘0’ else ‘Z’;
ps2_data 《= ‘0’ when ps2_data_hi_z=‘0’ else ‘Z’;
--檢測(cè)ps2clk上升沿和下降沿(略)
m2statech: process (reset, clk) ------------------m2 狀態(tài)
begin
if (reset=‘0’) then
m2_state 《= m2_reset;
elsif (clk‘event and clk=’1‘) then
m2_state 《= m2_next_state;
end if;
end procESS;
--m2 狀態(tài)傳輸邏輯
m2statetr: process (m2_state, q, fall,rise,watchdog_timer_done,bitcount,ps2_data,packet_good)
begin
ps2_clk_hi_z 《= ’1‘;
ps2_data_hi_z 《= ’1‘;
error_no_ack 《= ’0‘;
output_strobe 《= ’0‘;
case m2_state is
when m2_reset =》 -- 復(fù)位后向鼠標(biāo)發(fā)送命令字
m2_next_state 《= m2_hold_clk_l;
when m2_wait =》
if (fall=’1‘) then
m2_next_state 《= m2_gather;
else
m2_next_state 《= m2_wait;
end if;
when m2_gather =》
if ((watchdog_timer_done=’1‘) and (bitcount=TOTAL_BITS))then
m2_next_state 《= m2_verify;
else
m2_next_state 《= m2_gather;
end if;
when m2_verify =》
--if (bitcount 《 TOTAL_BITS) then
--m2_next_state 《= m2_wait;
--else
m2_next_state 《= m2_use;
--end if;
when m2_use =》
output_strobe 《= ’1‘;
m2_next_state 《= m2_wait;
-- 用狀態(tài)機(jī)的9個(gè)狀態(tài)實(shí)現(xiàn)命令字傳輸,使鼠標(biāo)進(jìn)入“streaming”模式,并等待鼠標(biāo)正確應(yīng)答 [page]
when m2_hold_clk_l =》
ps2_clk_hi_z 《= ’0‘; -- 啟動(dòng)看門狗!
if (watchdog_timer_done=’1‘) then
m2_next_state 《= m2_data_low_1;
else
m2_next_state 《= m2_hold_clk_l;
end if;
when m2_data_low_1 =》
ps2_data_hi_z 《= ’0‘; -- 數(shù)據(jù)位 開始位, d[0] and d[1]
if (fall=’1‘ and (bitcount = 2)) then
m2_next_state 《= m2_data_high_1;
else
m2_next_state 《= m2_data_low_1;
end if;
when m2_data_high_1 =》
ps2_data_hi_z 《= ’1‘; -- 數(shù)據(jù)位 d[2]
if (fall=’1‘ and (bitcount = 3)) then
m2_next_state 《= m2_data_low_2;
else
m2_next_state 《= m2_data_high_1;
end if;
when m2_data_low_2 =》
ps2_data_hi_z 《= ’0‘; -- 數(shù)據(jù)位 d[3]
if (fall=’1‘ and (bitcount = 4)) then
m2_next_state 《= m2_data_high_2;
else
m2_next_state 《= m2_data_low_2;
end if;
when m2_data_high_2 =》
ps2_data_hi_z 《= ’1‘; -- 數(shù)據(jù)位 d[4],d[5],d[6],d[7]
if (fall=’1‘ and (bitcount = 8)) then
m2_next_state 《= m2_data_low_3;
else
m2_next_state 《= m2_data_high_2;
end if;
when m2_data_low_3 =》
ps2_data_hi_z 《= ’0‘; -- 奇偶校驗(yàn)位
if (fall=’1‘) then
m2_next_state 《= m2_data_high_3;
else
m2_next_state 《= m2_data_low_3;
end if;
when m2_data_high_3 =》
ps2_data_hi_z 《= ’1‘; -- 允許鼠標(biāo)拉成低電平(ACK脈沖)
if (fall=’1‘ and (ps2_data=’1‘)) then
m2_next_state 《= m2_error_no_ack;
elsif (fall=’1‘ and (ps2_data=’0‘)) then
m2_next_state 《= m2_await_response;
else
m2_next_state 《= m2_data_high_3;
end if;
when m2_error_no_ack =》
error_no_ack 《= ’1‘;
m2_next_state 《= m2_error_no_ack;
-- 為了鼠標(biāo)正確進(jìn)入“streaming”模式,狀態(tài)極必須等待足夠長(zhǎng)的時(shí)間,確保鼠標(biāo)正確應(yīng)答0xFA。
when m2_await_response =》
--if (bitcount = 22) then
m2_next_state 《= m2_verify;
--else
-- m2_next_state 《= m2_await_response;
--end if;
when others =》 m2_next_state 《= m2_wait;
end case;
end process;-----------------------------m2 狀態(tài)結(jié)束
-- 位計(jì)數(shù)器 (略)
-- 數(shù)據(jù)移位寄存器(略)
-- 看門狗時(shí)間計(jì)數(shù)器(略)
watchdog_timer_done 《= ’1‘ when (watchdog_timer_count=WATCHDOG-1) else ’0‘;
packet_good 《= ’1‘; -- 接收數(shù)據(jù)包有效標(biāo)志
outdata: process (reset, clk) -- 輸出數(shù)據(jù)
begin
if (reset=’0‘) then
left_button 《= ’0‘;
right_button 《= ’0‘;
elsif (clk’event and clk=‘1’) then
if (output_strobe=‘1’) then
left_button 《= q(1);
right_button 《= q(2);
mouseyy 《= not (q(6) & q(6) & q(30 downto 23)) + “1”;
end if;
end if;
end process;
cordinatex: process (reset, clk)
begin
if (reset=‘0’) then
mousex 《= “0110010000”; -- 400
elsif (clk‘event and clk=’1‘) then
if (output_strobe=’1‘) then
if ((mousex 》= 797 and q(5)=’0‘) or (mousex 《= 2 and
q(5)=’1‘)) then
mousex 《= mousex;
else
mousex 《= mousex + (q(5) & q(5) & q(19 downto
12));--q(5):xsign q(6):ysign
end if;
end if;
end if;
end process;
cordinatey: process (reset, clk)
begin
if (reset=’0‘) then
mousey 《= “0100101100”; -- 300
elsif (clk’event and clk=‘1’) then
if (output_strobe=‘1’) then
if ((mousey 》= 597 and q(6)=‘1’) or (mousey 《= 2
and q(6)=‘0’)) then
mousey 《= mousey;
else
m ousey 《= mousey + mouseyy; --(q(6) & q(6) & q(30
downto 23));
end if;
end if;
end if;
end process;
data_ready 《= output_strobe;
end Behavioral;
結(jié)束語(yǔ)
該設(shè)計(jì)采用了清華大學(xué)THCII-1創(chuàng)新SoPC實(shí)驗(yàn)套件進(jìn)行綜合、仿真和下載,測(cè)試得到了滿意的效果,完整地實(shí)現(xiàn)了對(duì)PS/2和VGA的時(shí)序驅(qū)動(dòng)。
該設(shè)計(jì)可以被應(yīng)用到各種需要鼠標(biāo)操作、以VGA作為顯示的嵌入式系統(tǒng)中,從而大大提高人機(jī)交互能力,降低了開發(fā)成本,提高了開發(fā)效率,使系統(tǒng)的穩(wěn)定性也得到了可靠的保障。
責(zé)任編輯:gt
評(píng)論
查看更多