PS/2 键盘与单片机接口
用LCD1602显示
调试成功所以拿出来给大家分享,希望对大家有用,呵呵^_^
用PS/2键盘做系统输入部分蛮方便的哦!
可以使用Backspace/Esc/Tab/Caps Lock/Shift/Enter/Space/Arrow等按键
这是键盘通码:
/*--------------------------------------------------------------*/
//File: 鼠标液晶测试
//Date: 2009-4-19
//Time: 16:30
/*--------------------------------------------------------------*/
#include <reg52.h>
#include "PS_keyboard.H"
#include "LCD1602_8A.H"
/*--------------------------------------------------------------*/
//延时50ms 函数定义
void delay50ms(void)
{
unsigned char i, j;
for(i = 165; i > 0; i--)
for(j = 150; j > 0; j--);
}
/*--------------------------------------------------------------*/
//主函数
void main(void)
{
unsigned char x, y;
LCD_init(); //LCD1602初始化
keyboard_init(); //键盘初始化
while(1)
{
if(r_ok == 2)
{
if(keyboard_data == 0x29) LCD_printc(x++, y, ' '); //空格
else if(keyboard_data == 0x66) {LCD_printc(x = (--x & 0x0f), y, ' '); LCD_pos(x, y);}//退格
else if(keyboard_data == 0x0d) LCD_pos(x+=4, y); //制表
else if(keyboard_data == 0x5a) LCD_pos(x = 0, y = (++y & 0x01));//回车
else if(keyboard_data == 0x58) shift_flag = ~ shift_flag; //大小写切换
else if(keyboard_data == 0x76) {LCD_clr();LCD_pos(x=0, y="0");} //清屏,光标复位
else if(keyboard_data == 0x6b) LCD_pos(x = (--x & 0x0f), y); //光标左移
else if(keyboard_data == 0x74) LCD_pos(x = (++x & 0x0f), y); //光标右移
else if(keyboard_data == 0x75) LCD_pos(x, y = (--y & 0x01)); //光标上移
else if(keyboard_data == 0x72) LCD_pos(x, y = (++y & 0x01)); //光标下移
else //字符输出
{
look_ascii(); //查表
LCD_printc(x & 0x0f, y & 0x01, keyboard_ascii);
if(y > 1) {y = 0; LCD_clr(); x--;} //清屏
x++; if(x > 15) {x = 0; y++;} //换行
}
r_ok = 0; //清接收标志位
EX0 = 1; //继续检测按键
}
delay50ms();
}
}
/*--------------------------------------------------------------*/
//ASCII
unsigned char code KB_ASCII[48][3] = {
//unshifted, shifted, scan_code
'`', '~', 0x0E,
'1', '!', 0x16,
'2', '@', 0x1E,
'3', '#', 0x26,
'4', '$', 0x25,
'5', '%', 0x2E,
'6', '^', 0x36,
'7', '&', 0x3D,
'8', '*', 0x3E,
'9', '(', 0x46,
'0', ')', 0x45,
'-', '_', 0x4E,
'=', '+', 0x55,
'q', 'Q', 0x15,
'w', 'W', 0x1D,
'e', 'E', 0x24,
'r', 'R', 0x2D,
't', 'T', 0x2C,
'y', 'Y', 0x35,
'u', 'U', 0x3C,
'i', 'I', 0x43,
'o', 'O', 0x44,
'p', 'P', 0x4D,
'[', '{', 0x54,
']', '}', 0x5B,
'\\', '|',0x5D,
'a', 'A', 0x1C,
's', 'S', 0x1B,
'd', 'D', 0x23,
'f', 'F', 0x2B,
'g', 'G', 0x34,
'h', 'H', 0x33,
'j', 'J', 0x3B,
'k', 'K', 0x42,
'l', 'L', 0x4B,
';', ':', 0x4C,
'\'', '"',0x52,
'z', 'Z', 0x1A,
'x', 'X', 0x22,
'c', 'C', 0x21,
'v', 'V', 0x2A,
'b', 'B', 0x32,
'n', 'N', 0x31,
'm', 'M', 0x3A,
',', '<', 0x41,
'.', '>', 0x49,
'/', '?', 0x4A
};
/*--------------------------------------------------------------*/
//File: PS/2-keyboard头文件
//Date: 2009-4-18
//Time: 21:29
/*--------------------------------------------------------------*/
//防止被重复定义引用
#ifndef __PS_keyboard_H__
#define __PS_keyboard_H__
//包含头文件
#include "LCD_ASCII.H" //键盘通码表
/*--------------------------------------------------------------*/
sbit keyboard_sda = P1^6; //鼠标数据线
sbit keyboard_clk = P3^2; //鼠标时钟线
sbit led = P0^0; //按键LED指示
sbit beep = P0^1; //蜂鸣器指示
/*--------------------------------------------------------------*/
//数据定义
unsigned char n; //循环变量
unsigned int keyboard_word; //接收字16bits
unsigned char keyboard_data; //接收字节
unsigned char keyboard_ascii; //查表得到的字符
bit shift_flag; //shift标志位
unsigned char r_ok; //接收数据有效
/*--------------------------------------------------------------*/
//函数声明
void INT0_init(void); //外部中断INT0初始化
//void delay120us(void); //延时120us 函数定义
//void keyboard_write_dat(unsigned char dat); //发送数据
void keyboard_read_dat(void); //读出数据
void keyboard_init(void); //键盘初始化
void look_ascii(void); //查表字符
/*--------------------------------------------------------------*/
//外部中断INT0初始化
void INT0_init(void)
{
EA = 1; //总中断
EX0 = 1; //外部中断
PX0 = 1; //中断优先级
IT0 = 0; //低电平触发
}
/*--------------------------------------------------------------*/
//延时120us 函数定义
/*void delay120us(void)
{
unsigned char i, j;
for(i = 23; i > 0; i--)
for(j = 1; j > 0; j--);
}
/*--------------------------------------------------------------*/
//奇校验
bit check_parity(void)
{
ACC = keyboard_data;
if(~P == (bit)(keyboard_word & 0x0200)) return 1; //奇校验成功则返回1
else return 0; //奇校验失败则返回0
}
/*--------------------------------------------------------------*/
//读出字节数据
void keyboard_read_dat(void)
{
keyboard_data = (unsigned char)(keyboard_word >> 1);//去掉最高两位和最后一位
if(check_parity()) keyboard_word = 0; //奇校验成功//清接收数据字
else keyboard_data = 0; //置零
if(keyboard_data == 0xe0 | keyboard_data == 0xf0){;}//忽略0xe0和0xf0字节
else
if(keyboard_data == 0x12 | keyboard_data == 0x59) shift_flag = ~shift_flag;//shift按键检测
else {r_ok++; if(r_ok == 2) EX0 = 0;} //忽略通码,取断码,接收有效,断开中断,按键处理
}
/*--------------------------------------------------------------*/
//查表字符
void look_ascii(void)
{
unsigned char i;
for(i = 0; i < 48; i++)
{
if(KB_ASCII[2] == keyboard_data) //查找按键通码
{
keyboard_ascii = KB_ASCII[shift_flag]; //得到相应字符
}
}
}
/*--------------------------------------------------------------*/
//外部中断INT0服务
//接收11位数据:1START-8DATA-1PARITY-1STOP
void INT0_intservice(void) interrupt 0
{
keyboard_word >>= 1; //先向右空移一位
if(keyboard_sda) keyboard_word |= 0x0400; //先接收最低位
n++; if(n == 11) {keyboard_read_dat(); n = 0;} //接收完成则读出数据
}
/*--------------------------------------------------------------*/
//键盘初始化
void keyboard_init(void)
{
INT0_init(); //外部中断INT0初始化
}
/*--------------------------------------------------------------*/
#endif
/*--------------------------------------------------------------*/
//File: LCD1602_8A.H
//Date: 08-8-9 //08-8-8 //08-8-27 //08-8-26
//Time: 20:10
//Modi: 08-8-10 9:51
//Note: LCD1602 The Best Driver for you!
// Welcome to use. Have a good day!
/*--------------------------------------------------------------*/
//防止被重复定义
#ifndef __LCD1602_8A_H__
#define __LCD1602_8A_H__
//所需头文件
#include <intrins.h>
/*--------------------------------------------------------------*/
//LCD1602与单片机接口定义
sfr LCD_IO = 0xa0; //P0-0x80,P1-0x90,P2-0xA0,P3-0xB0;
sbit LCD_RS = P1^0; //LCD数据/命令选择端(H/L)
sbit LCD_RW = P1^1; //LCD 读/写 选择端(H/L)
sbit LCD_EN = P1^2; //LCD使能控制端
sbit LCD_BZ = LCD_IO^7; //LCD忙标志位
/*--------------------------------------------------------------*/
//函数声明
void LCD_busy (void); //检测LCD是否忙
void LCD_init (void); //LCD初始化
void LCD_clr (void); //LCD清屏
void LCD_cmd (unsigned char cmd); //写入指令
void LCD_dat (unsigned char dat); //写入数据
void LCD_pos (unsigned char x, unsigned char y); //显示定位
void LCD_printc(unsigned char x, unsigned char y, unsigned char c); //定位输出字符
//void LCD_prints(unsigned char x, unsigned char y, unsigned char *s); //定位输出字符串
//void LCD_printn(unsigned char x, unsigned char y, unsigned int num); //定位输出16位二进制数字
/*--------------------------------------------------------------*/
//检测LCD忙状态
void LCD_busy(void)
{
do
{
LCD_EN = 0;
LCD_RS = 0; //指令
LCD_RW = 1; //读出
LCD_IO = 0xff; //除P0口外,其它口不需要此句!!!
LCD_EN = 1;
_nop_(); //高电平读出 延迟时间1us
}while(LCD_BZ); //LCD_BZ=1表示忙,LCD_BZ=0表示空闲
LCD_EN = 0;
}
/*--------------------------------------------------------------*/
//写入指令
void LCD_cmd(unsigned char cmd)
{
LCD_busy(); //检测忙
LCD_RS = 0; //指令
LCD_RW = 0; //写入
LCD_EN = 1;
LCD_IO = cmd; //传指令
LCD_EN = 0; //下降沿有效
}
/*--------------------------------------------------------------*/
//写入数据
void LCD_dat(unsigned char dat)
{
LCD_busy(); //检测忙
LCD_RS = 1; //数据
LCD_RW = 0; //写入
LCD_EN = 1;
LCD_IO = dat; //传数据
LCD_EN = 0; //下降沿有效
}
/*--------------------------------------------------------------*/
//显示定位
void LCD_pos(unsigned char x, unsigned char y)
{
if(y) LCD_cmd(x|0xc0);//y=1第二行显示,y=0第一行显示 0<=x<16
else LCD_cmd(x|0x80);//数据指针=80+地址码(00H~27H,40H~67H)
}
/*--------------------------------------------------------------*/
//LCD清屏
void LCD_clr(void)
{
LCD_cmd(0x01);
}
/*--------------------------------------------------------------*/
//定位输出字符
void LCD_printc(unsigned char x, unsigned char y, unsigned char c)
{
LCD_pos(x, y);
LCD_dat(c);
}
/*--------------------------------------------------------------*/
//定位输出字符串
/*void LCD_prints(unsigned char x, unsigned char y, unsigned char *s)
{
LCD_pos(x, y);
while(*s)
{
LCD_dat(*s);
s++;
}
}
/*--------------------------------------------------------------*/
//定位输出16位二进制数字
// 0<= num <65536
/*void LCD_printn(unsigned char x, unsigned char y, unsigned int num)
{
char i;
unsigned char ii;
unsigned char dat[6];
for(i = 0; i < 6; i++) dat = 0; i = 0; //初始化数据
while(num / 10) //拆位
{
dat = num % 10; //最低位
num /= 10; i++;
}
dat = num; //最高位
ii = i; //保存dat的位数
for(; i >= 0; i--) dat += 48; //转化成ASCII
LCD_prints(x, y, " "); //清显示区域
LCD_pos(x, y);
for(i = ii; i >= 0; i--) LCD_dat(dat); //输出数字字符
}
/*--------------------------------------------------------------*/
//LCD初始化
void LCD_init(void)
{
LCD_cmd(0x38); //设置LCD为16X2显示,5X7点阵,八位数据接口
LCD_cmd(0x06); //LCD显示光标移动设置(光标地址指针加1,整屏显示不移动)
LCD_cmd(0x0f); //LCD开显示及光标设置(光标闪烁,显示"_")
LCD_cmd(0x01); //清屏
}
/*--------------------------------------------------------------*/
#endif
以下我整理的按键代码,希望对大家有用^_^
/*--------------------------------------------------------------*/
//ASCII unshifted
unsigned char code unshifted[][2] = {
'`', 0x0E,
'1', 0x16,
'2', 0x1E,
'3', 0x26,
'4', 0x25,
'5', 0x2E,
'6', 0x36,
'7', 0x3D,
'8', 0x3E,
'9', 0x46,
'0', 0x45,
'-', 0x4E,
'=', 0x55,
'q', 0x15,
'w', 0x1D,
'e', 0x24,
'r', 0x2D,
't', 0x2C,
'y', 0x35,
'u', 0x3C,
'i', 0x43,
'o', 0x44,
'p', 0x4D,
'[', 0x54,
']', 0x5B,
'\', 0x5D,
'a', 0x1C,
's', 0x1B,
'd', 0x23,
'f', 0x2B,
'g', 0x34,
'h', 0x33,
'j', 0x3B,
'k', 0x42,
'l', 0x4B,
';', 0x4C,
''', 0x52,
'z', 0x1A,
'x', 0x22,
'c', 0x21,
'v', 0x2A,
'b', 0x32,
'n', 0x31,
'm', 0x3A,
',', 0x41,
'.', 0x49,
'/', 0x4A
}
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
//ASCII shifted
unsigned char code shifted[][2] = {
'~', 0x0E,
'!', 0x16,
'@', 0x1E,
'#', 0x26,
'$', 0x25,
'%', 0x2E,
'^', 0x36,
'&', 0x3D,
'*', 0x3E,
'(', 0x46,
')', 0x45,
'_', 0x4E,
'+', 0x55,
'Q', 0x15,
'W', 0x1D,
'E', 0x24,
'R', 0x2D,
'T', 0x2C,
'Y', 0x35,
'U', 0x3C,
'I', 0x43,
'O', 0x44,
'P', 0x4D,
'{', 0x54,
'}', 0x5B,
'|', 0x5D,
'A', 0x1C,
'S', 0x1B,
'D', 0x23,
'F', 0x2B,
'G', 0x34,
'H', 0x33,
'J', 0x3B,
'K', 0x42,
'L', 0x4B,
':', 0x4C,
'"', 0x52,
'Z', 0x1A,
'X', 0x22,
'C', 0x21,
'V', 0x2A,
'B', 0x32,
'N', 0x31,
'M', 0x3A,
'<', 0x41,
'>', 0x49,
'?', 0x4A
}
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
//ASCII
unsigned char code KB_ASCII[][3] = {
'`', '~', 0x0E,
'1', '!', 0x16,
'2', '@', 0x1E,
'3', '#', 0x26,
'4', '$', 0x25,
'5', '%', 0x2E,
'6', '^', 0x36,
'7', '&', 0x3D,
'8', '*', 0x3E,
'9', '(', 0x46,
'0', ')', 0x45,
'-', '_', 0x4E,
'=', '+', 0x55,
'q', 'Q', 0x15,
'w', 'W', 0x1D,
'e', 'E', 0x24,
'r', 'R', 0x2D,
't', 'T', 0x2C,
'y', 'Y', 0x35,
'u', 'U', 0x3C,
'i', 'I', 0x43,
'o', 'O', 0x44,
'p', 'P', 0x4D,
'[', '{', 0x54,
']', '}', 0x5B,
'\', '|', 0x5D,
'a', 'A', 0x1C,
's', 'S', 0x1B,
'd', 'D', 0x23,
'f', 'F', 0x2B,
'g', 'G', 0x34,
'h', 'H', 0x33,
'j', 'J', 0x3B,
'k', 'K', 0x42,
'l', 'L', 0x4B,
';', ':', 0x4C,
''', '"', 0x52,
'z', 'Z', 0x1A,
'x', 'X', 0x22,
'c', 'C', 0x21,
'v', 'V', 0x2A,
'b', 'B', 0x32,
'n', 'N', 0x31,
'm', 'M', 0x3A,
',', '<', 0x41,
'.', '>', 0x49,
'/', '?', 0x4A
}
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
//Fuction Key Funx
#define Fun1 0x05
#define Fun2 0x06
#define Fun3 0x04
#define Fun4 0x0C
#define Fun5 0x03
#define Fun6 0x0B
#define Fun7 0x83
#define Fun8 0x0A
#define Fun9 0x01
#define Fun10 0x09
#define Fun11 0x78
#define Fun12 0x07
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
//Small KeyBoard
KP_0,70
KP_1,69
KP_2,72
KP_3,7A
KP_4,6B
KP_5,73
KP_6,74
KP_7,6C
KP_8,75
KP_9,7D
KP_NUM,77
KP_/,4A
KP_*,7C
KP_-,7B
KP_+,79
KP_EN,5A
KP_.,71
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
//Left Control Key
#define ESC 0x76
#define TAB 0x0D
#define CAPS 0x58
#define L_SHFT 0x12
#define L_CTRL 0x14
#define L_GUI 0x1F
#define L_ALT 0x11
#define SPACE 0x29
#define R_ALT 0x11
#define R_GUI 0x27
#define R_CTRL 0x14
#define R_SHFT 0x59
#define ENTER 0x5A
#define BKSP 0x66
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
//Middle Control Key
#define INSERT 0x70
#define HOME 0x6C
#define PG_UP 0x7D
#define DELETE 0x71
#define END 0x69
#define PG_DN 0x7A
#define SCROLL 0x7E
#define U_ARROW 0x75
#define D_ARROW 0x72
#define L_ARROW 0x6B
#define R_ARROW 0x74
/*--------------------------------------------------------------*/
用户518079 2009-4-19 18:31