#include <reg52.H>
#include <intrins.H>
#define uchar unsigned char
#define uint unsigned int
#define LCD_DATA P2 //数据口
sbit RS = P1^5; //并行的指令/数据选择信号, H数据, L命令
sbit RW = P1^7; //并行读写选择信号, H读, L写
sbit E = P1^6; //并行使能端, H有效, L无效
sbit PSB = P1^1; //并/串接口选择, H并,L串
sbit RET = P1^4; //复位, L有效
sbit DATA=P0^2;
uchar count,ASCII=65,Data;
uchar code datas1[] = {"PS2 键盘检测实验"};
uchar code datas2[] = {"检测的按键为"};
uchar code datas3[] = {"按键检测正确"};
uchar code datas4[] = {"检测有误 "};
void trains(uchar Code);
uchar code unshifted[][2]= //shift键没按下译码表
{
0x0e,'`',
0x15,'q',
0x16,'1',
0x1a,'z',
0x1b,'s',
0x1c,'a',
0x1d,'w',
0x1e,'2',
0x21,'c',
0x22,'x',
0x23,'d',
0x24,'e',
0x25,'4',
0x26,'3',
0x29,' ',
0x2a,'v',
0x2b,'f',
0x2c,'t',
0x2d,'r',
0x2e,'5',
0x31,'n',
0x32,'b',
0x33,'h',
0x34,'g',
0x35,'y',
0x36,'6',
0x39,',',
0x3a,'m',
0x3b,'j',
0x3c,'u',
0x3d,'7',
0x3e,'8',
0x41,',',
0x42,'k',
0x43,'i',
0x44,'o',
0x45,'0',
0x46,'9',
0x49,'.',
0x4a,'/',
0x4b,'l',
0x4c,';',
0x4d,'p',
0x4e,'-',
0x52,'\'',
0x54,'[',
0x55,'=',
0x5b,']',
0x5d,'\\',
0x61,'<',
0x69,'1',
0x6b,'4',
0x6c,'7',
0x70,'0',
0x71,'.',
0x72,'2',
0x73,'5',
0x74,'6',
0x75,'8',
0x79,'+',
0x7a,'3',
0x7b,'-',
0x7c,'*',
0x7d,'9',
0,0
};
uchar code shifted[][2]= //shift键按下译码表
{
0x0e,'~',
0x15,'Q',
0x16,'!',
0x1a,'Z',
0x1b,'S',
0x1c,'A',
0x1d,'W',
0x1e,'@',
0x21,'C',
0x22,'X',
0x23,'D',
0x24,'E',
0x25,'$',
0x26,'#',
0x29,' ',
0x2a,'V',
0x2b,'F',
0x2c,'T',
0x2d,'R',
0x2e,'%',
0x31,'N',
0x32,'B',
0x33,'H',
0x34,'G',
0x35,'Y',
0x36,'^',
0x39,'L',
0x3a,'M',
0x3b,'J',
0x3c,'U',
0x3d,'&',
0x3e,'*',
0x41,'<',
0x42,'K',
0x43,'I',
0x44,'O',
0x45,')',
0x46,'(',
0x49,'>',
0x4a,'?',
0x4b,'L',
0x4c,':',
0x4d,'P',
0x4e,'_',
0x52,'"',
0x54,'{',
0x55,'+',
0x5b,'}',
0x5d,'|',
0x61,'>',
0x69,'1',
0x6b,'4',
0x6c,'7',
0x70,'0',
0x71,'.',
0x72,'2',
0x73,'5',
0x74,'6',
0x75,'8',
0x79,'+',
0x7a,'3',
0x7b,'-',
0x7c,'*',
0x7d,'9',
0,0
};
//延时约2us
void delayUs()
{
_nop_();_nop_();
}
//延时 a * 1ms
void delayMs(uint a)
{
uint i, j;
for(i = a; i > 0; i--)
for(j = 100; j > 0; j--);
}
//检测LCD是否处于忙状态, 若忙返回1, 空闲返回0
bit checkBusy()
{
bit busy;
RS = 0;
RW = 1;
E = 1;
delayUs();
busy = (bit)(LCD_DATA&0x80);
E = 0;
return busy;
}
//等待LCD到空闲
void wait()
{
while(checkBusy());
}
//写命令
void writeCmd(uchar cmd)
{
wait();
RS = 0;
RW = 0;
E = 0;
delayUs();
LCD_DATA = cmd;
delayUs();
E = 1;
delayUs();
E = 0;
}
//写数据
void writeData(uchar dat)
{
wait();
RS = 1;
RW = 0;
E = 0;
delayUs();
LCD_DATA = dat;
delayUs();
E = 1;
delayUs();
E = 0;
}
//初始化LCD
void init()
{
PSB = 1; //并口方式
writeCmd(0x30); //基本指令, 扩充指令为34H
delayMs(10);
writeCmd(0x0c); //显示开, 关光标
writeCmd(0x01); //清屏
delayMs(10);
}
void init2()
{
PSB = 1; //并口方式
RET=0; //复位
delayUs(); //延时
RET=1; //复位置高
writeCmd(0x36);
delayMs(10);
writeCmd(0x3E);
delayMs(10);
writeCmd(0x01); //清屏
delayMs(10);
}
void setPosition(uchar x, uchar y)
{
uchar p;
switch(x%4)
{
case 0: p = 0x80; break; //第一行开始地址
case 1: p = 0x90; break; //第二行
case 2: p = 0x88; break; //第三行
case 3: p = 0x98; break; //第四行
}
p += y;
writeCmd(p);
}
void writeString(uchar * str)
{
uchar i = 0;
while(str[i] != '\0')
{
writeData(str[i++]);
}
}
void DisplayGraphic(unsigned char code *adder)
{
int i,j;
//*******显示上半屏内容设置
for(i=0;i<32;i++) //
{
writeCmd(0x80 + i); //SET 垂直地址 VERTICAL ADD
writeCmd(0x80); //SET 水平地址 HORIZONTAL ADD
for(j=0;j<16;j++)
{
writeData(*adder);
adder++;
}
}
//*******显示下半屏内容设置
for(i=0;i<32;i++) //
{
writeCmd(0x80 + i); //SET 垂直地址 VERTICAL ADD
writeCmd(0x88); //SET 水平地址 HORIZONTAL ADD
for(j=0;j<16;j++)
{
writeData(0xff);
adder++;
}
}
}
void initkb() //键盘初始化函数
{
EA=1;//�
EX0=1;
IT0=1;
count=0;
}
void exter0() interrupt 0
{
count++;
if(count>=2 && count<=9)
{
Data=(Data>>1);
if(DATA==1)
Data|=0x80;
}
}
void trains(uchar scancode)
{
static uchar up=0,shift=0; //up为通、断码标志,shift为shift键按下标志
uchar i;
if (!up) //已接收的11位数据是通码(up为0)
{
switch (scancode)//开始翻译扫描码
{
case 0xF0: //键盘释放标志(随后的一个字节是断码)
up=1; //设置up为断码标志
break;
case 0x12: //左shift键按下
shift=1; //设置shift为按下标志
break;
case 0x59: //右shift键按下
shift=1; //设置shift为按下标志
break;
default:
if(!shift) //如果shift键没有按下
{ //查找unshifted表,表中左列是扫描码,右列是对应的ASCII码
for(i=0;unshifted[i][0]!=scancode&&unshifted[i][0];i++);
if(unshifted[i][0]==scancode)
{
ASCII=unshifted[i][1];
}
}
else //如果shift键按下
{ //查找shifted表
for(i=0;shifted[i][0]!=scancode&&shifted[i][0];i++);
if(shifted[i][0]==scancode)
{
ASCII=shifted[i][1];
}
}
break;
}
}
else //已接收的11位数据是断码(up为1)
{
up = 0; //将断码标志复位
switch (scancode) //检测shift键释放
{
case 0x12 : //左shift键
shift = 0;
break;
case 0x59 : //右shift键
shift = 0;
break;
default:
break;
}
}
}
void main()
{
delayMs(500);
init();
initkb();
setPosition(0, 0);
writeString(datas1);
setPosition(1, 0);
writeString(datas2);
while(1)
{
if(count==11)
{
count=0;
trains(Data);
}
setPosition(2, 0);
writeData(ASCII);
if(count==0)
{
setPosition(3, 0);
writeString(datas3);
}
else
{
setPosition(3, 0);
writeString(datas4);
count=0;
}
}
}