实现pc机键盘(p/s2接口)与8位单片机连接使用
键盘时钟接在p3.2口,既8051的外部中断int0上,键盘数据接到p1.0上,每次按键,键盘会向单片机发脉冲使单片机发生外部中断,数据有p1.0口一位一位传进来。传回的数据格式为:1位开始位(0),8位数据位(所按按键的通码,用来识别按键),1位校验位(奇校验)1位结束位(1)
将键盘发回的数据放到一个缓冲区里(数组),当按键结束后发生内部中断来处理所按的按键
由于51单片机的容量有限所以缓冲区不可以开的太大,这就导致可以记录键盘的按键次数过少,也就是容错性一般。不过如果正常使用键盘是不会出错的
开发人:鞠春阳
#include "intrins.h" #include "ku.h" //按键通码与ascii对照表 sbit sda = p1 ^ 0; //键盘数据线 unsigned char dat = 0, dat1 = 0, dat2 = 0; //接收键盘数据变量? 存储通码变量 接受连续通码变量 unsigned char count = 0, num = 9, temp[5], shu = 0; //中数次数 中断控制变量 缓冲区数组 缓冲区指针 unsigned char key = 0; //按键最终值 void zhongduan() interrupt 0 //外部中断0 用来接受键盘发来的数据 { dat >>= 1; //接受数据 低->高 if (sda) { dat |= 0x80; } count++; if (count == num) { if (count == 9) { dat1 = dat; //中断9次后为键盘所按按键的通码(开始位始终为0在第一次中断时右移中忽略) num = 20; //使中断可以继续中断11次 } if (count == 20) { dat2 = dat; //取回第二个通码 if (dat1 == 0xe0 || dat2 == 0xf0) { //第一个通码是0xe0则证明所按按键为功能键,第二个通码是0xf0证明按键结束 temp[shu] = dat1; temp[shu + 1] = dat2; shu += 2; //将所按按键存到缓冲区中 ie = 0x82; //关闭外部中断并打开内部中断来处理所按按键 tr0 = 1; } else { temp[shu] = dat1; temp[shu + 1] = dat2; shu += 2; //如果shift键被按下则记录与它同时按下的那个键 count = 0; } if ((temp[0] == 18 || temp[0] == 89) && (temp[2] == 18 || temp[2] == 89)) { tr0 = 1; //如果缓冲区中有两个间隔的shift键则证明需要的铵键结束 } } } } void getkey() interrupt 1 //内部中断0 用来处理缓冲区里的数据 { unsigned char i = 0; tr0 = 0; th0 = 0; tl0 = 0; count = 0; //中断记数则0 if ((temp[0] == 18 || temp[0] == 89) && temp[1] != 0xf0) { //shift被按下 for (i = 0; i < 21; i++) { if (addshift[i][0] == temp[1]) { //搜索shift被按下的表 key = addshift[i][1]; ie = 0x83; //打开外部中断 return; } } } else if (temp[0] == 0xe0) { //所按下的按键是功能键 for (i = 0; i < 80; i++) { if (noshift[i][0] == temp[1]) { //功能键的通码在缓冲区的第二位 key = noshift[i][1]; ie = 0x83; return; } } } else { //普通按键 for (i = 0; i < 80; i++) { if (noshift[i][0] == temp[0]) { //普按键的通码在缓冲区的第一位 key = noshift[i][1]; ie = 0x83; return; } } } for (i = 0; i < 5; i++) { temp[i] = 0; } }