单片机驱动标准PC机键盘的C51程序
2012-11-04
标签: 键盘

功能:

实现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;
    }
}


可能会用到的工具/仪表
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号