键盘驱动程序程鼐
单片机系统中ps2键盘驱动程序的设计
在单片机系统中,经常使用的键盘都是专用键盘.此类键盘为单独设计制作的,成本高、使用硬件连接线多,且可靠性不高,这一状况在那些要求键盘按键较多的应用系统中更为突出.与此相比,在PC系统中广泛使用PS/2键盘具有价格低、通用可靠,且使用连接线少(仅使用2根信号线)的特点,并可满足多种系统的要求.因此在单片机系统中应用PS/2键盘是一种很好的选择.文中在介绍PS/2协议和PS/2键盘工作原理与特点的基础上,给出了一个在单片机上实现对PS/2键盘支持的硬件连接与驱动程序设计实现.该设计实现了在单片机系统中对PS/2标准104键盘按键输入的支持.使用Keil C51开发的驱动程序接口和库函数可以方便地移植到其他单片机或嵌入式系统中.所有程序在Keil uVision2上编译通过,在单片机AT89C51上测试通过.1 PS/2协议目前,PC机广泛采用的PS/2接口为mini-DIN 6pin的连接器,如图1所示.PS/2设备有主从之分,主设备采用Female插座,从设备采用Male插头.现在广泛使用的PS/2键盘鼠标均在从设备方式下工作.PS/2接口的时钟与数据线都是集电极开路结构,必须外接上拉电阻(一般上拉电阻设置在主设备中).主从设备之间数据通信采用双向同步串行方式传输,时钟信号由从设备产生.1.1 从设备到主设备的通信当从设备向主设备发送数据时,首先检查时钟线,以确认时钟线是否为高电平.如果是高电平,从设备就可以开始传输数据;反之,从设备要等待获得总线的控制权,才能开始传输数据.传输的每一帧由11位组成,发送时序及每一位的含义如图2所示.每一帧数据中开始位总是为0,数据校验采用奇校验方式,停止位始终为1.从设备到主设备通信时,从设备总是在时钟线为高时改变数据线状态,主设备在时钟下降沿读人数据线状态.1.2 主设备到从设备的通信主设备与从设备进行通信时,主设备首先将时钟线和数据线设置为“请求发送”状态,具体方式为:首先下拉时钟线至少100us抑制通信,然后下拉数据线“请求发送”,最后释放时钟线.在此过程中,从设备在不超过10us 的间隔内必须检查这个状态,当设备检测到这个状态时,它将开始产生时钟信号.此时数据传输的每一帧由12位构成,其时序和每一位含义如图3所示.与从设备到主设备通信相比,其每帧数据多了一个ACK位.这是从设备应答接收到字节的应答位,由从设备通过拉低数据线产生,应答位ACK总是为0.主设备到从设备通信过程中,主设备总是在时钟线为低电平时改变数据线的状态,从设备在时钟上升沿读人数据线状态.2 PS/2键盘的编码与命令集2.1 PS/2键盘的编码目前,PC机使用的PS/2键盘都默认采用第2套扫描码集.扫描码有两种不同的类型:“通码(make code)”和“断码(break code)”.当一个键被按下或持续按住时,键盘会将该键的通码发送给主机;而当一个键被释放时,键盘会将该键的断码发送给主机.根据键盘按键扫描码的不同,可将按键分为3类:第1类按键通码为一个字节,断码为0xF0+通码形式.如A键,其通码为0x1C;断码为0xF0 0x1C.第2类按键通码为两字节0xE0+0xXX形式,断码为0xE0+0xF0+0xXX形式.如Right Ctrl键,其通码为0xE0 0x14;断码为0xE0 0xF0 0x14.第3类特殊按键有两个,Print Screen键,其通码为0xE0 0x12 0xE0 0x7C;断码为0xE0 0xF0 0x7C 0xE0 0xF0 0x12.Pause键,其通码为0xE1 0x14 0x77 0xE1 0xF0 0xl4 0xF0 0x77;断码为空.组合按键扫描码的发送是按照按键发生的次序,如按下面顺序按左Shift十A键:①按下左Shift键;②按下A键;③释放A键;④释放左Shift键,那么计算机上接收到的一串数据为0x12 0x1C 0xF0 0x1C 0xF0 0x12.在文中的驱动程序设计中,就是根据按键的分类对其分别进行处理.2.2 PS/2键盘的命令集主机可通过向PS/2键盘发送命令对键盘进行设置或者获得键盘的状态等操作.每发送一个字节,主机都会从键盘获得一个应答0xFA(“重发resend”和“回应echo”命令例外).驱动程序在键盘初始化过程中所用的指令:0xED,主机在该命令后跟随发送一个参数字节,用于指示键盘上Num Lock,Caps Lock,Scroll Lock Led的状态;0xF3,主机在这条命令后跟随发送一个字节参数定义键盘机打的速率和延时;0xF4,用于当主机发送0xF5禁止键盘后,重新使能键盘.3 PS/2键盘与单片机的连接电路PS/2键盘与AT89C51单片机的连接方式如图4所示.P1.0接PS/2数据线;P3.2(INT0)接PS/2时钟线.因为单片机的P1,P3口内部是带上拉电阻的,所以PS/2的时钟线和数据线可以直接与单片机的P1,P3相连接.4 驱动程序设计驱动程序的开发使用Keil C51语言以及KeiluVision2编程环境.PS/2 104键盘驱动程序主要任务是实现单片机与键盘间PS/2通信,同时将接收到的按键扫描码转换为该按键的键值KeyVal,提供给系统上层软件使用.4.1 单片机与键盘间PS/2通信的程序设计在PS/2通信过程中,主设备(文中是单片机)是在时钟信号为低时发送和接收数据信号.因为单片机向键盘发送的是指令,需要键盘回应,所以这部分程序采用查询方式;而单片机接收键盘数据时,数据线上的信号在时钟为低时已经稳定,所以这部分程序采用中断方式,且不需要在程序中加入延时程序.单片机向PS/2键盘发送数据程序代码为:void ps2_sentchar(unsigned char sentchar){//ps2主设备向从设备发送数据unsigned char sentbit_cnt= 0x00;unsigned char sentchar_chk = 0x00;EX0=0; //关外部中断0//发起一个传送,发起始位PS2_SGN_CLOCK = 0; //将时钟线拉低并保持100 usdelay100us();PS2_SGN_DATA= 0; //起始位PS2_SGN_CLOCK = 1;//发送DATA0-7for(sentbit_cnt=0;sentbit_cnt< 8;sentbit_cnt++){while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变为低PS2_SGN_DATA = sentchar& 0x01;//发送数据if(PS2_SGN_DATA) sentchar_chk++; //计算校验while(!PS2_SGN_CL0CK) _nop_(); //等待时钟线变高sentchar>>=1; //待发送数据右移一位}//发送校验位while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变低switch(sentchar_chk){case 0:case 2:case 4:case 6:PS2_SGN_DATA =1;break;//奇校验case 1:case 3:case 5:case 7:PS2_SGN_DATA = 0;break;//奇校验default;break;)while(!PS2_SGN_CLOCK) _nop_(); //等待时钟线变高while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变低PS2_SGN_DATA =1;//发送停止位,停止位总为1while(!PS2_SGN_CLOCK) _nop_(); //等待时钟线变高while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变低//接收ACK//if(PS2_SGN_DATA) error();//ACK信号由键盘发出,总为低电平while(!PS2_SGN_CLOCK) _nop_(); //等待时钟线变高EX0= 1; //开外部中断0}单片机由PS/2键盘接收数据程序:外部中断0设置为下降沿触发void int0() interrupt 0 using 0 {//EX0=0; //关外部中断0switch(ps2_revchar_cnt){case 1:……case 8:mcu_revchar<<=1;if(PS2_SGN_DATA) mcu_revchar |= 0x01;ps2_revchar_cnt++;break;case 0:ps2_revchar_cnt++;break; //开始位,case 9:ps2_revchar_cnt++;break; //校验位,可添加校验程序case 10: _nop_();//停止位ps2_revchar_cnt= 0;revchar_flag=1;//置接收到数据标识位break;default:break;}EX0=1;//开外部中断0}4.2 键盘扫描码转换程序设计由于键盘扫描码无规律可循,因此由键盘扫描码获得相应按键的键值(字符键为其ASCII值,控制键如F1,Ctrl等为自定义值),只能通过查表的方式获得.由于按键的3种类型及部分按键对应着两个键值(如A键的键值根据Caps和Shift键状态有0x41(A)和0x61(a)两种),因此综合考虑查表转换速度和资源消耗,设计中使用4个键盘表:键盘扫描码转换基本集和切换集(kb_plain_map[NR_KEYS]与kb_shift_map[NR_KEYS]);包含E0前缀的键盘扫描码转换基本集和切换集(kbeO_plain_map[NR_KEYS]与kbe0_shiftmap[NR_KEYS]).PS/2 104键盘按键扫描码最大值为0x83,所以设置NR_KEYS为132.所有4个键盘表的定义均为如下形式:KB_MAP[MAKE CODE]=KEYVAL,如果扫描码对应的按键为空(如KB_MAP[0x00]),则定义相应键值为NULL_KEY(0x00).以下是键盘扫描码基本集的部分代码实例:kb_plain_map[NR_K EYS]={……NULL_KEY;0x2C;0x6B;0x69;0x6F;0x30;0x39;NULL_KEY; //扫描码0x40~0x47//对应按键空,逗号,K,I,O,0,9,空//对应键值0x00,',','k','i','o','O','9',0x00…… };如此设计键盘转换表的另一个好处在于,以后如需扩展支持有ACPI、Windows多媒体按键键盘时,只需要将键表中相应处修改即可,如ACPIPower按键通码为0xE0 0x37,修改kbe0_plain_map[0x37]=KB_ACPI_PWR即可.特殊按键Pause使用单独程序处理,如果接收到0xE1就转入这段程序.而Print Screen键则将其看作是两个通码分别为0xE0 0x12和0xE0 0x7C的“虚键”的组合键处理.在驱动程序中设定如下全局变量:led_status记录Scroll Lock Led,Num Lock Led和Caps Lock Led的状态(关为0,开为1);agcs_status记录左右Shift Ctrl Gui Alt状态,相应键按下则对应位为1,释放为0.E0_FLAG接到0xE0置1;E1_FLAG接收到0xE1置1;F0_FLAG接收到0xF0置1.按键键值通过KeyVal提供上层程序使用.PS/2键盘扫描码键值转换程序ps2_codetrans()流程框架如图5所示.第1类按键的扫描码键值转换程序代码。
基于嵌入式linux的串口自定义键盘驱动开发
291基于嵌入式Linux 的串口自定义键盘驱动开发张士林(江苏自动化研究所,江苏连云港222006)摘要:近年,随着科技发展,嵌入式已成为当今时代产业主流。
而嵌入式Linux 的优势使其成为主要的操作系统之一。
本文介绍了Linux 下驱动开发的一般模式,详细分析了基于串口通讯的自定义键盘驱动的开发方法,对嵌入式Linux 驱动开发有一定程度的指导作用。
关键词:嵌入式Linux 系统;串口键盘;驱动开发中图分类号:TP316.2文献标识码:A 文章编号:1673-1131(2019)12-0291-02Abstract:In recent years,with the development of science and technology,embedded technology has become the mainstream of the industry.The advantages of embedded Linux make it one of the main operating systems.This paper introduces the general mode of driver development under Linux,and analyzes in detail the development method of custom keyboard driver based on serial port communication.This paper has certain reference signification for the research and development of embedded system.Key words:embedded Linux system;serial keyboard driver;driver development0引言嵌入式系统(Embedded system ),是一种“完全嵌入受控器件内部,为特定应用而设计的专用计算机系统”。
19264显示驱动程序
19264控制器KS0108#include <at89x52.h>#include <intrins.h>#include "zimo.h"#define RS P2_6 /*"H" is send or read the data;"L" is the instruction*/ #define RW P3_6#define E P2_5 /*Operation enable*/#define CS1 P2_4#define CS2 P2_3#define CS3 P2_2#define DATA P0#define uchar unsigned char#define uint unsigned int/* -------------------------------------------------Delay some time----------- */void delay10ms(unsigned char x){unsigned char i,j,k;for(i=0;i<x;i++)for(j=0;j<10;j++)for(k=0;k<120;k++);}/* -------------------------------------------------Send the instruction to the First KS0108 window--*/void OutFI(uchar i){unsigned char data_sta;do{E=0;RW=1;RS=0;CS1=0;_nop_();E=1;_nop_();data_sta=DATA;E=0;RW=0;CS1=1;E=1;}while(data_sta&0x80);E=0;RW=0;RS=0;CS1=0;_nop_();E=1;_nop_();DATA=i;_nop_();E=0;RW=1;CS1=1;E=1;}/* ------------------------------------------------- Send the instruction to the Second KS0108 window.--*/void OutSI(uchar i){unsigned char data_sta;do{E=0;RW=1;RS=0;CS2=0;_nop_();E=1;_nop_();data_sta=DATA;E=0;RW=0;CS2=1;E=1;}while(data_sta&0x80);E=0;RW=0;RS=0;CS2=0;_nop_();E=1;_nop_();DATA=i;_nop_();E=0;RW=1;CS2=1;E=1;}/* ------------------------------------------------- Send the instruction to the Third KS0108 window--*/void OutTI(uchar i){unsigned char data_sta;do{E=0;RW=1;RS=0;CS3=0;_nop_();E=1;_nop_();data_sta=DATA;E=0;RW=0;CS3=1;E=1;}while(data_sta&0x80);E=0;RW=0;RS=0;CS3=0;_nop_();E=1;_nop_();DATA=i;_nop_();E=0;RW=1;CS3=1;E=1;}/* -------------------------------------------------Send the data to the First ks0108 Window--*/void OutFD(uchar i){unsigned char data_sta;do{E=0;RW=1;RS=0;CS1=0;_nop_();E=1;_nop_();data_sta=DATA;E=0;RW=0;CS1=1;E=1;}while(data_sta&0x80);E=0;RW=0;RS=1;CS1=0;_nop_();E=1;_nop_();DATA=i;_nop_();E=0;RW=1;CS1=1;E=1;}/* ------------------------------------------------- Send the data to the Second ks0108 Window--*/void OutSD(uchar i){unsigned char data_sta;do{E=0;RW=1;RS=0;CS2=0;_nop_();E=1;_nop_();data_sta=DATA;E=0;RW=0;CS2=1;E=1;}while(data_sta&0x80);E=0;RW=0;RS=1;CS2=0;_nop_();E=1;_nop_();DATA=i;_nop_();E=0;RW=1;CS2=1;E=1;}/* ------------------------------------------------- Send the data to the Third ks0108 Window--*/void OutTD(uchar i){unsigned char data_sta;do{E=0;RW=1;RS=0;CS3=0;_nop_();data_sta=DATA;E=0;RW=0;CS3=1;E=1;}while(data_sta&0x80);E=0;RW=0;RS=1;CS3=0;_nop_();E=1;_nop_();DATA=i;_nop_();E=0;RW=1;CS3=1;E=1;}/* ------------------------------------------------- Read the data to the First ks0108 Window--*//*unsigned char RD_data_F(){unsigned char data_sta;do{E=0;RW=1;RS=0;CS1=0;_nop_();E=1;_nop_();data_sta=DATA;E=0;RW=0;CS1=1;E=1;}while(data_sta&0x80);E=0;RW=1;RS=1;CS1=0;_nop_();E=1;_nop_();_nop_();_nop_();data_sta=DATA;_nop_();E=0;RW=0;CS1=1;E=1;return (data_sta);}/* ------------------------------------------------- Read the data to the Second ks0108 Window--*//*unsigned char RD_data_S(){unsigned char data_sta;do{E=0;RW=1;RS=0;CS2=0;_nop_();E=1;_nop_();_nop_();_nop_();data_sta=DATA;E=0;RW=0;CS2=1;E=1;}while(data_sta&0x80);E=0;RW=1;RS=1;CS2=0;_nop_();data_sta=DATA;_nop_();E=0;CS2=1;E=1;return (data_sta);}/* ------------------------------------------------- Read the data to the Third ks0108 Window--*//*unsigned char RD_data_T(){unsigned char data_sta;do{E=0;RW=1;RS=0;CS3=0;_nop_();E=1;_nop_();_nop_();_nop_();data_sta=DATA;E=0;RW=0;CS3=1;E=1;}while(data_sta&0x80);E=0;RW=1;RS=1;CS3=0;_nop_();E=1;_nop_();data_sta=DATA;_nop_();E=0;CS3=1;E=1;return(data_sta);}/* ------------------------------------------------- Initialize the LCD,The system reset,invoke First time-*/void InitLCD(){OutFI(0x40); /*Set the Y address 0 */OutSI(0x40);OutTI(0x40);OutFI(0xb8); /*Set the Page 0 */OutSI(0xb8);OutTI(0xb8);OutFI(0xc0); /*Set the display start line 0 */OutSI(0xc0);OutTI(0xc0);OutFI(0x3f); /*Display ON */OutSI(0x3f);OutTI(0x3f);}/* -------------------------------------------------Clear the three ks0108's display ram.Clrscr screen-*/void Clrscreen(){unsigned char i,j;for(i=0;i<8;i++){OutFI(0xb8|i);for(j=0;j<64;j++){OutFI(j|0x40);OutFD(0);}}for(i=0;i<8;i++)(OutSI(0xb8|i);for(j=0;j<64;j++)(OutSI(j|0x40);OutSD(0);}}for(i=0;i<8;i++)(OutTI(0xb8|i);for(j=0;j<64;j++)(OutTI(j|0x40);OutTD(0);}}}/* -------------------------------------------------Display Chinese ideograph;x_add is the x address;It has 4 layers,0,1,2,3; Width is the Chinese ideograph width;bmp is the table's name-*/void DrawBmp(uchar x_add,uchar layer,uchar width,uchar *bmp)(unsigned char x;unsigned int i=0;for(x=x_add;x<x_add+width;x++)(if (x>127) /*The Third KS0108*/(OutTI((x-128)|0x40); /*Set the x address*/OutTI(layer|0xb8); /*Set the y address*/OutTD(bmp[i]); /*Send thd data to LCD ram*/OutTI((x-128)|0x40); /*Display the down screen*/ OutTI((layer|0xb8)+1); i++; /*Display zimo table address add 1*/ OutTD(bmp[i]);}else if (x>63) /*The Second ks0108*/{OutSI((x-64)|0x40);OutSI(layer|0xb8);OutSD(bmp[i]);OutSI((x-64)|0x40);OutSI((layer|0xb8)+1);i++;OutSD(bmp[i]);}else /*The First ks0108*/{OutFI(x|0x40);OutFI(layer|0xb8);OutFD(bmp[i]);OutFI(x|0x40);OutFI((layer|0xb8)+1);i++;OutFD(bmp[i]);}i++;}}/* -------------------------------------------------Display Chinese ideograph;x_add is the x address;It has 4 layers,0,1,2,3; Width is the Chinese ideograph width;bmp is the table's name.-*/void DrawBmp_f(uchar x_add,uchar layer,uchar width,uchar *bmp) {unsigned char x;unsigned int i=0;for(x=x_add;x<x_add+width;x++) (if (x>127)(OutTI((x-128)|0x40);OutTI(layer|0xb8);OutTD(~bmp[i]);OutTI((x-128)|0x40);OutTI((layer|0xb8)+1);i++;OutTD(~bmp[i]);}else if (x>63)(OutSI((x-64)|0x40);OutSI(layer|0xb8);OutSD(~bmp[i]);OutSI((x-64)|0x40);OutSI((layer|0xb8)+1);i++;OutSD(~bmp[i]);}else(OutFI(x|0x40);OutFI(layer|0xb8);OutFD(~bmp[i]);OutFI(x|0x40);OutFI((layer|0xb8)+1);i++;OutFD(~bmp[i]);}i++;}}/*Display indention; x_add is the x address;It has 4 layers,0,1,2,3; Width is the Chinese ideograph width-*/void _DrawBmp_(uchar x_add,uchar layer,uchar width){unsigned char x;for(x=x_add;x<x_add+width;x++){if (x>127){OutTI((x-128)|0x40);OutTI(layer|0xb8);OutTD(0);OutTI((x-128)|0x40);OutTI((layer|0xb8)+1);OutTD(0);}else if (x>63){OutSI((x-64)|0x40);OutSI(layer|0xb8);OutSD(0);OutSI((x-64)|0x40);OutSI((layer|0xb8)+1);OutSD(0);}else{OutFI(x|0x40);OutFI(layer|0xb8);OutFD(0);OutFI(x|0x40);OutFI((layer|0xb8)+1);OutFD(0);/* --------------------------------------------------Display indention; x_add is the x address;It has 4 layers,0,1,2,3; Width is the Chinese ideograph width-*/void _DrawBmp_black(uchar x_add,uchar layer,uchar width){unsigned char x;for(x=x_add;x<x_add+width;x++){if (x>127){OutTI((x-128)|0x40);OutTI(layer|0xb8);OutTD(0xff);OutTI((x-128)|0x40);OutTI((layer|0xb8)+1);OutTD(0xff);}else if (x>63){OutSI((x-64)|0x40);OutSI(layer|0xb8);OutSD(0xff);OutSI((x-64)|0x40);OutSI((layer|0xb8)+1);OutSD(0xff);}else{OutFI(x|0x40);OutFI(layer|0xb8);OutFD(0xff);}}OutFI(x|0x40);OutFI((layer|0xb8)+1);OutFD(0xff);}}}/* --------------------------------------------------Display the line display_data_graph is the display graph data-*/void _DrawBmp_line(uchar x_add,uchar layer,uchar width,uchar display_data_graph) {unsigned char x;unsigned int i=0;for(x=x_add;x<x_add+width;x++){if (x>127){OutTI((x-128)|0x40);OutTI(layer|0xb8);OutTD(display_data_graph);}else if (x>63){OutSI((x-64)|0x40);OutSI(layer|0xb8);OutSD(display_data_graph);}else{OutFI(x|0x40);OutFI(layer|0xb8);OutFD(display_data_graph);}i++;/*Display the column display_data_graph is the display graph data-*/void _DrawBmp_column(uchar x,uchar width) {unsigned int i=0;if (x>127){for(i=0;i<width;i++){OutTI((x-128)|0x40);OutTI(i|0xb8);OutTD(0xff);}}else if (x>63){for(i=0;i<width;i++){OutSI((x-64)|0x40);OutSI(i|0xb8);OutSD(0xff);}}else{for(i=0;i<width;i++){OutFI(x|0x40);OutFI(i|0xb8);OutFD(0xff);}}}}}。
C51的4X4键盘程序设计
二、中断请求标志
1、TCON的中断标志
IT0(TCON.0),外部中断0触发方式控制位。 当IT0=0时,为电平触发方式。 当IT0=1时,为边沿触发方式(下降沿有效)。 IE0(TCON.1),外部中断0中断请求标志位。 IT1(TCON.2),外部中断1触发方式控制位。 IE1(TCON.3),外部中断1中断请求标志位。 TF0(TCON.5),定时/计数器T0溢出中断请求标志位。 TF1(TCON.7),定时/计数器T1溢出中断请求标志位。
图 3-3-4 利用延时函数消除键盘抖动实现键盘输入电路
二、程序设计
#include<reg51.h> #define uchar unsigned char code uchar seven_seg[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; sbit key1 = P3.0; sbit key2 = P3.1; uchar key1_state,key2_state; //按键按下的状态变量 void delay(uchar i) { while (i) i--; } void key_scan (void) //键盘扫描函数 { if(key1 == 0) //如果按键按下 { delay(200); //延时一段时间,消除键抖 while(key1 == 0) key1_state = 1; //再对按键检测,如果确实按 下,按键状态变量为1 } if(key2 == 0) { delay(200); while(key2 == 0) key2_state = 1; } }
3.3.4 4×4键盘程序设计
4×4键盘16键盘阵列,本案例采用P1口完成, 见图3-3-5所示,把P18条I/O口分成4条列线4条行 线交叉但不接触,16个按键放置交叉位置,在单 片机复杂系统需要较多按键时,这种接法可以节 省单片机的硬件资源。键盘和P1口之间采用总线 连接布局,在电路原理设计过程中,总线只是图 示引脚之间的相连接关系,但不具有电气连接特 性,相连引脚之间需要标注相同的网络标号采用 电气连接特性,如图3-3-5中,单片机的P1.0与键 盘阵列上的P1.0相连。在设计单片机系统或其它 电子系统时,由于器件引脚较多,器件与器件之 间会经常采用总线连接,并且把电路模块化设计。
usb键盘驱动 (2)
USB键盘驱动简介USB键盘驱动是一种用于连接计算机和USB键盘的软件程序。
它的作用是使计算机能够正确地识别和响应来自USB键盘的输入信号,并将其转化为计算机可以理解的指令。
在计算机发展的早期阶段,键盘通常是通过传统的PS/2接口连接到计算机主机。
但随着USB(Universal Serial Bus,通用串行总线)技术的不断发展,USB键盘开始逐渐取代传统的PS/2键盘。
与PS/2键盘相比,USB键盘具有更高的传输速度、更大的数据带宽和更广泛的兼容性。
为了正常使用USB键盘,用户需要安装正确的USB键盘驱动程序。
本文将介绍USB键盘驱动的工作原理、安装方法和常见问题解决方法。
工作原理USB键盘驱动的工作原理可以简单分为以下几个步骤:1.设备识别:当用户将USB键盘插入计算机时,计算机会自动检测到新的USB设备并尝试识别其类型。
在识别过程中,计算机会自动加载适当的驱动程序。
2.驱动加载:计算机根据USB设备的类型加载相应的驱动程序。
对于USB键盘,计算机会加载USB键盘驱动程序。
驱动程序通常存储在操作系统的驱动库中。
3.功能映射:USB键盘驱动会解析来自键盘的输入信号,并将其转化为计算机可以理解的指令。
这些指令通常与键盘上的特定按键和功能相对应。
4.指令传递:USB键盘驱动将转化后的指令传递给操作系统,操作系统会根据指令执行相应的操作。
例如,当用户按下键盘上的某个按键时,驱动程序会将相应的指令传递给操作系统,并在屏幕上显示相应的字符或执行相应的操作。
安装方法安装USB键盘驱动可以通过以下几种方式实现:1.自动安装:大多数操作系统(如Windows、Mac和Linux)都具有自动安装驱动程序的功能。
当用户将USB键盘插入计算机时,操作系统会自动检测并加载相应的驱动程序。
用户只需要按照系统提示进行操作即可完成安装过程。
2.手动安装:在某些情况下,操作系统可能无法自动安装USB键盘驱动程序。
这时,用户可以尝试手动安装驱动程序。
STM32-矩阵键盘程序4×4课件.doc
/*--------------------------------------------------------------------------------------* 矩阵键盘驱动* 文件: keyboard.c* 编写人:LiuHui* 描述:扫描4x4 矩阵键盘输入,并返回键值* 适用范围:驱动采用ST3.5 库编写,适用于STM32F10x 系列单片机* 所用引脚:PA0-PA7* 编写时间:2014 年5 月20 日--------------------------------------------------------------------------------------*/#include "stm32f10x.h"#include "keyboard.h"#include "dealy.h"/*-------------------------------- 矩阵键盘初始化----------------------------------------* 功能:初始化stm32 单片机GPIO //PA0-PA7* 参数传递:* 输入:无* 返回值:无--------------------------------------------------------------------------------------*/void KeyBoard_Init(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);}/*------------------------------ 矩阵键盘扫描--------------------------------------------* 功能:扫描矩阵键盘,并返回键值* 参数:* 输入:无* 返回:有键按下返回该键值* 无键按下时则返回0--------------------------------------------------------------------------------------*/u8 Read_KeyValue(void){u8 KeyValue=0;if((GPIO_ReadInputData(GPIOA)&0xff)!=0x0f){Delay_ms(10);if((GPIO_ReadInputData(GPIOA)&0xff)!=0x0f){GPIO_SetBits(GPIOA, GPIO_Pin_0);GPIO_ResetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);switch(GPIO_ReadInputData(GPIOA)&0xff){case 0x11: KeyValue = 1; break;case 0x21: KeyValue = 5; break;case 0x41: KeyValue = 9; break;case 0x81: KeyValue = 13;break;}GPIO_SetBits(GPIOA, GPIO_Pin_1);GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3);switch(GPIO_ReadInputData(GPIOA)&0xff){case 0x12: KeyValue = 2; break;case 0x22: KeyValue = 6; break;case 0x42: KeyValue = 10;break;case 0x82: KeyValue = 14;break;}GPIO_SetBits(GPIOA, GPIO_Pin_2);GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_3);switch(GPIO_ReadInputData(GPIOA)&0xff){case 0x14: KeyValue = 3; break;case 0x24: KeyValue = 7; break;case 0x44: KeyValue = 11;break;case 0x84: KeyValue = 15;break;}GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2);switch(GPIO_ReadInputData(GPIOA)&0xff){case 0x18: KeyValue = 4; break;case 0x28: KeyValue = 8; break;case 0x48: KeyValue = 12;break;case 0x88: KeyValue = 16;break;}GPIO_SetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3); GPIO_ResetBits(GPIOA, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 |GPIO_Pin_7);while((GPIO_ReadInputData(GPIOA)&0xff)!=0x0f);return KeyValue;}}return 0;}/*--------------------------------THE END--------------------------------------------*//*--------------------------------------------------------------------------------------* 矩阵键盘驱动* 文件: keyboard.h* 编写人:LiuHui* 描述:扫描4x4 矩阵键盘输入,并返回键值* 适用范围:驱动为ST3.5 库编写,适用于STM32F10x 系列单片机* 所用引脚:PA0-PA7* 编写时间:2013 年11 月22 日* 版本: 1.0--------------------------------------------------------------------------------------*/#ifndef __KEYBOARD_H#define __KEYBOARD_Hvoid KeyBoard_Init(void);u8 Read_KeyValue(void);#endif/*----------------------------------THE END------------------------------------------*#include "stm32f10x.h"void KeyBoard_Init(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6);GPIO_ResetBits(GPIOB, GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10);}//3?ê?? ˉPA,PBvoid Delay_ms(int time){int i=0;while(time--){i=12000;while(i--);}}u8 Read_KeyValue(void){u8 KeyValue=1;if((GPIO_ReadInputData(GPIOB)&0xff)!=0x0f){Delay_ms(10);if((GPIO_ReadInputData(GPIOB)&0xff)!=0x0f){GPIO_SetBits(GPIOB, GPIO_Pin_3);GPIO_ResetBits(GPIOB, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6); switch(GPIO_ReadInputData(GPIOB)&0xff){case 0x11: KeyValue = 7; break;case 0x21: KeyValue = 4; break;case 0x41: KeyValue = 1; break;case 0x81: KeyValue = 0; break;}GPIO_SetBits(GPIOB, GPIO_Pin_4);GPIO_ResetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6); switch(GPIO_ReadInputData(GPIOB)&0xff){case 0x12: KeyValue = 8; break;case 0x22: KeyValue = 5; break;case 0x42: KeyValue = 2; break;case 0x82: KeyValue = 0; break;}GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_ResetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_6);switch(GPIO_ReadInputData(GPIOB)&0xff){case 0x14: KeyValue = 9; break;case 0x24: KeyValue = 6; break;case 0x44: KeyValue = 3; break;case 0x84: KeyValue = 0; break;}GPIO_SetBits(GPIOB, GPIO_Pin_6);GPIO_ResetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);switch(GPIO_ReadInputData(GPIOB)&0xff){case 0x18: KeyValue = 0; break;case 0x28: KeyValue = 0; break;case 0x48: KeyValue = 0;break;case 0x88: KeyValue = 0;break;}GPIO_SetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6); GPIO_ResetBits(GPIOB, GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10);//while((GPIO_ReadInputData(GPIOB)&0xff)!=0x0f);return KeyValue;}}return 0;}uint16_t table[]={0xEB,0x28,0xB3,0xBA,0x78,0xDA,0xDB,0xA8,0xFB,0xFA};int main(){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);KeyBoard_Init();int keyvalue=Read_KeyValue();GPIO_Write(GPIOA, table[keyvalue]);/*while(1){int i;for(i=0;i<10;i++){GPIO_Write(GPIOA, table[i]);Delay_ms(500);}}*//*u8 keyvalue;for(int i=0;;i++){KeyBoard_Init();keyvalue=Read_KeyValue();GPIO_Write(GPIOA,table[keyvalue]);Delay_ms(500);}*/}#include "stm32f10x.h"void KeyBoard_Init(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6);GPIO_ResetBits(GPIOB, GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10);}void Delay_ms(int time){int i=0;while(time--){i=12000;while(i--);}}u8 Read_KeyValue(void){if((GPIO_ReadInputData(GPIOB)&0xff)!=0x73)// 在这个程序下为什么无论是GPIO_ReadInputData(GPIOB)&0xff)!=0x73 还是GPIO_ReadInputData(GPIOB)&0xff)==0x73 都能往下运行,而在屏蔽Delay_ms(10) 后则只能运行一种,是因为这个Delay_ms(10) 对if 里的判断有影响吗?{Delay_ms(10);GPIO_Write(GPIOA,0x33);}return 0;}int main(){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);KeyBoard_Init();Read_KeyValue();}。
linux设备驱动之键盘驱动分析 - linux设备模型 - Linux内核学习
static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct atkbd *atkbd;
struct input_dev *dev;
int err = -ENOMEM;
atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL); dev = input_allocate_device(); if (!atkbd || !dev)
三:键盘驱动入口 在atkbd.c中,module的入口函数为:
static int __init atkbd_init(void)
…/…/showart_1089643.h…
1/6
2011/5/26
linux设备驱动之键盘驱动分析 - linux设…
{
dmi_check_system(atkbd_dmi_quirk_table);
strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
port->serio = serio; port->irq = I8042_KBD_IRQ;
return 0; } 初始化了一个serio 结构. 在i8 04 2 _register_po rts()中: static void __devinit i8042_register_ports(void) {
-----------------------------------------本文系本站原创,欢迎转载! 转载请注明出处:/ ------------------------------------------
单片机驱动4X4矩阵式键盘输入程序(1)
单片机驱动4X4矩阵式键盘输入程序(1)单片机驱动4X4矩阵式键盘输入程序 (1)用AT89S51单片机的并行口P1接4×4矩阵键盘,以P1.0-P1.3作输入线,以P1.4-P1.7作输出线;在数码管上显示每个按键的“0-F”序号。
实现键盘输入的识别。
我将给大家提供c和汇编两个版本的4X4矩阵式键盘输入程序。
如汇编语言源程序:KEYBUF EQU 30HORG 00HSTART: MOV KEYBUF,#2WAIT:MOV P3,#0FFHCLR P3.4MOV A,P3ANL A,#0FHXRL A,#0FHJZ NOKEY1LCALL DELY10MSMOV A,P3ANL A,#0FHXRL A,#0FHJZ NOKEY1MOV A,P3ANL A,#0FHCJNE A,#0EH,NK1MOV KEYBUF,#0LJMP DK1NK1: CJNE A,#0DH,NK2MOV KEYBUF,#1LJMP DK1NK2: CJNE A,#0BH,NK3 MOV KEYBUF,#2LJMP DK1NK3: CJNE A,#07H,NK4 MOV KEYBUF,#3LJMP DK1NK4: NOPDK1:MOV A,KEYBUFMOV DPTR,#TABLE MOVC A,@A+DPTRMOV P0,ADK1A: MOV A,P3ANL A,#0FHXRL A,#0FHJNZ DK1ANOKEY1:MOV P3,#0FFHCLR P3.5MOV A,P3ANL A,#0FHXRL A,#0FHJZ NOKEY2LCALL DELY10MSMOV A,P3ANL A,#0FHXRL A,#0FHJZ NOKEY2MOV A,P3ANL A,#0FHCJNE A,#0EH,NK5MOV KEYBUF,#4LJMP DK2NK5: CJNE A,#0DH,NK6 MOV KEYBUF,#5LJMP DK2NK6: CJNE A,#0BH,NK7 MOV KEYBUF,#6LJMP DK2NK7: CJNE A,#07H,NK8 MOV KEYBUF,#7LJMP DK2NK8: NOPDK2:MOV A,KEYBUFMOV DPTR,#TABLE MOVC A,@A+DPTRMOV P0,ADK2A: MOV A,P3ANL A,#0FHXRL A,#0FHJNZ DK2ANOKEY2:MOV P3,#0FFHCLR P3.6MOV A,P3ANL A,#0FHXRL A,#0FHLCALL DELY10MSMOV A,P3ANL A,#0FHXRL A,#0FHJZ NOKEY3MOV A,P3ANL A,#0FHCJNE A,#0EH,NK9MOV KEYBUF,#8LJMP DK3NK9: CJNE A,#0DH,NK10 MOV KEYBUF,#9LJMP DK3NK10: CJNE A,#0BH,NK11 MOV KEYBUF,#10LJMP DK3NK11: CJNE A,#07H,NK12 MOV KEYBUF,#11LJMP DK3NK12: NOPDK3:MOV A,KEYBUFMOV DPTR,#TABLEMOVC A,@A+DPTRMOV P0,ADK3A: MOV A,P3ANL A,#0FHXRL A,#0FHJNZ DK3AMOV P3,#0FFHCLR P3.7MOV A,P3ANL A,#0FHXRL A,#0FHJZ NOKEY4LCALL DELY10MSMOV A,P3ANL A,#0FHXRL A,#0FHJZ NOKEY4MOV A,P3ANL A,#0FHCJNE A,#0EH,NK13MOV KEYBUF,#12LJMP DK4NK13: CJNE A,#0DH,NK14 MOV KEYBUF,#13LJMP DK4NK14: CJNE A,#0BH,NK15 MOV KEYBUF,#14LJMP DK4NK15: CJNE A,#07H,NK16 MOV KEYBUF,#15LJMP DK4NK16: NOPDK4:MOV A,KEYBUFMOV DPTR,#TABLEMOVC A,@A+DPTRMOV P0,ADK4A: MOV A,P3ANL A,#0FHXRL A,#0FHJNZ DK4ANOKEY4:LJMP WAITDELY10MS:MOV R6,#10D1: MOV R7,#248DJNZ R7,$DJNZ R6,D1RETTABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71HEND。
CH451键盘、数码管驱动程序及电路
苦心人,天不负,三千炎黄甲可灭倭苦心人,天不负,三千炎黄甲可灭倭谁也没有权力代表那3500万死去的同胞原谅日本!!--------- "我们要记取的不仅是南京大屠杀到底有多少人罹难,更要谨记这些人是如何惨死的。
" --张纯如主页博客相册|个人档案 |好友查看文章CH451键盘、数码管驱动程序及电路(8051、凌阳61)2009-06-17 15:442.1. 显示驱动● 内置大电流驱动级,段电流不小于25mA,字电流不小于150mA。
● 动态显示扫描控制,直接驱动 8位数码管或者 64 只发光管LED。
● 可选数码管的段与数据位相对应的不译码方式或者 BCD 译码方式。
● 数码管的字数据左移、右移、左循环、右循环。
● 各数码管数字独立闪烁控制。
● 通过占空比设定提供16级亮度控制。
● 支持段电流上限调整,可以省去所有限流电阻。
● 扫描极限控制,支持1到8个数码管,只为有效数码管分配扫描时间。
2.2. 键盘控制● 内置64 键键盘控制器,基于8×8矩阵键盘扫描。
● 内置按键状态输入的下拉电阻,内置去抖动电路。
● 键盘中断,低电平有效输出。
● 提供按键释放标志位,可供查询按键按下与释放。
2.3. 其它● 高速的 4线串行接口,支持多片级联,时钟速度从0 到 10MHz。
● 串行接口中的DIN和DCLK信号线可以与其它接口电路共用,节约引脚。
● 完全内置时钟振荡电路,不需要外接晶体或者阻容振荡。
● 内置上电复位和看门狗Watch-Dog,提供高电平有效和低电平有效复位输出。
详细资料下载地址如果迅雷下载不成功,就用IE下(文件另存为)/axsdffffproteus/filebox/down/fc/010eddef4a38fbcf956375013504d54 7/filebox/down/fc/1bf2b8ae32d118285755d332543cadb c部分程序如下:#define CH451_RESET 0x0201 //复位#define CH451_LEFTMOV 0x0300 //设置移动方式-作移#define CH451_LEFTCYC 0x0301 //设置移动方式-左循#define CH451_RIGHTMOV 0x0302 //设置移动方式-右移#define CH451_RIGHTCYC 0x0303 //设置移动方式-右循#define CH451_SYSOFF 0x0400 //关显示、键盘、看门狗#define CH451_SYSON1 0x0401 //开显示#define CH451_SYSON2 0x0403 //开显示、键盘#define CH451_SYSON3 0x0407 //开显示、键盘、看门狗功能#define CH451_DSP 0x0500 //设置默认显示方式#define CH451_BCD 0x0580 //设置BCD译码方式#define CH451_TWINKLE 0x0600 //设置闪烁控制#define CH451_DIG0 0x0800 //数码管位0显示#define CH451_DIG1 0x0900 //数码管位1显示#define CH451_DIG2 0x0a00 //数码管位2显示#define CH451_DIG3 0x0b00 //数码管位3显示#define CH451_DIG4 0x0c00 //数码管位4显示#define CH451_DIG5 0x0d00 //数码管位5显示#define CH451_DIG6 0x0e00 //数码管位6显示#define CH451_DIG7 0x0f00 //数码管位7显示//须主程序定义的参数sbit ch451_dclk=P2^5; //串行数据时钟上升延激活sbit ch451_din=P2^6; // 串行数据输出,接CH451的数据输入sbit ch451_load=P2^7; //串行命令加载,上升延激活sbit ch451_dout=P3^3; //INT1,键盘中断和键值数据输入,接CH451的数据输出unsigned char ch451_key; // 存放键盘中断中读取的键值//********************************************//初始化子程序void ch451_init(){ch451_din=0; //先低后高,选择4线输入ch451_din=1;IT1=1; //设置下降沿触发PX1=1; //设置低优先级EX1=1; //开中断EA=1;//*****************************************************//输出命令子程序//定义一无符号整型变量存储12字节的命令字。
单片机驱动标准PC机键盘的C51程序
单片机驱动标准PC机键盘的C51程序单片机驱动标准PC 机键盘的C51 程序//#i nclude”reg51.h”#i nclude “intrins.h”#i nclude “ku.h”//按键通码与ascii对照表sbit sda= p1; //键盘数据线unsigned char dat=0,dat1=0,dat2=0; //接收键盘数据变量? 存储通码变量接受连续通码变量unsigned char count=0,num=9,temp[5],shu=0; //中数次数中断控制变量缓冲区数组缓冲区指针unsigned char key=0; //按键最终值void zhongduan() interrupt 0 //外部中断0 用来接受键盘发来的数据{dat>>=1; //接受数据低->高if(sda) dat|=0x80;count++;if(count==num){if(count==9){dat1=dat; //中断9 次后为键盘所按按键的通码(开始位始终为0 在第一次中断时右移中忽略)num=20; //使中断可以继续中断11 次}if(count==20){dat2=dat; //取回第二个通码if(dat1==0xe0 || dat2==0xf0) //第一个通码是0xe0 则证明所按按键为功能键,第二个通码是0xf0证明按键结束{temp[shu]=dat1;temp[shu+1]=dat2; shu+=2; //将所按按键存到缓冲区中ie=0x82; //关闭外部中断并打开内部中断来处理所按按键tr0=1;} else{temp[shu]=dat1;temp[shu+1]=dat2; shu+=2; //如果shift 键被按下则记录与它同时按下的那个键count=0;}if((temp[0]==18 || temp[0]==89) && (temp[2]==18 || temp[2]==89) ) tr0=1; //如果缓冲区中有两个间隔的shift 键则证明需要的铵键结束}}}void getkey() interrupt 1 //内部中断0 用来处理缓冲区里的数据{unsigned char i=0;tr0=0;th0=0;tl0=0;count=0; //中断记数则0if((temp[0]==18 || temp[0]==89) && temp[1]!=0xf0 ) //shift 被按下{for(i=0;itips:感谢大家的阅读,本文由我司收集整编。
matrix keyboard driver解析
Matrix键盘驱动是一种适用于多行多列多按键情况的键盘驱动,与简单的GPIO按键驱动相比,它的结构更复杂。
在Linux内核中,Matrix键盘驱动的实现主要位于`drivers/input/keyboard/matrixkeypad.c`文件中。
以下是对Matrix键盘驱动的解析:
1. 功能实现:
Matrix键盘驱动的具体开发流程包括添加编译选项、添加设备树节点、内核源码中按键映射写法等。
2. 硬件电路:
Matrix键盘驱动的硬件设计需要考虑上拉模式和下拉模式。
上拉模式下,输入GPIO 硬件设计为上拉;下拉模式下,输入GPIO硬件设计为下拉。
3. 调试步骤:
调试Matrix键盘驱动时,可以使用hexdump命令、类hexdump工具源码等调试工具。
调试流程包括大致调试流程和具体步骤描述。
4. 源码中添加调试log小技巧:
在源码中添加调试log可以帮助开发者更好地理解驱动程序的运行过程和问题所在。
5. 内核源码逻辑分析:
Matrix键盘驱动的整体功能逻辑包括键盘Matrixkeypad_scan()函数扫描原理、键盘Matrixkeypadparsedt()函数源码解析、键盘Matrixkeypadinitgpio()函数源码解析等。
基于 WinCE 的模拟键盘驱动程序的实现
基于 WinCE 的模拟键盘驱动程序的实现
吴弋晻;葛海江;张能贵
【期刊名称】《机电工程》
【年(卷),期】2008(025)009
【摘要】针对有限的嵌入式系统硬件资源,设计并开发高效的底层设备驱动对增强嵌入式系统的运行可靠性和提高系统运行效率至关重要.简要介绍了 S3C2410 芯片的体系结构,阐述了在 WinCE 操作系统中编写设备驱动程序的实现过程与方法,并在S3C2410上实现了键盘中断方式的驱动程序,最后,把模拟键盘驱动程序加栽到了 WinCE 内核中.研究结果表明,该实现方法对其他类似设备的驱动开发具有一定的借鉴意义.
【总页数】3页(P103-105)
【作者】吴弋晻;葛海江;张能贵
【作者单位】杭州职业技术学院电子技术应用研究所,浙江,杭州,310018;杭州职业技术学院电子技术应用研究所,浙江,杭州,310018;杭州电子科技大学计算机应用研究所,浙江,杭州,310018
【正文语种】中文
【中图分类】TP3
【相关文献】
1.基于WinCE下NDIS小端口驱动程序的设计与实现 [J], 石启国
2.基于WinCE环境的CAN适配卡驱动程序的设计与实现 [J], 杨军波;须文波
3.基于WinCE环境的CAN适配卡驱动程序的设计与实现 [J], 杨军波;须文波
4.基于S3C2440与WinCE平台上的FIQ驱动程序的实现 [J], 开元海;汪超;郑勇
5.基于WinCE环境的CAN总线扩展卡驱动程序的设计与实现 [J], 杨清华
因版权原因,仅展示原文概要,查看原文内容请购买。
DA9034驱动程序阅读笔记(2)
软件英才网软件行业驰名招聘网站DA9034驱动程序阅读笔记(2)作者联系方式:李先静<xianjimli at hotmail dot com>DA9034是一个集成了电源管理、音频设备、触摸屏控制器和能用A/D|D/A转换的多功能芯片。
最近读了一下相关驱动程序,这里记些笔记,不成体系,作为备忘而已。
有兴趣的朋友可以一起讨论。
DA9034支持四类LED驱动:LCD背光、键盘背光、FLASH_LED和PC_LED。
在broncho a1中,显示背光是通过LED_DRIVER1连接到LCD控制器的LED1-LED5上的。
LCD背光驱动比较简单,它主要通过操作LED1_CONTROL寄存器来控制LCD背光的开/关/强度。
LED1_CONTROL的描述:LED1_RAMP LED1_PWM<6> LED1_PWM<5> LED1_PWM<4> LED1_PWM<3>LED1_PWM<2> LED1_PWM<1> LED1_PWM<0>LCD背光设备是一个platform device,在littleton.c中定义:static struct platform_device micco_bl_device = {.name = "micco-bl",.id = -1,};LCD背光驱动程序在drivers/video/backlight/micco_bl.c:static struct platform_driver miccobl_driver = {.probe = miccobl_probe,.remove = miccobl_remove,.suspend = miccobl_suspend,.resume = miccobl_resume,软件英才网软件行业驰名招聘网站.driver = {.name = "micco-bl",},};在miccobl_probe函数里,会注册一个backlight设备:static int __init miccobl_probe(struct platform_device *pdev){struct backlight_device *bd;bd = backlight_device_register("micco-bl", &pdev->dev, NULL,&miccobl_ops);if (IS_ERR(bd))return PTR_ERR(bd);platform_set_drvdata(pdev, bd);bd->props.power = FB_BLANK_UNBLANK;bd->props.brightness = LCD_LED_DEFAULT;bd->props.max_brightness = LCD_LED_MAX;miccobl_send_intensity(bd);return 0;}对于miccobl_ops,主要提供了两个函数:static struct backlight_ops miccobl_ops = {.get_brightness = miccobl_get_intensity,.update_status = miccobl_set_intensity,};读取当前的亮度:软件英才网软件行业驰名招聘网站static int miccobl_get_intensity(struct backlight_device *bd){return current_intensity;}通过修改寄存器MICCO_LED1_CONTROL来设置亮度。
S78A可编程键盘安装手册
S78A可编程键盘安装手册吉成POS可编程键盘安装手册安装手册 I. 程序安装(Program Installation) i).先运行设置程序,然后出现以下对话框。
按“Next”键继续。
1吉成POS可编程键盘安装手册 ii) 在下列对话框中选择目标文件夹,然后按“Next”键继续。
iii) 在以下对话框中输入属于可编程键盘应用程序的程序管理器组的名称,然后按“Next”键继续。
2吉成POS可编程键盘安装手册 iv) 在以下对话框中按“Next”键开始安装程序v) 正在安装程序3吉成POS可编程键盘安装手册vi)程序安装完成,按“Finish”键退出安装。
4吉成POS可编程键盘安装手册II. 驱动程序设置(Driver Setup)这部分只适用于Windows 2000 和Windows XP系统。
对于使用在Windows 9X 和 Windows Me上的可编程键盘不须要驱动程序设置。
1) 从系统上的控制面板中打开“Device Manager” ,选择下面键盘默认的驱动程序,然后选中这个驱动程序并点击该驱动程序上的“Property” 键。
5吉成POS可编程键盘安装手册 2) 按以下对话框中的“Update Driver”键下载键盘的驱动程序。
3)按“Next” 键开始对键盘的驱动程序升级。
6吉成POS可编程键盘安装手册4) 在下面的对话框中选中“Display a list of the known drivers for this device so that Ican choose a specific driver”选项,然后按“Next” 键继续。
5)在以下对话框中,选中驱动程序的安装设备“Standard 101/102-key or MicrosoftNatural PS/2 Keyboard” ,然后按“Have Disk” 键继续。
7吉成POS可编程键盘安装手册6) 将可编程键盘应用程序的驱动程序安装在“driver”文件夹下的文件夹中,通过按“Browse”键查找“driver”文件夹。
linux和qtopia下的矩阵键盘驱动程序
linux和qtopia下的矩阵键盘驱动程序基于s3c2440和linux,实现了3*4的矩阵键盘驱动。
功能:延时消抖,重复按键,多键齐按(??)更详细的说明文档:“基于S3C24440和嵌入式Linux的矩阵键盘设计”,电子技术,2008,45(5):21-23/*********************************************************** s3c2440-keyboard.c** keyboard driver for S3C2440 based PDA*** History:2007/04/30*************************************************************/#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <asm/irq.h>#include <asm/arch/irq.h>#include <asm/arch/irqs.h>#include <asm/arch/clocks.h>#include <asm/hardware.h>#include <asm/arch/S3C2440.h>#define DEVICE_NAME "s3c2440-kb" //键盘设备名static int kbMajor = 0; //默认的主设备号#define MAX_KB_BUF 10 //循环队列的尺寸typedef struct {unsigned int keyStatus;int irq;// int timeCount;u_short buf[MAX_KB_BUF]; /* 循环队列*/unsigned int head, tail; /* 循环队列的读写指针*/spinlock_t lock; /*锁*/} KB_DEV;static KB_DEV kbdev;#define KEY_UP 0 //按键弹起#define KEY_DOWN 1 //按键按下#define NO_KEY_DOWN 2 //没有键按下#define EINT1_DOWN 0#define EINT3_DOWN 1#define EINT8_DOWN 2#define NO_EINT_DOWN 3/*循环队列操作*/#define BUF_HEAD (kbdev.buf[kbdev.head])#define BUF_TAIL (kbdev.buf[kbdev.tail])#define INCBUF(x) if((++x)==MAX_KB_BUF) x=0/*定时器设置*/#define KB_TIMER_DELAY (HZ/50) /*HZ表示每秒产生的时钟滴答数,定时器超时为20ms*/#define REPEAT_START_DELAY (HZ) /* 自动重复开始延时:1秒*/ #define REPEAT_DELAY (HZ/2) /*自动重复延时:0.5秒*/static struct timer_list kb_timer;static struct timer_list repeat_timer;spinlock_t repeat_lock;static int timeCount =1;static int TIME_OUT =5;/*键盘矩阵*/static u_short keyboard_code_map[4][3]={{1 , 2 , 3 },{4 , 5 , 6 },{7 , 8 , 9 },{10, 11, 12}}; //每个按键对应的键盘码static u_short pre_keyboard_code = 0; //上次扫描得到的按键值static u_short curr_keyboard_code = 0;//当前扫描得到的按键值static u_short snap_keyboard_code[4][3]={{0 , 0 , 0 },{0 , 0 , 0 },{0 , 0 , 0 },{0, 0, 0}}; //临时按键值#define DETECTION_THROLD 3static int requestIrq();static int s3c2440_kb_release(struct inode *inode, struct file *filp);/*----------------------------------------------------* func: 初始化GPJCON寄存器,将GPJ9,GPJ10,GPJ11,GPJ12* 配置成output管腿*------------------------------------------------------*/static void init_gpjcon(){//GPJ9,GPJ10,GPJ11,GPJ12------>outputGPJCON &= 0xFC03FFFF;GPJCON |= 0x01540000;}/*----------------------------------------------------* func: 向GPJ9,GPJ10,GPJ11,GPJ12输出value* param:* value: 输出值*------------------------------------------------------*///static inline void output_giop(int value ) //往所有行输出{value &= 0x0000000F;value <<= 9;GPJDAT &= 0xE1FF;GPJDAT |= value;udelay(2);}/*----------------------------------------------------* func: 判断eint当前是否是低电平* param:* irq: 当前引发中断的eint的irq号* return:* EINT1_DOWN: eint1上是低电平* EINT3_DOWN: eint3上是低电平* EINT8_DOWN: eint8上是低电平* NO_EINT_DOWN:eint上不是低电平------------------------------------------------------*/int get_eint_value(int irq){u_int IOValue;IOValue = GPFDAT ;if( (irq == 1) && (( IOValue & 0x00000002)==0) ) {return EINT1_DOWN;}if((irq ==3 ) && (( IOValue & 0x00000008)==0) ) {return EINT3_DOWN;}IOValue = GPGDAT ;if((irq ==36) && (( IOValue & 0x0000001)==0) ) {return EINT8_DOWN;}return NO_EINT_DOWN;}/*----------------------------------------------------* func: 扫描键盘,判断哪一个键被按下* param:* x: 得到按键的行号* y: 得到按键的列号* return:* KEY_DOWN: 键盘上有键被按下* NO_KEY_DOWN: 键盘上没有键被按下------------------------------------------------------*/static inline int scan_keyboard(int* x,int* y) {int matrix_row,matrix_col,matrix_col_status; output_giop(0xF); //往所有行输出1//判断按键在哪一行matrix_row=matrix_col=-1;output_giop(0xE);//在第1行上输出1,其余行输出0 matrix_col_status = get_eint_value(kbdev.irq);if(matrix_col_status != NO_EINT_DOWN){matrix_row = 0;matrix_col = matrix_col_status;goto scanend;}output_giop(0xD);//在第2行上输出1,其余行输出0matrix_col_status = get_eint_value(kbdev.irq);if(matrix_col_status != NO_EINT_DOWN){matrix_row=1;matrix_col = matrix_col_status;goto scanend;}output_giop(0xB);//在第3行上输出1,其余行输出0 matrix_col_status =get_eint_value(kbdev.irq);if(matrix_col_status != NO_EINT_DOWN){matrix_row=2;matrix_col = matrix_col_status;goto scanend;}output_giop(0x7);//在第4行上输出1,其余行输出0 matrix_col_status =get_eint_value(kbdev.irq);if(matrix_col_status != NO_EINT_DOWN){matrix_row=3;matrix_col = matrix_col_status;goto scanend;}scanend:output_giop(0);if(matrix_row >=0 ){snap_keyboard_code[matrix_row][matrix_col_status]=snap_keyboard_code[matrix_row][matrix_col_status] + 1;if(snap_keyboard_code[matrix_row][matrix_col]>=DETECTION_THROLD) {*x=matrix_row;*y=matrix_col;curr_keyboard_code = keyboard_code_map[matrix_row][matrix_col]; return KEY_DOWN;}}return NO_KEY_DOWN;}/*----------------------------------------------------* func: 判断本次按键是否与上次按键相同* param:** return:* 0: 相同* 1: 不同------------------------------------------------------*/static inline int key_changed(){return (pre_keyboard_code == curr_keyboard_code)? 0 : 1; }/*----------------------------------------------------* func: 将按键对应的键盘码保存到循环队列中* param:* keyValue: 按键的对应的键盘码* return:*------------------------------------------------------*/static inline void save_key_to_queue(u_short keyValue) {if (kbdev.keyStatus == KEY_DOWN){BUF_HEAD = keyValue;INCBUF(kbdev.head);//wake_up_interruptible(&(kbdev.wq));}}/*----------------------------------------------------* func: 重复按键定时器处理程序,如果一直按住某键,则将该键的键盘码定时存到循环队列中* param:* data: 无参数* return:*------------------------------------------------------*/static inline void repeat_timer_handler(unsigned long data){spin_lock_irq(&(repeat_lock));if(kbdev.keyStatus ==KEY_DOWN){repeat_timer.expires = jiffies + REPEAT_DELAY;//设置自动重复延时add_timer(&repeat_timer);//将定时器加入队列if(pre_keyboard_code != 0){//printk("repeat save keyvalue\n %d",pre_keyboard_code);save_key_to_queue(pre_keyboard_code);//将按键值存入循环队列}}else//如果按键弹起{//del_timer(&repeat_timer);// printk("del repeat timer\n");}spin_unlock_irq(&(repeat_lock));}/*----------------------------------------------------* func: 使能中断* param:* return:*------------------------------------------------------*///使能中断static inline void enableIrq(){//清除SRCPND寄存器中eint1 eint2 eint8相应位SRCPND = 0x0000002A;//使能中断enable_irq(IRQ_EINT1);enable_irq(IRQ_EINT3);enable_irq(IRQ_EINT8);}/*----------------------------------------------------* func: 键盘定时扫描程序,如果得到稳定键码,将键码存* 入循环队列;如果没有,则延时20ms后继续扫描* param:* data: 无参数* return:*------------------------------------------------------*/static inline void kb_timer_handler(unsigned long data){int x,y;spin_lock_irq(&(kbdev.lock));x = y = 0;if(scan_keyboard(&x,&y) == KEY_DOWN){// printk("snap_keyboard_code=%d, %d, %d, %d\n",snap_keyboard_code[0][1],snap_keyboard_code[1][1],snap_keyboard_c ode[2][1],snap_keyboard_code[3][1]);kbdev.keyStatus =KEY_DOWN;if(key_changed()){pre_keyboard_code = curr_keyboard_code;save_key_to_queue(pre_keyboard_code);//printk("KEY_DOWN:%d x=%d y =%d\n",timeCount,x,y);//设置自动重复开始延时定时器/*repeat_timer.expires = jiffies + REPEAT_START_DELAY;add_timer(&repeat_timer);*/}timeCount=1;memset(snap_keyboard_code,0,12*sizeof(u_short));//curr_keyboard_code =0;kb_timer.expires = jiffies + KB_TIMER_DELAY;add_timer(&kb_timer);}else{//printk("snap_keyboard_code=%d, %d, %d, %d\n",snap_keyboard_code[3][0],snap_keyboard_code[3][1],snap_keyboard_c ode[3][2],snap_keyboard_code[3][3]);kb_timer.expires = jiffies + KB_TIMER_DELAY;add_timer(&kb_timer);//printk("timeCount:%d\n",timeCount);if (timeCount==TIME_OUT) //扫描5次后仍然没有得到稳定键值{//复位计数器timeCount=1;kbdev.keyStatus =KEY_UP;//使能中断enableIrq();//关闭定时器del_timer(&kb_timer);del_timer(&repeat_timer);//printk("enable irq \n\n\n");curr_keyboard_code = 0;pre_keyboard_code= 0 ;memset(snap_keyboard_code,0,12*sizeof(u_short));elsetimeCount++;}spin_unlock_irq(&(kbdev.lock));}/*----------------------------------------------------* func: 从循环队列中读取按键的键码* param:* return: 按键的键码*------------------------------------------------------*/static inline int kbRead(){u_short keyvalue;spin_lock_irq(&(kbdev.lock));keyvalue = BUF_TAIL;INCBUF(kbdev.tail );spin_unlock_irq(&(tsdev.lock));return keyvalue;}/*----------------------------------------------------* func: 对应文件读的函数,如果循环队列中有键码, 则将键码拷贝到用户空间的buffer中* param:** return:* 返回从循环队列中读取的键码的字节数**------------------------------------------------------*/static ssize_tS3C2440_kb_read(struct file *filp, char *buffer, size_t count, loff_t * ppos) {u_short keyvalue;if(kbdev.head == kbdev.tail){return 0;}else{keyvalue = kbRead();count = sizeof(keyvalue);/*将数据拷贝到用户空间*/copy_to_user(buffer,&(keyvalue),count);return count;}}/*----------------------------------------------------* func: 与打开文件对应的open函数,初始化全局变量和定* 时器以及请求中断* param:*** return:*------------------------------------------------------*/static int S3C2440_kb_open(struct inode *inode, struct file *filp) {kbdev.keyStatus = KEY_UP;kbdev.head=kbdev.tail = 0;kbdev.lock = SPIN_LOCK_UNLOCKED;repeat_lock = SPIN_LOCK_UNLOCKED;output_giop(0);//初始化定时器init_timer(&kb_timer);kb_timer.function = kb_timer_handler;//初始化重复按键定时器init_timer(&repeat_timer);repeat_timer.function = repeat_timer_handler;/*if(requestIrq() !=0)return -1;*/enableIrq();MOD_INC_USE_COUNT;return 0;}static struct file_operations kb_fops = {owner: THIS_MODULE,open: S3C2440_kb_open,read: S3C2440_kb_read,release: s3c2440_kb_release,};/*----------------------------------------------------* func: 中断处理程序,关闭中断开启键盘扫描定时器* param:*** return:*------------------------------------------------------*/static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) {spin_lock_irq(&kbdev.lock);//禁止所有中断disable_irq(IRQ_EINT1);disable_irq(IRQ_EINT3);disable_irq(IRQ_EINT8);kbdev.irq = irq;//printk("irq=%d\n",kbdev.irq);//启动定时器kb_timer.expires = jiffies + KB_TIMER_DELAY;add_timer(&kb_timer);repeat_timer.expires = jiffies + REPEAT_START_DELAY;add_timer(&repeat_timer);spin_unlock_irq(&kbdev.lock);}/*----------------------------------------------------* func: 初始化eint中断相关寄存器,安装中断处理程序* param:*** return:*------------------------------------------------------*/static int requestIrq(){int ret;/* Enable interrupt *///==================================================// irq: Linux中断号,与硬件中断号不同// handle: 中断处理程序// flag: SA_INTERRUPT指示这是个快速中断处理程序// dev_id: 用于共享的中断信号线,通常设置成NULL//===================================================ret =set_external_irq(IRQ_EINT1,EXT_FALLING_EDGE,GPIO_PULLUP_DIS); if(ret)goto eint_failed ;ret = request_irq(IRQ_EINT1, keyboard_interrupt, SA_INTERRUPT, DEVICE_NAME, NULL);if(ret)goto eint1_failed;ret =set_external_irq(IRQ_EINT8,EXT_FALLING_EDGE,GPIO_PULLUP_DIS); //EXT_LOWLEVELif(ret)goto eint_failed;ret = request_irq(IRQ_EINT8, keyboard_interrupt, SA_INTERRUPT, DEVICE_NAME, NULL);if(ret)goto eint8_failed;ret =set_external_irq(IRQ_EINT3,EXT_FALLING_EDGE,GPIO_PULLUP_DIS); if(ret)goto eint_failed;ret = request_irq(IRQ_EINT3, keyboard_interrupt, SA_INTERRUPT, DEVICE_NAME, NULL);if(ret)goto eint3_failed;return 0;eint3_failed:free_irq(IRQ_EINT3, keyboard_interrupt);eint8_failed:free_irq(IRQ_EINT8, keyboard_interrupt);eint1_failed:free_irq(IRQ_EINT1, keyboard_interrupt);eint_failed:printk(DEVICE_NAME ": IRQ Requeset Error\n");return ret;}static int s3c2440_kb_release(struct inode *inode, struct file *filp){/*注销设备*/// unregister_chrdev(kbMajor, DEVICE_NAME);/*释放中断*//*free_irq(IRQ_EINT1,NULL);free_irq(IRQ_EINT8,NULL);free_irq(IRQ_EINT3,NULL);MOD_DEC_USE_COUNT;*/return 0;}/*----------------------------------------------------* func: 初始化键盘驱动,注册字符设备* param:*** return:>=0 : 初始化键盘驱动成功<0: 失败*------------------------------------------------------*/static int __init s3c2440_kb_init(void){int ret;/*初始化管腿配置*/init_gpjcon();output_giop(0);/*注册设备*/ret = register_chrdev(99, DEVICE_NAME, &kb_fops); if(ret < 0) {printk(DEVICE_NAME " can't get major number\n"); return ret;}kbMajor = ret;printk("%s: major number=99\n",DEVICE_NAME);requestIrq();//暂时禁止所有中断,等到open时再打开disable_irq(IRQ_EINT1);disable_irq(IRQ_EINT3);disable_irq(IRQ_EINT8);return 0;}/*----------------------------------------------------* func: 注销字符设备,释放中断* param:*** return:*------------------------------------------------------*/static void __exit s3c2440_kb_exit(void){/*注销设备*/unregister_chrdev(kbMajor, DEVICE_NAME); printk("exit\n");/*释放中断*/free_irq(IRQ_EINT1,NULL);free_irq(IRQ_EINT8,NULL);free_irq(IRQ_EINT3,NULL);}module_init(s3c2440_kb_init);module_exit(s3c2440_kb_exit);//EXPORT_SYMBOL(s3c2440_kb_init);//EXPORT_SYMBOL(s3c2440_kb_exit);如果将此驱动和qtopia程序结合起来,需要修改qt源代码的qkeyboard_qws.cpp文件,添加对矩阵键盘的支持class QWSHPCButtonsHandler : public QWSKeyboardHandler {Q_OBJECTpublic:QWSHPCButtonsHandler();virtual ~QWSHPCButtonsHandler();bool isOpen() { return buttonFD > 0; }private slots:void readKeyboardData();private:QString terminalName;int buttonFD;struct termios newT, oldT;QSocketNotifier *notifier;};QWSHPCButtonsHandler::QWSHPCButtonsHandler() : QWSKeyboardHandler(){#ifdef QT_QWS_HPCterminalName = "/dev/keyboard";buttonFD = -1;notifier = 0;if ((buttonFD = open(terminalName, O_RDONLY | O_NDELAY, 0)) < 0) { qWarning("Cannot open %s\n", tin1());return;}notifier = new QSocketNotifier( buttonFD, QSocketNotifier::Read, this ); connect( notifier, SIGNAL(activated(int)),this,SLOT(readKeyboardData()) );#endif}QWSHPCButtonsHandler::~QWSHPCButtonsHandler(){#ifdef QT_QWS_HPCif ( buttonFD > 0 ) {::close( buttonFD );buttonFD = -1;}#endif}void QWSHPCButtonsHandler::readKeyboardData(){#ifdef QT_QWS_HPC//-----------port form ButtonDetect-begin-----------int tempint,i;unsigned short buffer[1];tempint=0;int current_press=-1;do{tempint=read(buttonFD,buffer,1);if(tempint > 0 ){// printf("\nCurrent Press Buttom %d \n",buffer[0]);current_press = (int)buffer[1];goto set_hpckey;}}while(tempint >0);//-----------port form ButtonDetect-end-------------set_hpckey:int k=(-1);switch(current_press) {case 3: k=Qt::Key_Up; break; //case 11: k=Qt::Key_Down; break; //case 8: k=Qt::Key_Left; break; //case 6: k=Qt::Key_Right; break; //case 7: k=Qt::Key_Enter; break; // Entercase 4: k=Qt::Key_Escape; break; // Enter default: k=(-1); break;}if ( k >= 0 ){qwsServer->processKeyEvent( 0, k, 0, 1, false ); }#endif}。
4×5矩阵键盘驱动程序
4×5矩阵键盘驱动程序一、工作原理及接口电路4×5矩阵键盘有4条列线,5条行线共20个按键。
每个按键对应不同键值,键盘扫描采用外部中断扫描方式,本系统中键盘为无源结构,键盘工作时不依靠任何外部电源。
4×5矩阵键盘结构图如图2-10 所示。
图2-10 4×5矩阵键盘结构图1)4×5矩阵键盘结构及按键抖动消除当键盘中按键数量较多时为减少I/O口的占用,通常将按键排列成矩阵形式,如图2-12所示。
在矩阵式键盘中,每条行线和列线在交叉处不直接连通,而是通过一个机械弹性开关加以连接。
这样5条列线(R0~R4)和4条行线(L0~L3)就可以构成20个按键的矩阵键盘。
键盘采用了无源结构,工作是不依靠任何外部电源。
由于机械弹性开关的机械触点的弹性作用,一个按键开关在闭合时并不会马上稳定的闭合,在断开时也不会马上断开,因而机械开关在闭合及断开瞬间均伴有一连串的抖动,如图2-11所示。
图2-11 按键时的抖动抖动的时间长短由按键开关机械特性及按键的人为因素决定,一般为5ms~20ms。
按键抖动如果处理不当会引起一次按键被误处理多次,所以消除抖动是必要的。
消除抖动的有硬件处理和软件处理两种方法。
当按键较多一般采用软件消抖方式。
软件消抖原理为当检测出按键闭合后执行一个延时程序(产生5ms~20ms的延时),待前沿抖动消失后再次检测按键的状态,如果按键仍保持闭合状态则可确认为有键按下。
当检测到按键释放并执行延时程序,待后沿抖动消失后才转入按键的处理程序。
1)矩阵键盘的工作原理从4×5矩阵键盘的4条列线和5条行线分别引出9条端线接于单片机的9个I/O 口,由于键盘采用了无源结构所以行列线的电平由单片机I/O口的电平决定。
进入按键处理程序后先使4条列线全为低电平,5条行线全为高电平,为读行线状态做准备,没有按键时这种状态不会被改变。
当键盘上的某个按键闭合时,则该键所对应的行线和列线被短路。
第七章 键盘驱动程序 Linux设备驱动程序 教学课件
键盘的分类
线性键盘
它是指每个按键都占用嵌入式处理器的 一个I/O端口,并通过这个I/O端口实现 人机交互,各个按键之间互不影响。 这种方法简单、可靠,但是对I/O端口的 1. 占用量很大。
矩阵键盘
它是指当按键数量过多时,采用矩阵的 排列方法,将键盘设计成N行M列的矩 阵形式。其中,每个按键占用行和列的 一个交点,并且以行和列为单位引出信 号线。 这样总共有N+M根信号线,虽然需要与 N+M个I/O端口相连,却可以驱动N*M个 按键。大大减少了对嵌入式处理器I/O端 口的占用,节省了宝贵的资源。
write_gpio_bit(dat, 1)
write_gpio_bit(dat, 0)
//CPLD_BASE的定义在/includ/asm-arm/arch-s3c2410/smdk.h内.#define KEYBOARD_MAJOR 50
#define Kbd7279_GETKEY 0
int KeyValue;
目录
键盘接口概述 键盘的驱动程序设计实例 IIC接口芯片ZLG7290扩展键盘 智能控制芯片HD7279扩展键盘
说明
ZLG7290读普通键的入口地址和读功能键 的入口地址不同,读普通按键的地址为 01H,读功能键的地址为03H。读普通键 返回按键的编号,读功能键返回的不是按 键编号,需要程序对返回值进行翻译,转 换成功能键的编号。
set_gpio_ctrl(dat);
set_gpio_ctrl(GPIO_F5|GPIO_MODE_EINT);
//set EINT MODE
set_external_irq(33,2,0);
for(i=0;i<100;i++);
4X4键盘的SIOC驱动程式开发
嵌入式軟體期中作業4X4鍵盤的SIOC驅動程式開發995202051_黃子濬1.硬體周邊原理每個按鍵有它的行值和列值,行值和列值的組合就是識別這個按鍵的編碼。
矩陣的行線和列線分別通過兩並行接口和CPU通信。
鍵盤處理程序的任務是:確定有無鍵按下,判斷哪一個鍵按下,鍵的功能是什麼;還要消除按鍵在閉合或斷開時的抖動。
兩個並行口中,一個輸出掃描碼,使按鍵逐行動態接地,另一個並行口輸入按鍵狀態,由行掃描值和回饋信號共同形成鍵編碼而識別按鍵,通過軟件查表,查出該鍵的功能。
2.SIOC的Driver設計及主要程式說明以下程式碼主要流程:a.設定四隻in pin(0~3)腳&設定四隻out pin(4~7)腳分別對應4*4鍵盤的16個按鍵b.在每次while迴圈開始時先把in pin(0~3)腳reset為0,其中一隻out pin(4)腳set為1其餘out pin(5~7)腳reset為0c.依序檢測每隻in pin腳是否為1,如為1表示有鍵值輸入並將鍵盤上對應的數字print出來d.檢測完四隻in pin腳之後,將out pin(4) reset為0並將out pin(5) set為1,並回到步驟c,之後依序將剩餘兩隻out pin(6~7)腳set為1即可完成整個鍵盤的掃描輸入。
int main(void){RCC_Configuration();TIM_Configuration();GPIO_Configuration();NVIC_Configuration();Set_System();while(1){GPIO_ResetBits(GPIOA, GPIO_Pin_0);GPIO_ResetBits(GPIOA, GPIO_Pin_1);GPIO_ResetBits(GPIOA, GPIO_Pin_2);GPIO_ResetBits(GPIOA, GPIO_Pin_3);GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);GPIO_ResetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_7);if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)!=0){while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==1);printf("c\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)!=0) {while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)==1);printf("8\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)!=0) {while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)==1);printf("4\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)!=0) {while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==1);printf("0\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else{GPIO_SetBits(GPIOA, GPIO_Pin_5);GPIO_ResetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_7);if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)!=0){while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==1);printf("d\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)!=0){while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)==1);printf("9\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)!=0){while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)==1);printf("5\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)!=0){while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==1);printf("1\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else{GPIO_SetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);GPIO_ResetBits(GPIOA, GPIO_Pin_7);if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)!=0) {while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==1);printf("e\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)!=0) {while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)==1);printf("a\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)!=0){printf("6\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)!=0){while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==1);printf("2\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else{GPIO_SetBits(GPIOA, GPIO_Pin_7);GPIO_ResetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);GPIO_ResetBits(GPIOA, GPIO_Pin_6);if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)!=0){while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==1);printf("f\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)!=0){printf("b\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)!=0){while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)==1);printf("7\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)!=0){while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==1);printf("3\r\n");Delay(0x8ffff);Delay(0x8ffff); Delay(0x8ffff);}}}}}}void GPIO_Configuration(void)//設定GPIO pin腳{GPIO_InitStructure.GPIO_Pin= GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin= GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);}3.SIOC與週邊的接線圖3.1鍵盤&SIOC面板3.2鍵盤接線3.3SIOC接線(PA0~PA7)4.SIOC驗證下圖為測試SIOC是否都能確實接收來自鍵盤的按鍵。
4个按键驱动程序
;4个按键驱动程序;4X4 按键驱动程序POUT EQU P2KPIN EQU P1PDIG1 EQU P3.0V AL DA TA 30HKID DA TA 31HKTMP DA TA 32H;*************************;按键扫描程序;;模块应用变量;硬件连接端口:KPIN;返回按键值:V AL;按键处理应用功能程序:KEYPFUN ;;***********************;内部使用变量定义:KID=0,KTMP=0MOV KID,#0MOV KTMP,#0MOV V AL,#0;********************** KEYS:MOV DPTR,#KJMPMOV A,KIDRL AJMP @A+DPTRKJMP:AJMP KEYENAJMP KEYDELAJMP KEYSCANAJMP KEYUPAJMP KEYFUNMOV KID,#0RETKS: MOV KPIN,#0FH NOPNOPMOV A,KPINANL A,#0FHXRL A,#0FHRETKEYEN:ACALL KSJZ KENEXTMOV KTMP,#0INC KID KENEXT: RET KEYDEL:INC KTMPMOV A,KTMPCJNE A,#30,KDEXTMOV KTMP,#0INC KID KDEXT: RETKEYUP:ACALL KSJNZ KUPEXTINC KID KUPEXT: RET;********************;KPIN:0 0 0 0 1 1 1 1 =0FH ;KV AL:0 0 0 0 1 1 1 1 =F;KV AL:0 0 0 0 1 1 1 0 =E;KV AL:0 0 0 0 1 1 0 1 =D;KV AL:0 0 0 0 1 1 0 0 =C;KV AL:0 0 0 0 1 0 1 1 =B;KV AL:0 0 0 0 1 0 1 0 =A;KV AL:0 0 0 0 1 0 0 1 =9;KV AL:0 0 0 0 1 0 0 0 =8;KV AL:0 0 0 0 0 1 1 1 =7;KV AL:0 0 0 0 0 1 1 0 =6;KV AL:0 0 0 0 0 1 0 1 =5;KV AL:0 0 0 0 0 1 0 0 =4;KV AL:0 0 0 0 0 0 1 1 =3;KV AL:0 0 0 0 0 0 1 0 =2;KV AL:0 0 0 0 0 0 0 1 =1KEYSCAN:ACALL KSJZ KSEXTMOV V AL,AINC KIDRETKSEXT:MOV KID,#0RET;*************************; KEYFUN:MOV KID,#0MOV DPTR,#KFUNMOV A,V ALRL AJMP @A+DPTRKFUN:AJMP KFUNLAJMP K1FUNAJMP K2FUNAJMP K3FUNAJMP K4FUNMOV V AL,#0RETKFUNL: NOPRETK1FUN:RETK2FUN:RETK3FUN:RETK4FUN:RET;******************************;********************;KPIN:0 0 0 0 1 1 1 1 =0FH ;KV AL:0 0 0 0 1 0 0 0 =1;KV AL:0 0 0 0 0 1 0 0 =2;KV AL:0 0 0 0 0 0 1 0 =3;KV AL:0 0 0 0 0 0 0 1 =4;******************** KEYSCAN:ACALL KSJZ KSEXTMOV R4,#4CLR CKSLP:RRC AJC KV ALDJNZ R4,KSLP KSEXT:MOV KID,#0RETKV AL:MOV V AL,R4INC KIDRET;***********************;********************;KPIN:0 0 0 0 1 1 1 1 =0FH ;KV AL:0 0 0 0 1 0 0 0 =4;KV AL:0 0 0 0 0 1 0 0 =3;KV AL:0 0 0 0 0 0 1 0 =2;KV AL:0 0 0 0 0 0 0 1 =1 KEYSCAN:ACALL KSJZ KSEXTMOV R4,#0CLR CKSLP:RRC AJC KV ALINC R4CJNE R4,#4,KSLP KSEXT:MOV KID,#0RETKV AL:INC R4MOV V AL,R4INC KIDRET;************************;可用于拔码盘;********************;KPIN:0 0 0 0 1 1 1 1 =0FH;KV AL:0 0 0 0 1 1 1 1 =F;KV AL:0 0 0 0 1 1 1 0 =E;KV AL:0 0 0 0 1 1 0 1 =D;KV AL:0 0 0 0 1 1 0 0 =C;KV AL:0 0 0 0 1 0 1 1 =B;KV AL:0 0 0 0 1 0 1 0 =A;KV AL:0 0 0 0 1 0 0 1 =9;KV AL:0 0 0 0 1 0 0 0 =8;KV AL:0 0 0 0 0 1 1 1 =7;KV AL:0 0 0 0 0 1 1 0 =6;KV AL:0 0 0 0 0 1 0 1 =5;KV AL:0 0 0 0 0 1 0 0 =4;KV AL:0 0 0 0 0 0 1 1 =3;KV AL:0 0 0 0 0 0 1 0 =2;KV AL:0 0 0 0 0 0 0 1 =1 KEYSCAN:ACALL KSJZ KSEXTMOV V AL,AINC KIDRETKSEXT:MOV KID,#0RET;*************************;*************************** ;*************************;KPIN: D7 - D0 =0FEH; D7 D6 D5 D4 ; D0 0 1 2 3 ; D1 4 5 6 7 ; D2 8 9 A B ; D3 C D E FKEYSCAN:ACALL KSJZ KSCEXTMOV R2,#0FEHMOV R3,#0KS1:MOV KPIN,R2NOPNOPMOV A,KPINMOV R4,#4SETB CKS2:RLC AJNC KV ALINC R3DJNZ R4,KS2MOV A,R2JNB ACC.3,KSCEXTRL AMOV R2,ASJMP KS1KV AL:MOV V AL,R3INC KIDRETKSCEXT:MOV KID,#0RET;************************;***************************** ;KPIN: D7 - D0 =0EFH; D7 D6 D5 D4 ; D0 C 8 4 0 ; D1 D 9 5 1 ; D2 E A 6 2 ; D3 F B 7 3KEYSCAN:ACALL KSJZ KSCEXTMOV R2,#0EFHMOV R3,#0KS1:MOV KPIN,R2NOPNOPMOV A,KPINMOV R4,#4SETB CKS2:RRC AJNC KV ALINC R3DJNZ R4,KS2MOV A,R2JNB ACC.7,KSCEXTRL AMOV R2,ASJMP KS1KV AL:MOV V AL,R3INC KIDRETKSCEXT:MOV KID,#0RET;************************;**************************;KPIN: D7 - D0 =0EFH; D7 D6 D5 D4 ; D0 F B 7 3 ; D1 E A 6 2 ; D2 D 9 5 1 ; D3 C 8 4 0KEYSCAN:ACALL KSJZ KSCEXTMOV R2,#0EFHMOV R3,#0KS1:MOV KPIN,R2NOPNOPMOV A,KPINANL A,#0FHXRL A,#0FHJZ KS3MOV R4,#4SETB CKS2:RRC AJC KV ALDJNZ R4,KS2 KSCEXT:MOV KID,#0RETKS3:MOV A,R2JNB ACC.7,KSCEXTRL AINC R3MOV R2,ASJMP KS1KV AL:MOV A,R3RL ARL ADEC AADD A,R4MOV V AL,AINC KIDRET;*************************;************************;KPIN: D7 - D0 =0EFH; D7 D6 D5 D4 ; D0 C 8 4 0 ; D1 D 9 5 1 ; D2 E A 6 2 ; D3 F B 7 3 KEYSCAN:ACALL KSJZ KSCEXTMOV R2,#0EFHMOV R3,#0KS1:MOV KPIN,R2NOPNOPMOV A,KPINANL A,#0FHXRL A,#0FHJZ KS3MOV R4,#0SETB CKS2:RRC AJC KV ALINC R4CJNE R4,#4,KS2 KSCEXT:MOV KID,#0RETKS3:MOV A,R2JNB ACC.7,KSCEXTRL AINC R3MOV R2,ASJMP KS1KV AL:MOV A,R3RL ARL AADD A,R4MOV V AL,AINC KIDRET;*************************;*************************;KPIN: D7 - D0 =0FEH; D7 D6 D5 D4 ; D0 0 1 2 3 ; D1 4 5 6 7 ; D2 8 9 A B ; D3 C D E F KEYSCAN:ACALL KSJZ KSCEXTMOV R2,#0FEHMOV R3,#0KS1:MOV KPIN,R2NOPNOPMOV A,KPINANL A,#0F0HXRL A,#0F0HJZ KS3MOV R4,#0SETB CKS2:RLC AJC KV ALINC R4CJNE R4,#4,KS2 KSCEXT:MOV KID,#0RETKS3:MOV A,R2JNB ACC.3,KSCEXTRL AINC R3MOV R2,ASJMP KS1KV AL:MOV A,R3RL ARL AADD A,R4MOV V AL,AINC KIDRET;********************;******************************* ;KPIN: D7 - D0 =0EFH; D7 D6 D5 D4 ; D0 3 2 1 0; D1 7 6 5 4; D2 B A 9 8; D3 F E D CKEYSCAN:ACALL KSJZ KSCEXTMOV R2,#0FEHMOV R3,#0KS1:MOV KPIN,R2NOPNOPMOV A,KPINANL A,#0F0HXRL A,#0F0HJZ KS3MOV R4,#4SETB CKS2:RLC AJC KV ALDJNZ R4,KS2 KSCEXT:MOV KID,#0RETKS3:MOV A,R2JNB ACC.3,KSCEXTRL AINC R3MOV R2,ASJMP KS1KV AL:MOV A,R3RL ARL AADD A,R4DEC AMOV V AL,AINC KIDRET;*********************;************************;KPIN: D7 - D0 =0EFH; D7 D6 D5 D4 ; D0 C 8 4 0 ; D1 D 9 5 1; D3 F B 7 3 KEYSCAN:ACALL KSJZ KSCEXTMOV R2,#0FEHMOV R3,#0KS1:MOV KPIN,R2NOPNOPJB KPIN.4,KSL1MOV A,#0SJMP KV ALKSL1:JB KPIN.5,KSL2MOV A,#4SJMP KV ALKSL2:JB KPIN.6,KSL3MOV A,#8SJMP KV ALKSL3:JB KPIN.7,KS2MOV A,#12KV AL:ADD A,R3MOV V AL,AINC KIDRETKSCEXT:MOV KID,#0RETKS2:MOV A,R2JNB ACC.3,KSCEXTRL AINC R3MOV R2,ASJMP KS1;****************************;**************************;KPIN: D7 - D0 =0FEH; D7 D6 D5 D4 ; D0 3 2 1 0; D2 B A 9 8 ; D3 F E D CKEYSCAN:ACALL KSJZ KSCEXTMOV R2,#0EFHMOV R3,#0KS1:MOV KPIN,R2NOPNOPJB KPIN.0,KSL1MOV A,#0SJMP KV ALKSL1:JB KPIN.1,KSL2MOV A,#4SJMP KV ALKSL2:JB KPIN.2,KSL3MOV A,#8SJMP KV ALKSL3:JB KPIN.3,KS2MOV A,#12KV AL:ADD A,R3MOV V AL,AINC KIDRETKSCEXT:MOV KID,#0RETKS2:MOV A,R2JNB ACC.7,KSCEXTRL AINC R3MOV R2,ASJMP KS1;************************。
S3C44B0X按键键盘的μClinux驱动程序设计
S3C44B0X按键键盘的μClinux驱动程序设计
吴旭;屈万里
【期刊名称】《电子工程师》
【年(卷),期】2006(32)5
【摘要】用三星公司的嵌入式微处理器S3C44B0X设计的嵌入式开发板大多采用1×4按键键盘,在移植μC linux到这类开发板上时,必须设计键盘驱动程序。
1×4键盘驱动程序通过修改μC linux源代码中PC键盘的驱动程序得到。
根据实际电路,对键盘的初始化、键盘中断处理程序进行了处理,用户可根据需要决定各键的扫描码。
此驱动程序利用操作系统计时器解决了键盘的抖动问题。
1×4键盘驱动程序可用于其他类似的嵌入式系统。
【总页数】2页(P50-51)
【关键词】S3C44BOX;开发板;按键键盘;μClinux;驱动程序
【作者】吴旭;屈万里
【作者单位】华中科技大学电子与信息工程系
【正文语种】中文
【中图分类】TP316.8
【相关文献】
1.WinCE下的SPI键盘硬件及驱动程序设计 [J], 刘智国;张伟丽
2.基于μClinux和S3C44B0X的A/D设备驱动程序的设计 [J], 刘鑫;雷升印
3.基于μClinux嵌入式车载网络系统的CAN总线设备驱动程序设计 [J], 黄涛;周
德恒
4.基于μClinux嵌入式车载网络系统的CAN总线设备驱动程序设计 [J], 黄涛;周德恒
5.基于μClinux的火灾报警系统CAN总线设备驱动程序设计 [J], 夏鹏晖;张秋燕;张李静
因版权原因,仅展示原文概要,查看原文内容请购买。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
EDA技术课程设计任务书
班级:姓名:程鼐学号:
设计题目:键盘驱动程序
一、设计目的
进一步巩固理论知识,培养所学理论知识在实际中的应用能力;掌握EDA设计的一般方法;熟悉一种EDA软件,掌握一般EDA系统的调试方法;利用EDA软件设计一个电子技术综合问题,培养VHDL编程、书写技术报告的能力。
为以后进行工程实际问题的研究打下设计基础。
二、设计任务
利用外接键盘实现键盘按键的选择,在8位动态七段数码管上实现按键扫描码的显示,在16X16点阵上实现按键字符的显示。
三、设计要求
(1)通过对相应文献的收集、分析以及总结,给出相应课题的背景、意义及现状研究分析。
(2)通过课题设计,掌握计算机组成原理的分析方法和设计方法。
(3)学习按要求编写课程设计报告书,能正确阐述设计和实验结果。
(4)学生应抱着严谨认真的态度积极投入到课程设计过程中,认真查阅相应文献以及实现,给出个人分析、设计以及实现。
四、设计时间安排
查找相关资料(1天)、设计并绘制系统原理图(2天)、编写VHDL程序(2天)、调试(2天)、编写设计报告(2天)和答辩(1天)。
五、主要参考文献
[1] 江国强编著. EDA技术与实用(第三版). 北京:电子工业出版社,2011.
[2] 曹昕燕,周凤臣.EDA技术实验与课程设计.北京:清华大学出版社,2006.5
[3] 阎石主编.数字电子技术基础.北京:高等教育出版社,2003.
[4] Mark Zwolinski. Digital System Design with VHDL.北京:电子工业出版社,2008
[5] Alan B. Marcovitz Introduction to logic Design.北京:电子工业出版社,2003
指导教师签字:年月日。