原创 PS/2 键盘与单片机

2009-10-10 14:46 4174 6 7 分类: MCU/ 嵌入式

rar程序打包


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
/*--------------------------------------------------------------*/


 


 


 


 


 



 

文章评论1条评论)

登录后参与讨论

klyzh2003_363865542 2009-4-19 18:31

好,学习了!
相关推荐阅读
Alexi2008 2010-05-22 22:40
LCD简单菜单显示
LCD简单菜单显示显示器件为图形型LCD12864(主控芯片KS0108)什么都不带!包含以下文件:LCD菜单(测试)LCD菜单(简单)LCD菜单(界面)LCD菜单(遥控器)希望对大家有用^_^感兴趣...
Alexi2008 2010-05-22 14:33
LCD12864(KS0108)液晶演示程序
LCD12864(KS0108)液晶演示程序LCD12864(KS0108)液晶演示程序视频: LCD12864演示程序(什么都不带的液晶) 视频演示网址:http://v.youku.com/v_s...
Alexi2008 2009-10-22 18:27
AVR代码
AVR单片机程序代码集,给需要的朋友们参考呵呵,都是自己一边学一边写的,一个一个字符从键盘敲出来的^_^希望对大家有用:-)呵呵,编译软件为:  ICCAVR V6.31A版本一共七个压缩包,呵呵,分...
Alexi2008 2009-10-22 15:18
VGA相关资料
VGA相关资料呵呵^_^如果你想玩的就请下载,有很多东西,都是花了我好几个夜晚才搜到的都是网上的资料:-)有兴趣的可以做做哦 包含以下文件夹:├─VGA+2051│  │  共享-----国外优秀电子...
Alexi2008 2009-08-17 19:54
AVR端口操作宏定义,便于移植
AVR端口操作宏定义头文件(ICCAVRIO.H),便于移植(ICCAVR编译环境) 压缩包里面有网上的相关资料,把它看完,相信你会更加了解红宏定义的^_^还有头文件在ICCAVRIO.H在Inclu...
我要评论
1
6
1
2
3
4
5
6
7
8
9
0
关闭 热点推荐上一条 /2 下一条