第1页9.1键盘接口设计9.2LED驱动器设计9.3D/A接口设计9.4A/D接口设计第9章FPGA在微机工程中实践应用第2页教学目标了解键盘接口原理及设计方法理解LED驱动器设计原理理解和掌握D/A接口设计的主要内容理解和掌握A/D接口设计的主要内容第3页教学重点理解LED驱动器设计理解和掌握D/A接口设计的主要内容理解和掌握A/D接口设计的主要内容第4页键盘工作原理键盘是由一组规则排列的按键组成,一个按键实际上是一个开关元件,它是微型计算机最常用的输入设备。微机键盘通常使用机械触点式按键开关,其主要功能是把机械上的通断转换为电气上的逻辑关系。也就是说,它能提供标准的TTL逻辑电平,以便与通用数字系统的逻辑电平相容。9.1键盘接口设计第5页在触点抖动期间检测按键的通与断状态,可能导致判断出错。即按键一次按下或释放被错误地认为是多次操作,这种情况是不允许出现的。为了克服按键触点机械抖动所致的检测误判,必须采取去抖动措施,可从硬件、软件两方面予以考虑。硬件去抖动措施:在键数较少时,可采用硬件去抖软件去抖动措施:当键数较多时采用软件去抖。去抖动措施第6页矩阵式键盘的结构及原理该类型键盘由行线和列线组成,按键位于行、列线的交叉点上。由图9-2可知,一个4×4的行、列结构可以构成一个含有16个按键的键盘,但是只占用8个I/O口线,因此,矩阵式键盘较之独立式按键键盘可以节省很多I/O口。0123456789101112131415V33I/OI/OI/OI/OI/OI/OI/OI/O图9-2第7页矩阵式键盘按键的识别识别按键的方法很多,其中,最常见的方法是扫描法。以下是以8号键的识别为例来介绍扫描法:8号键按下时,第2行一定为低电平,然而,第2行为低电平时,能否肯定是8号键按下呢?回答是否定的,因为9、10、11号键按下同样使第2行为低电平。接下页第8页为进一步确定具体键,不能使所有列线在同一时刻都处在低电平,可在某一时刻只让一条列线处于低电平,其余列线均处于高电平,另一时刻,让下一列处在低电平,依此循环,这种依次轮流每次选通一列的工作方式称为键盘扫描。采用键盘扫描后,再来观察8号键按下时的工作过程,当第0列处于低电平时,第2行处于低电平,而第1、2、3列处于低电平时,第2行却处在高电平,由此可判定按下的键应是第2行与第0列的交叉点,即8号键。第9页对于矩阵式键盘,按键的位置由行号和列号唯一确定,因此可分别对行号和列号进行二进制编码,然后将两值合成一个字节,高4位是行号,低4位是列号。如图9.2中的8号键,它位于第2行,第0列,因此,其键盘编码应为20H。采用上述编码对于不同行的键离散性较大,不利于散转指令对按键进行处理。因此,可采用依次排列键号的方式对安排进行编码。以图9-2中的4×4键盘为例,可将键号编码为:01H、02H、03H…0EH、0FH、10H等16个键号。编码相互转换可通过计算或查表的方法实现。键盘的编码第10页矩阵式按键FPGA描述clkclk_scanclk_scankeydrv[3..0]keyvalue[3..]keyin[3..0]clkclk_scankeypressedkeydrv[3..0]keyvalue[3..]keypressedclkkeyin[3..0]键盘接口顶层模块第11页libraryIEEE;useIEEE.STD_LOGIC_1164.ALL;useIEEE.STD_LOGIC_ARITH.ALL;useIEEE.STD_LOGIC_UNSIGNED.ALL;entitykeyisPort(clk:instd_logic;keyin:instd_logic_vector(3downto0);keyvalue:outstd_logic_vector(3downto0);keypressed:outstd_logic;keydrv:inoutstd_logic_vector(3downto0));endkey;architectureBehavioralofkeyis接下页第12页componentkeyscanport(clk_scan:instd_logic;--扫描时钟key_drv:outstd_logic_vector(3downto0)--扫描信号);endcomponent;componentclkgenport(clk:instd_logic;clk_scan:outstd_logic);endcomponent;接下页第13页componentkeydecoderport(key_in:instd_logic_vector(3downto0);--键盘输入key_drv:instd_logic_vector(3downto0);--键盘输出clk:instd_logic;--全局时钟clk_scan:instd_logic;--扫描时钟keyvalue:outstd_logic_vector(3downto0);--键盘的键值key_pressed:outstd_logic);endcomponent;signalclk_scan:std_logic;begin接下页第14页keyscan1:keyscanportmap(clk_scan=clk_scan,key_drv=keydrv);clkgen1:clkgenportmap(clk=clk,clk_scan=clk_scan);keydecoder1:keydecoderportmap(key_in=keyin,接下页第15页key_drv=keydrv,clk=clk,clk_scan=clk_scan,keyvalue=keyvalue,key_pressed=keypressed);endBehavioral;第16页键盘扫描电路模块接下页第17页libraryIEEE;useIEEE.STD_LOGIC_1164.ALL;useIEEE.STD_LOGIC_ARITH.ALL;useIEEE.STD_LOGIC_UNSIGNED.ALL;entitykeyscanisPort(clk_scan:instd_logic;--扫描时钟key_drv:outstd_logic_vector(3downto0));endkeyscan;architectureBehavioralofkeyscanisconstants0:STD_LOGIC_VECTOR(3DOWNTO0):=1110;constants1:STD_LOGIC_VECTOR(3DOWNTO0):=1101;constants2:STD_LOGIC_VECTOR(3DOWNTO0):=1011;接下页第18页constants3:STD_LOGIC_VECTOR(3DOWNTO0):=0111;signalpresent_state:STD_LOGIC_VECTOR(3DOWNTO0);--当前状态机signalnext_state:STD_LOGIC_VECTOR(3DOWNTO0);--下次状态机beginprocess(clk_scan)beginif(clk_scan'eventandclk_scan='1')thenpresent_state=next_state;--状态机在上升沿时翻转endif;endprocess;接下页第19页process(present_state)begincasepresent_stateiswhens0=next_state=s1;whens1=next_state=s2;whens2=next_state=s3;whens3=next_state=s0;whenothers=next_state=s0;endcase;endprocess;key_drv=present_state;--输出译码信号endBehavioral;第20页键盘译码电路模块接下页第21页libraryIEEE;useIEEE.STD_LOGIC_1164.ALL;useIEEE.STD_LOGIC_ARITH.ALL;useIEEE.STD_LOGIC_UNSIGNED.ALL;entitykeydecoderisPort(key_in:instd_logic_vector(3downto0);--键盘输入key_drv:instd_logic_vector(3downto0);--键盘输出clk:instd_logic;--全局时钟clk_scan:instd_logic;--扫描时钟keyvalue:outstd_logic_vector(3downto0)--键盘的键值);接下页第22页key_pressed:outstd_logic);--有键盘按下去的标志endkeydecoder;architectureBehavioralofkeydecoderissignaltemp:STD_LOGIC_VECTOR(7DOWNTO0);--键盘的输入信号signaltemp_preseed:STD_LOGIC;--键盘按下标志位signaltemp1,temp2,temp3,temp4,temp5,temp6:STD_LOGIC;--同步化信号signalkey_pressed_asy:STD_LOGIC;begintemp=key_drv&key_in;process(temp)begin接下页第23页casetempiswhen11101110=keyvalue=CONV_STD_LOGIC_VECTOR(1,4);temp_preseed='1';when11101101=keyvalue=CONV_STD_LOGIC_VECTOR(2,4);temp_preseed='1';when11101011=keyvalue=CONV_STD_LOGIC_VECTOR(3,4);temp_preseed='1';when11100111=keyvalue=CONV_STD_LOGIC_VECTOR(4,4);temp_preseed='1';when11011110=keyvalue=CONV_STD_LOGIC_VECTOR(5,4);temp_preseed='1';when11011101=keyvalue=CONV_STD_LOGIC_VECTOR(6,4);temp_preseed='1';when11011011=keyvalue=CONV_STD_LOGIC_VECTOR(7,4);temp_preseed='1';接下页第24页when11010111=keyvalue=CONV_STD_LOGIC_VECTOR(8,4);temp_preseed='1';when10111110=keyvalue=CONV_STD_LOGIC_VECTOR(9,4);temp_preseed='1';when10111101=keyvalue=CONV_STD_LOGIC_VECTOR(10,4);temp_preseed='1';when10111011=keyvalue=CONV_STD_LOGIC_VECTOR(11,4);temp_preseed='1';when10110111=keyvalue=CONV_STD_LOGIC_VECTOR(12,4);temp_preseed='1';when01111110=keyvalue=CONV_STD_LOGIC_VECTOR(13,4);temp_preseed='1';when01111101=keyvalue=CONV_STD_LOGIC_VECTOR(14,4);temp_preseed='1';接下页第25页when01111011=keyvalue=CONV_STD_