⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kb.c

📁 WINAVR编写的PS2键盘驱动
💻 C
字号:
/*---------------------------------------------------------
 *Filename:kb.c
 *Function:PS2键盘程序,忽略起始位、奇偶校验位、停止位
 *Author:ken
 *Date:2007-8-18
----------------------------------------------------------*/
#include "kb.h"
#include "scancodes.h"
#include <avr/io.h>
#include <avr/interrupt.h>

#define BUFF_SIZE 64
#define PSDAT PD6
#define PSCLK PD2

unsigned char edge, bitcount;               //edge表示是下降沿读取,还是上升沿读取;bitcount是一帧的位数

unsigned char kb_buffer[BUFF_SIZE];
unsigned char *inpt, *outpt;
unsigned char buffcnt;                      //用于记录当前的缓冲区读或写的位置



/*-----------------------------------------------------------
InitKeyBoard :键盘程序初始化函数
输入参数     :无
输出参数     :无
作者         :ken
日期         :2007-8-18
------------------------------------------------------------*/ 
void InitKeyBoard(void)
{
    inpt =  kb_buffer;                        // 初始化键盘缓冲区
    outpt = kb_buffer;
    buffcnt = 0;

    MCUCR = (1<<ISC01);                      // INT0下降沿有效
    edge = 0;                                // 0 = 下降沿  1 = 上升沿
    bitcount = 11;                           // PS2传输一帧数据是11位,一个起始位,一个奇偶校验位,一个停止位。
    sei();                                   // 开全局中断
}


/*-----------------------------------------------------------
INT0_interrupt:处理键盘中断服务程序
输入参数      :无
输出参数      :无
作者          :ken
日期          :2007-8-18
------------------------------------------------------------*/ 
SIGNAL(SIG_INTERRUPT0)                           //PSCLK与PD2即INT0连接,下降沿读取PSDAT的数据
{
    static unsigned char data;                 // data用来保存接收到的数据。

        if(bitcount < 11 && bitcount > 2)       // 3-10位是数据位. 忽略起始位,校验位,停止位
        {                                      
            data = (data >> 1);                 //因为PS2协议是低位在前的,所以要右移
            if(PIND & (1<<PSDAT))              
                data = data | 0x80;             
        }

        if(--bitcount == 0)                    // 11位数据都接收完,进入解码程序
        {
            decode(data);
            bitcount = 11;
        }
 }

/*-----------------------------------------------------------
decode        :解码键码程序
输入参数 sc   :8bit原始代码数据
输出参数      :无
作者          :ken
日期          :2007-8-18
------------------------------------------------------------*/ 
void decode(unsigned char sc)
{
    static unsigned char is_up=0, shift = 0, mode = 0;
    unsigned char i;
 
    if (!is_up)              // Last data received was the up-key identifier
    {
        switch (sc)
        {
          case 0xF0 :        // The up-key identifier
            is_up = 1;
            break;

          case 0x12 :        // Left SHIFT
            shift = 1;
            break;

          case 0x59 :        // Right SHIFT
            shift = 1;
            break;

          case 0x05 :        // F1
            if(mode == 0)
                mode = 1;    // Enter scan code mode
            if(mode == 2)
                mode = 3;    // Leave scan code mode
            break;

          default:
            if(mode == 0 || mode == 3)        // If ASCII mode
            {
                if(!shift)                    //  识别有没有按下shift键
                {                            // for语句又于寻找键盘码
                    for(i = 0; unshifted[i][0]!=sc && unshifted[i][0]; i++);//输出没按shift键的码
                    if (unshifted[i][0] == sc) {
                        put_kbbuff(unshifted[i][1]);
                    }
                } else {                    // If shift pressed
                    for(i = 0; shifted[i][0]!=sc && shifted[i][0]; i++);//输出按下shift键的码
                    if (shifted[i][0] == sc) {
                        put_kbbuff(shifted[i][1]);
                    }
                }
            } 
			else{                                   // Scan code mode
                print_hexbyte(sc);            // Print scan code
                put_kbbuff(' ');

            }
            break;
        }
    } else {
        is_up = 0;                            // Two 0xF0 in a row not allowed
        switch (sc)
        {
          case 0x12 :                        // Left SHIFT
            shift = 0;
            break;
            
          case 0x59 :                        // Right SHIFT
            shift = 0;
            break;

          case 0x05 :                        // F1
            if(mode == 1)
                mode = 2;
            if(mode == 3)
                mode = 0;
            break;
          case 0x06 :                        // F2
            break;  
            
        } 
    }    
} 


/*-----------------------------------------------------------
put_kbbuff    :键码保存到缓冲区
输入参数 c    :经解码所得键码数据
输出参数      :无
作者          :ken
日期          :2007-8-18
------------------------------------------------------------*/ 
void put_kbbuff(unsigned char c)
{
    if (buffcnt<BUFF_SIZE)                        // If buffer not full
    {
        *inpt = c;                                // Put character into buffer
        inpt++;                                    // Increment pointer

        buffcnt++;

        if (inpt >= kb_buffer + BUFF_SIZE)        // Pointer wrapping
            inpt = kb_buffer;
    }
}


/*-----------------------------------------------------------
getchar_kb    :键码接收程序
输入参数      :无
输出参数      :键码
作者          :ken
日期          :2007-8-18
------------------------------------------------------------*/ 
unsigned char getchar_kb(void)
{
    unsigned char byte;
    while(buffcnt == 0);                           // Wait for data

    byte = *outpt;                                 // Get byte
    outpt++;                                       // Increment pointer

    if (outpt >= kb_buffer + BUFF_SIZE)            // Pointer wrapping
        outpt = kb_buffer;
    
    buffcnt--;                                     // Decrement buffer count

    return byte;
}

/*-----------------------------------------------------------
print_hexbyte :直接保存原始8bit代码到缓冲区,不经解码
输入参数 i    :原始8bit代码
输出参数      :无
作者          :ken
日期          :2007-8-18
------------------------------------------------------------*/ 
void print_hexbyte(unsigned char i)
{
    unsigned char h, l;
    
    h = i & 0xF0;               // 高4位
    h = h>>4;
    h = h + '0';
    
    if (h > '9')
        h = h + 7;

    l = (i & 0x0F)+'0';         // 低4位
    if (l > '9')
        l = l + 7;

    put_kbbuff(h);
    put_kbbuff(l);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -