[共享]PS2键盘通用支持库(v0.9beta)
RD_KeyBoard_PS2.c------------------------------------------------------------------
/***********************************************************
* 函数库说明:PS/2键盘底层硬件驱动函数库 *
* 版本: v0.90beta *
* 作者: 王卓然 *
* 创建日期:2008年1月17日 *
* -------------------------------------------------------- *
*[支 持 库] *
* 支持库名称: *
* 需要版本: *
* 支持库名称: *
* -------------------------------------------------------- *
*[版本更新] *
* 修改: *
* 修改日期: *
* 版本: *
* -------------------------------------------------------- *
*[版本历史] *
* -------------------------------------------------------- *
*[使用说明] *
***********************************************************/
/********************
* 头 文 件 配 置 区 *
********************/
# include "RD_MacroAndConst.h"
# include "LIB_Config.h"
# include "RD_UseKeyBoard_PS2.h"
/********************
* 系 统 宏 定 义*
********************/
/*------------------*
* 常 数 宏 定 义*
*------------------*/
/*------------------*
* 动 作 宏 定 义*
*------------------*/
/********************
*用户变量类型定义 *
********************/
/********************
* 结构体定义区 *
********************/
/********************
* 模块函数声明区*
********************/
/********************
* 全局函数声明区*
********************/
BOOL PROC_Key_Board_PS2_Scan(void);
uint8 Scan_Key_Board_PS2(void);
UINT8 Key_Board_PS2_GetLastMakeKey(void);
UINT8 Key_Board_PS2_GetLastBreakKey(void);
/********************
* 模块变量声明区*
********************/
static uint8 s_cPS2KeyNum = KEY_NULL;
static uint8 s_cPS2LastBreakKey = KEY_NULL;
static uint8 s_cPS2LastMakeKey = KEY_NULL;
/********************
* 全局变量声明区*
********************/
uint8 g_cPS2GetData = 0;
uint8 g_cPS2ReceiveCount = 0;
BOOLg_cPS2IfGetNewData = FALSE;
/********************
* 自定义变量声明*
********************/
START_DEFINE_QUEUE(PS2KeyBuffer,8,uint8,uint8)
END_DEFINE_QUEUE
/***********************************************************
* 函数说明:按键扫描码返回函数 *
* 输入: 无 *
* 输出: 无 *
* 调用函数:无 *
***********************************************************/
uint8 Scan_Key_Board_PS2(void)
{
return s_cPS2KeyNum;
}
/***********************************************************
* 函数说明:最后一个通码函数 *
* 输入: 无 *
* 输出: 最后一个通码 *
* 调用函数:无 *
* -------------------------------------------------------- *
* [ 说 明 ] 当读取通码以后,会自动复位为KEY_NULL *
***********************************************************/
UINT8 Key_Board_PS2_GetLastMakeKey(void)
{
UINT8 chTempLastMakeKey = s_cPS2LastMakeKey;
s_cPS2LastMakeKey = KEY_NULL;
return chTempLastMakeKey;
}
/***********************************************************
* 函数说明:最后一个断码 *
* 输入: 无 *
* 输出: 最后一个断码 *
* 调用函数:无 *
* -------------------------------------------------------- *
* [ 说 明 ] 当读取断码以后,会自动复位为KEY_NULL *
***********************************************************/
UINT8 Key_Board_PS2_GetLastBreakKey(void)
{
UINT8 chTempLastBreakKey = s_cPS2LastBreakKey;
s_cPS2LastBreakKey = KEY_NULL;
return chTempLastBreakKey;
}
/***********************************************************
* 函数说明:PS2键盘扫描处理函数 *
* 输入: 无 *
* 输出: 无 *
* 调用函数:无 *
***********************************************************/
BOOL PROC_Key_Board_PS2_Scan(void)
{
static BOOL s_bIfKeyUp = TRUE;
uint8 cQueueCount = 0;
uint8 cTempData = 0;
cQueueCount = __GET_QUEUE_COUNT;
if (__PEEK_DATA(cTempData))
{
//如果缓冲区不为空
if (cTempData == 0xE0)
{
if (cQueueCount > 1)
{
__GET_DATA(cTempData);
__PEEK_DATA(cTempData);
if (cTempData == 0xF0)
{
if (cQueueCount > 2)
{
//取到了断开码
__GET_DATA(cTempData);
__GET_DATA(s_cPS2LastBreakKey);
s_cPS2KeyNum = KEY_NULL;
}
}
else
{
//取到了通码
__GET_DATA(s_cPS2KeyNum);
s_cPS2LastMakeKey = s_cPS2KeyNum;
}
}
}
else
{
if (cTempData == 0xF0)
{
if (cQueueCount > 1)
{
__GET_DATA(cTempData);
__GET_DATA(s_cPS2LastBreakKey);
s_cPS2KeyNum = KEY_NULL;
}
}
else
{
//取到了通码
__GET_DATA(s_cPS2KeyNum);
s_cPS2LastMakeKey = s_cPS2KeyNum;
}
}
}
return TRUE;
} RD_KeyBoard_PS2.h
----------------------------------------------------------------------
#ifndef _USE_KEY_BOARD_PS2_H_
#define _USE_KEY_BOARD_PS2_H_
/***********************************************************
* 声明库说明:PS/2键盘底层硬件驱动函数声明库 *
* 版本: v0.90beta *
* 作者: 王卓然 *
* 创建日期:2008年1月17日 *
* -------------------------------------------------------- *
*[支 持 库] *
* 支持库名称: *
* 需要版本: *
* 支持库名称: *
* -------------------------------------------------------- *
*[版本更新] *
* 修改: *
* 修改日期: *
* 版本: *
* -------------------------------------------------------- *
*[版本历史] *
* -------------------------------------------------------- *
*[使用说明] *
***********************************************************/
/********************
* 头 文 件 配 置 区 *
********************/
/********************
* 系 统 宏 定 义*
********************/
/*------------------*
* 常 数 宏 定 义*
*------------------*/
#ifndef KEY_NULL
# define KEY_NULL 0xff
#endif
/*------------------*
* 动 作 宏 定 义*
*------------------*/
#ifndef KEY_BOARD_PS2_RECEIVE
# define KEY_BOARD_PS2_RECEIVE(n)
#endif
# define __PUT_DATA(n) ADD_QUEUE_DATA(PS2KeyBuffer,(n))
# define __GET_DATA(n) GET_QUEUE_DATA(PS2KeyBuffer,&(n))
# define __GET_QUEUE_COUNT GET_QUEUE_COUNT(PS2KeyBuffer)
# define __PEEK_DATA(n) PEEK_QUEUE_DATA(PS2KeyBuffer,&(n))
# define PS2_GET_LAST_MAKE_KEY Key_Board_PS2_GetLastMakeKey()
# define PS2_GET_LAST_BREAK_KEY Key_Board_PS2_GetLastBreakKey()
# define KEY_BOARD_PS2_INSERT_INT_ISR_CODE \
{\
static uint8 s_cTempData = 0;\
static uint8 s_cParity = 0;\
g_cPS2ReceiveCount++;\
if (g_cPS2ReceiveCount == 1)\
{\
if (KEY_BOARD_PS2_DATA == HIGH)\
{\
s_cTempData = 0;\
s_cParity = 0;\
g_cPS2ReceiveCount = 0;\
}\
}\
else if (g_cPS2ReceiveCount == 10)\
{\
if (KEY_BOARD_PS2_DATA ^ (s_cParity & 0x01))\
{\
g_cPS2IfGetNewData = TRUE;\
g_cPS2GetData = s_cTempData;\
__PUT_DATA(g_cPS2GetData);\
KEY_BOARD_PS2_RECEIVE(g_cPS2GetData);\
}\
}\
else if (g_cPS2ReceiveCount == 11)\
{\
g_cPS2ReceiveCount = 0;\
s_cParity = 0;\
}\
else\
{\
if (KEY_BOARD_PS2_DATA)\
{\
s_cTempData |= BIT(g_cPS2ReceiveCount-2);\
s_cParity += 1;\
}\
else\
{\
s_cTempData &= ~BIT(g_cPS2ReceiveCount-2);\
}\
}\
}
/********************
*用户变量类型定义 *
********************/
/********************
* 结构体定义区 *
********************/
/********************
* 函 数 引 用 区*
********************/
extern BOOL PROC_Key_Board_PS2_Scan(void);
extern uint8 Scan_Key_Board_PS2(void);
extern UINT8 Key_Board_PS2_GetLastMakeKey(void);
extern UINT8 Key_Board_PS2_GetLastBreakKey(void);
/********************
* 全局变量引用区*
********************/
extern uint8 g_cPS2GetData;
extern uint8 g_cPS2ReceiveCount;
extern BOOLg_cPS2IfGetNewData;
/********************
*自定义变量引用区 *
********************/
EXTERN_REFERENCE_QUEUE(PS2KeyBuffer,uint8,uint8)
#endif 使用说明:
1、该头文件还处在更新中,已经可以从PS2键盘中提取所需的键盘扫描码,并能单独存储最后一次的通码和断码。
2、该头文件提供一个Scan_Key_Board_PS2()函数,该函数将PS2键盘的输出模拟成普通的 n*m 键盘扫描的输出模式,即当有键按下时,通过该函数将获得对应的键盘扫描码,当没有键按下时,将获得一个KEY_NULL的返回。
3、该头文件需要的硬件支持为:
一个下降沿触发的外中断,并将.h中的宏KEY_BOARD_PS2_INSERT_INT_ISR_CODE粘贴到中断处理程序中。该外中断接PS2的CLK线。
一个普通端口,接PS2的Data线。
4、将PROC_Key_Board_PS2_Scan()放到定时器的毫秒中断处理程序中,或者放到主程序的超级循环中(但必须保证该程序在超级循环中具有一定的实时性)。
所有针对该头文件的配置都必须放在一个名叫LIB_Config.h的头文件中,一个典型的配置如下:
硬件ATMega16
//PS/2键盘模块
# define KEY_BOARD_PS2_DATA PIN_PD2
# include "RD_TPL_QUEUE.h"
# include "RD_KeyBoard_PS2.h"
大家注意到,宏KEY_BOARD_PS2_DATA实际上被绑定在了PIN_PD2上。
下面的代码你可以看作是伪代码,他实际上描述了该头文件的一个典型使用方法。
void main(void)
{
System_INIT(); //代码初始化
//DISP_BOARD_SET_FLASH_POS(BIT(1));
//DISP_BOARD_SET_ICON(0x0F);
CLS
//Locate(1,1);
//PrintD(123);
//Locate(1,1);
//PrintN(0x1234,4);
while(TRUE) //超级循环
{
UINT8 chLastBreakKey = KEY_NULL;
UINT8 chLastMakeKey = KEY_NULL;
Locate(1,1);
PrintN(Scan_Key_Board_PS2(),2);
chLastBreakKey = PS2_GET_LAST_BREAK_KEY;
if (chLastBreakKey != KEY_NULL)
{
LOCATE(5,1);
PrintN(chLastBreakKey,2);
}
chLastMakeKey = PS2_GET_LAST_MAKE_KEY;
if (chLastMakeKey != KEY_NULL)
{
LOCATE(3,1);
PrintN(chLastMakeKey,2);
}
PROC_Key_Board_PS2_Scan();
}
}
实例工程:点击此处下载ourdev_208916.rar(文件大小:195K)
如果你想直接使用该示例工程,需要在ICCV7的环境下进行工程编译。
硬件上,关于显示,需要两个端口来实现一个8位的排显示。相关的头文件是RD_UseDISPBoard.h。对应的配置也在LIB_Config.h中。例如:
//显示模块
# define DISP_BOARD_START_POS 2
# define _USE_DISP_BOARD_FOR_SPECIAL_POS
# define DISP_BOARD_POSITION PORTA
# define DISP_BOARD_DATA PORTB
# define SYS_TIMER_MS_ADD_UNTILL_OVF g_wSystemTimer
# include "RD_UseDISPBoard.h"
因为我使用的实际上6位排显,所以调整了显示的起始位置:# define DISP_BOARD_START_POS 2
对于扫描位选,硬件决定了,给高电平,对应数码管被选中,这和头文件的默认模式是不同的,所以我要通过宏来设定:# define _USE_DISP_BOARD_FOR_SPECIAL_POS
# define DISP_BOARD_POSITION PORTA 定义了位选端口
# define DISP_BOARD_DATA PORTB 定义了断码端口
# define SYS_TIMER_MS_ADD_UNTILL_OVF g_wSystemTimer 定义了一个用于特效显示用的计数器,该计数器以毫秒为单位单向增加 好贴! 非常好贴。
谢谢分享。 支持 支持,楼主写程序习惯很好啊,俺都是些好了再加注释(有时候就懒得加了)。 支持 顶!!!!!!!!!!!!! 好贴! 好贴!
编程习惯也很好啊 很好,谢谢! 长见识了,谢谢楼主! 做记号 请问硬件怎么搭,才能用上PS2键盘呢? 2楼有较为详细的说明。 恩,好贴呀 好東東~~ ;)又出精品了 不错! 有没PS2鼠标的? 好! 好东西,顶! mark 好东西谢谢 好东西,顶! 收藏了 收藏! 不错··· MARK MARK mark! 不错,支持下。 mark支持 记号,谢谢吖~~~~ dddddddddddd 还没看,有空研究一下 顶一下 mark mark mark Mark mark ,PS2,改天再看 dddddddddddddd ps2 最近在DIY的IO口不够 矩阵键盘更改未ps2 mark mark mark 收藏! mark!!!! mark mark mark mark Mark 好东西。。。 恩,好贴呀 好贴 mark mark mark 谢谢共享 不错的代码,没细看,但是这结构,移植性应该很好! MARK!!!!!!!!!!!!! 我去。。。太谢谢了,
早知道我那PS2的免驱设备就好做了。。
学习。 好东西,顶一个
页:
[1]