键盘驱动程序设计(中)

问题

键盘扫描码可以直接使用吗?扫描码代表键位上的字符吗?

键盘扫描码不可以直接使用,扫描码不代表键位上的字符。

常用编码区别

扫描码(Scan Code)

  • 与键盘厂商有关,不同厂商的扫描码可能不同

虚拟键码(Key Code)

  • 键盘按键统一标准编码 (键盘厂商无关)

ASCII 码

  • 常用字符的统一编码 (键盘按键无关)

键盘驱动设计

建立扫描码,虚拟键码,ASCII 码之间的映射

解析扫描码,处理常用组合键 (Shift,Caps lock,等)

用4字节表示键盘操作结果:动作 | 扫描码 | 虚拟键码 | ASCII

键盘驱动主要功能

处理主键盘按键

  • 字符按键,功能按键,Shift,Cpas Lock

处理数字键盘按键

  • 字符按键,Shift,Num Lock

处理特殊字符

  • Pause Break

深入键盘扫描码

普通按键:1字节 (按键扫描码)

E0拓展按键:2字节 (0xE0 + 按键扫描码)

  • E0拓展按键是一个键盘上有2个相同的键,它们具有相同的扫描码,其中一个按键用按键扫描码表示,另一个按键用 0xE0 + 按键扫描码表示。

E1拓展按键:6字节 (Break Pause)

E2拓展按键:......

关键体力活 => 建立映射表

键盘驱动关键逻辑

键盘驱动关键逻辑

键盘驱动程序设计

keyboard.h


#ifndef KEYBOARD_H
#define KEYBOARD_H

#include "type.h"

void PutScanCode(byte sc);
uint FetchKeyCode();

#endif

keyboard.c


#include "keyboard.h"
#include "screen.h"
#include "utility.h"

typedef struct
{
	byte ascii1;   // no shift code
    byte ascii2;   // shift code
    byte scode;    // scan code
    byte kcode;    // key code
} KeyCode;

enum
{
	KeyRelease = 0,
	KeyPress = 0x1000000
};

static const KeyCode gKeyMap[] = 
{
/* 0x00 - none      */ {  0,        0,        0,         0   },
/* 0x01 - ESC       */ {  0,        0,       0x01,      0x1B },
/* 0x02 - '1'       */ { '1',      '!',      0x02,      0x31 },
/* 0x03 - '2'       */ { '2',      '@',      0x03,      0x32 },
/* 0x04 - '3'       */ { '3',      '#',      0x04,      0x33 },
/* 0x05 - '4'       */ { '4',      '$',      0x05,      0x34 },
/* 0x06 - '5'       */ { '5',      '%',      0x06,      0x35 },
/* 0x07 - '6'       */ { '6',      '^',      0x07,      0x36 },
/* 0x08 - '7'       */ { '7',      '&',      0x08,      0x37 },
/* 0x09 - '8'       */ { '8',      '*',      0x09,      0x38 },
/* 0x0A - '9'       */ { '9',      '(',      0x0A,      0x39 },
/* 0x0B - '0'       */ { '0',      ')',      0x0B,      0x30 },
/* 0x0C - '-'       */ { '-',      '_',      0x0C,      0xBD },
/* 0x0D - '='       */ { '=',      '+',      0x0D,      0xBB },
/* 0x0E - BS        */ {  0,        0,       0x0E,      0x08 },
/* 0x0F - TAB       */ {  0,        0,       0x0F,      0x09 },
/* 0x10 - 'q'       */ { 'q',      'Q',      0x10,      0x51 },
/* 0x11 - 'w'       */ { 'w',      'W',      0x11,      0x57 },
/* 0x12 - 'e'       */ { 'e',      'E',      0x12,      0x45 },
/* 0x13 - 'r'       */ { 'r',      'R',      0x13,      0x52 },
/* 0x14 - 't'       */ { 't',      'T',      0x14,      0x54 },
/* 0x15 - 'y'       */ { 'y',      'Y',      0x15,      0x59 },
/* 0x16 - 'u'       */ { 'u',      'U',      0x16,      0x55 },
/* 0x17 - 'i'       */ { 'i',      'I',      0x17,      0x49 },
/* 0x18 - 'o'       */ { 'o',      'O',      0x18,      0x4F },
/* 0x19 - 'p'       */ { 'p',      'P',      0x19,      0x50 },
/* 0x1A - '['       */ { '[',      '{',      0x1A,      0xDB },
/* 0x1B - ']'       */ { ']',      '}',      0x1B,      0xDD },
/* 0x1C - CR/LF     */ {  0,        0,       0x1C,      0x0D },
/* 0x1D - l. Ctrl   */ {  0,        0,       0x1D,      0x11 },
/* 0x1E - 'a'       */ { 'a',      'A',      0x1E,      0x41 },
/* 0x1F - 's'       */ { 's',      'S',      0x1F,      0x53 },
/* 0x20 - 'd'       */ { 'd',      'D',      0x20,      0x44 },
/* 0x21 - 'f'       */ { 'f',      'F',      0x21,      0x46 },
/* 0x22 - 'g'       */ { 'g',      'G',      0x22,      0x47 },
/* 0x23 - 'h'       */ { 'h',      'H',      0x23,      0x48 },
/* 0x24 - 'j'       */ { 'j',      'J',      0x24,      0x4A },
/* 0x25 - 'k'       */ { 'k',      'K',      0x25,      0x4B },
/* 0x26 - 'l'       */ { 'l',      'L',      0x26,      0x4C },
/* 0x27 - ';'       */ { ';',      ':',      0x27,      0xBA },
/* 0x28 - '\''      */ { '\'',     '\"',     0x28,      0xDE },
/* 0x29 - '`'       */ { '`',      '~',      0x29,      0xC0 },
/* 0x2A - l. SHIFT  */ {  0,        0,       0x2A,      0x10 },
/* 0x2B - '\'       */ { '\\',     '|',      0x2B,      0xDC },
/* 0x2C - 'z'       */ { 'z',      'Z',      0x2C,      0x5A },
/* 0x2D - 'x'       */ { 'x',      'X',      0x2D,      0x58 },
/* 0x2E - 'c'       */ { 'c',      'C',      0x2E,      0x43 },
/* 0x2F - 'v'       */ { 'v',      'V',      0x2F,      0x56 },
/* 0x30 - 'b'       */ { 'b',      'B',      0x30,      0x42 },
/* 0x31 - 'n'       */ { 'n',      'N',      0x31,      0x4E },
/* 0x32 - 'm'       */ { 'm',      'M',      0x32,      0x4D },
/* 0x33 - ','       */ { ',',      '<',      0x33,      0xBC },
/* 0x34 - '.'       */ { '.',      '>',      0x34,      0xBE },
/* 0x35 - '/'       */ { '/',      '?',      0x35,      0xBF },
/* 0x36 - r. SHIFT  */ {  0,        0,       0x36,      0x10 },
/* 0x37 - '*'       */ { '*',      '*',      0x37,      0x6A },
/* 0x38 - ALT       */ {  0,        0,       0x38,      0x12 },
/* 0x39 - ' '       */ { ' ',      ' ',      0x39,      0x20 },
/* 0x3A - CapsLock  */ {  0,        0,       0x3A,      0x14 },
/* 0x3B - F1        */ {  0,        0,       0x3B,      0x70 },
/* 0x3C - F2        */ {  0,        0,       0x3C,      0x71 },
/* 0x3D - F3        */ {  0,        0,       0x3D,      0x72 },
/* 0x3E - F4        */ {  0,        0,       0x3E,      0x73 },
/* 0x3F - F5        */ {  0,        0,       0x3F,      0x74 },
/* 0x40 - F6        */ {  0,        0,       0x40,      0x75 },
/* 0x41 - F7        */ {  0,        0,       0x41,      0x76 },
/* 0x42 - F8        */ {  0,        0,       0x42,      0x77 },
/* 0x43 - F9        */ {  0,        0,       0x43,      0x78 },
/* 0x44 - F10       */ {  0,        0,       0x44,      0x79 },
/* 0x45 - NumLock   */ {  0,        0,       0x45,      0x90 },
/* 0x46 - ScrLock   */ {  0,        0,       0x46,      0x91 },
/* 0x47 - Home      */ {  0,        0,       0x47,      0x24 },
/* 0x48 - Up        */ {  0,        0,       0x48,      0x26 },
/* 0x49 - PgUp      */ {  0,        0,       0x49,      0x21 },
/* 0x4A - '-'       */ {  0,        0,       0x4A,      0x6D },
/* 0x4B - Left      */ {  0,        0,       0x4B,      0x25 },
/* 0x4C - MID       */ {  0,        0,       0x4C,      0x0C },
/* 0x4D - Right     */ {  0,        0,       0x4D,      0x27 },
/* 0x4E - '+'       */ {  0,        0,       0x4E,      0x6B },
/* 0x4F - End       */ {  0,        0,       0x4F,      0x23 },
/* 0x50 - Down      */ {  0,        0,       0x50,      0x28 },
/* 0x51 - PgDown    */ {  0,        0,       0x51,      0x22 },
/* 0x52 - Insert    */ {  0,        0,       0x52,      0x2D },
/* 0x53 - Del       */ {  0,        0,       0x53,      0x2E },
/* 0x54 - Enter     */ {  0,        0,       0x54,      0x0D },
/* 0x55 - ???       */ {  0,        0,        0,         0   },
/* 0x56 - ???       */ {  0,        0,        0,         0   },
/* 0x57 - F11       */ {  0,        0,       0x57,      0x7A },  
/* 0x58 - F12       */ {  0,        0,       0x58,      0x7B },
/* 0x59 - ???       */ {  0,        0,        0,         0   },
/* 0x5A - ???       */ {  0,        0,        0,         0   },
/* 0x5B - Left Win  */ {  0,        0,       0x5B,      0x5B },	
/* 0x5C - Right Win */ {  0,        0,       0x5C,      0x5C },
/* 0x5D - Apps      */ {  0,        0,       0x5D,      0x5D }
};

static uint IsShift(byte sc)
{
	return (sc == 0x2A) || (sc == 0x36);
}

static uint IsCapsLock(byte sc)
{
	return (sc == 0x3A);
}

static uint IsNumLock(byte sc)
{
	return (sc == 0x45);
}

static uint MakeCode(KeyCode* pkc, int shift, int capsLock, int numLock, int E0)
{
	uint ret = 0;
	
	PrintChar('\n');
	PrintChar(pkc->ascii1);
	PrintChar(' ');
	PrintIntDec(shift);
	PrintChar(' ');
	PrintIntDec(capsLock);
	PrintChar(' ');
	PrintIntDec(numLock);
	PrintChar(' ');
	PrintIntDec(E0);
	PrintChar('\n');
	
	return ret;
}

static uint KeyType(byte sc)
{
	uint ret = KeyPress;
	
	if(sc & 0x80)
	{
		ret = KeyRelease;
	}
	
	return ret;
}

static uint PauseHandler(byte sc)
{
	uint ret = 0;
	
	
	return ret;
}

static uint KeyHandler(byte sc)
{
	uint ret = 0;
	
	static uint cShift = 0;
	static uint cCapsLock = 0;
	static uint cNumLock = 0;
	static uint E0 = 0;
	
	if(sc == 0xE0)
	{
		E0 = 1;
		ret = 1;
	}
	else
	{
		uint pressed = KeyType(sc);
		KeyCode* pkc = NULL;
		
		if(!pressed)
		{
			sc -= 0x80;
		}
		
		pkc = (KeyCode*)AddrOff(gKeyMap, sc);
		
		if(ret = !!pkc->scode)
		{
			uint code = 0;
			
			if(IsShift(sc))
			{
				cShift = pressed;
			}
			else if(IsCapsLock(sc) && pressed)
			{
				cCapsLock = !cCapsLock;
			}
			else if(IsNumLock(sc) && pressed)
			{
				cNumLock = !cNumLock;
			}
			
			code = pressed | MakeCode(pkc, cShift, cCapsLock, cNumLock, E0);
			
			E0 = 0;
		}
	}
	
	return ret;
}

void PutScanCode(byte sc)
{
	if(PauseHandler(sc))
	{
		/* Pause Key */
	}
	else if(KeyHandler(sc))
	{
		/* Normal Key */
	}
	else
	{
		/* Uknown Key */
	}
}

uint FetchKeyCode()
{
	uint ret = 0;
	
	
	return ret;
}

ihandler.c

void KeyboardHandler()
{
	byte sc = ReadPort(0x60);
	
	PrintIntHex(sc);
	PrintString("  ");

	PutScanCode(sc);

	SendEOI(MASTER_EOI_PORT);
}

gKeyMap 是扫描码、虚拟键盘和 ASCII 之间的映射。

PutScanCode 函数用来处理扫描码。

KeyHandler 函数用来处理普通按键的情况。它需要记录 Shift、Caps Lock、Num Lock 这些特殊按键是否被按下,同时需要处理 E0拓展按键 的情况。

首先按下 a ,然后按下 CapsLock,然后按下 NumLock,最后按下 a。可以看出,相应的特殊按键都被记录下来了。 

问题

如何判断按键是否属于数字小键盘?数字小键盘上的按键有什么特殊之处?

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值