打印
[AVR单片机]

[分享]PS2键盘

[复制链接]
2721|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yidou|  楼主 | 2010-3-25 20:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 yidou 于 2010-3-25 20:59 编辑

  • /*******************************************
  •   文件:PS2_KB.C
  •   环境:编译为ICC AVR6.25A,仿真为AVR Studio4.10
  •   硬件:ATMEGA16芯片
  •   日期:2006年12月10日
  •   功能:驱动开发板上的PS2接口,实现PS2键盘(支持第2套扫描码)
  •   备注:参考《AVR系列单片机C语言编程与应用实例》(清华大学出版社)
  • /******************************************/

  • #include <IOM16V.H>         //包含型号头文件

  • #include <MACROS.H>         //包含"位"操作头文件

  • #include <STDIO.H>          //标准输入输出头文件

  • #include <AVR_PQ1A.H>       //包含自定义常量头文件

  • #include "YJ1602.C"

  • #pragma interrupt_handler Int0:2    //外部中断0中断函数声明

  • #pragma data:code                   //将译码表放在FLASH

  • const uchar 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
  • };

  • const uchar 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
  • };

  • #pragma data:data           //将以后的变量放在RAM

  • void Decode(uchar scancode);//声明函数原型
  • uchar edge, bitcount,ascii=' ';     //edge为0下降沿中断,为1上升沿中断

  • //bitcount为位计数值

  • //ascii为翻译后的ASCII码,初值为空格

  • /*******************************************
  • 函数名称: Init_kb
  • 功    能: 初始化PS2函数
  • 参    数: 无
  • 返回值  : 无
  • /********************************************/

  • void Init_kb(void)
  • {
  • MCUCR = 2;       //设置INT0为下降沿触发中断
  • edge = 0;        //0为下降沿中断标志,1为上升沿中断标志
  • bitcount = 11;   //每次11位数据,一个起始位(0),8个数据位,一个奇偶校验位,一个停止位(1)
  • DDRD&=~BIT(PD2); //配置中断管脚为输入
  • PORTD|=BIT(PD2); //使能中断管脚的上拉
  • DDRA&=~BIT(PA0); //配置键盘数据输入口为输入
  • PORTA|=BIT(PA0); //使能数据输入管脚的上拉
  • SREG|=BIT(GLOBAL);//打开全局中断
  • GICR|=BIT(EXTINT0);
  • }

  • /*******************************************
  • 函数名称: Disp_ascii
  • 功    能: 在1602液晶上显示键盘上的ASCII码
  • 参    数: ascii--将要显示的ASCII码
  • 返回值  : 无
  • /********************************************/

  • void Disp_ascii(uchar ascii)
  • {
  • LCD1602_gotoXY(1,2);
  • LCD1602_sendstr("KEY_ASCII:");
  • LCD1602_sendbyte(iDat,ascii);
  • }

  • /*******************************************
  • 函数名称: Int0
  • 功    能: 外部中断0的中断服务函数,上升沿中断读入11位数据,下降沿调用解码程序
  • 参    数: 无
  • 返回值  : 无
  • /********************************************/

  • void Int0(void)
  • {

  • static uchar data;   // 声明局部静态变量来保存扫描码

  • if (!edge)                 // 如果是下降沿触发中断
  • {

  • if(bitcount < 11 && bitcount > 2)    //3到10位是数据,起始位,校验位和停止位忽略
  •   {
  •     data = (data >> 1);                  //右移保存数据

  • if(PINA&0x01)
  •     {
  •       data|=0x80;                      //存储一个'1'
  •     }
  •   }
  •   MCUCR=3;               //设置INT0为上升沿触发中断
  •   edge=1;                //设置上升沿中断标志
  • }

  • else
    //如果是上升沿触发中断
  • {
  •   MCUCR=2;               //设置INT0为下降沿触发中断
  •   edge=0;                //设置下降沿中断标志

  • if(--bitcount==0)      //如果11位全部接收完毕
  •   {
  •    Decode(data);     //将扫描码翻译成ASCII码
  •    bitcount = 11;        //重新设为11位数据
  •   }
  • }
  • }

  • /*******************************************
  • 函数名称: Decode
  • 功    能:
  • 参    数: scancode--需要翻译的扫描码
  • 返回值  : 无
  • /********************************************/

  • void Decode(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[0]!=scancode&&unshifted[0];i++);

  • if(unshifted[0]==scancode)
  •            {
  •             ascii=unshifted[1];
  •            }
  •         }

  • else
    //如果shift键按下
  •         {                     //查找shifted表

  • for(i=0;shifted[0]!=scancode&&shifted[0];i++);

  • if(shifted[0]==scancode)
  •            {
  •             ascii=shifted[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;
  •   }
  • }
  • }

  • /*******************************************
  • 函数名称: main
  • 功    能: 实现PS2键盘的驱动,在1602液晶上显示键盘上的ASCII码
  • 参    数: 无
  • 返回值  : 无
  • /********************************************/

  • void main(void)
  • {
  • Board_init( );             //初始化开发板
  • LCD1602_initial( );        //初始化1602
  • Init_kb();                 //初始化PS2键盘接口

  • while(1)
  • {
  •   Disp_ascii(ascii);    //显示翻译后的ASCII码
  • }
}
来源:http://read.pudn.com/downloads93/sourcecode/embed/362725/19_PS2/PS2_KB.C__.htm

相关帖子

沙发
xwj| | 2010-3-25 21:02 | 只看该作者
好多好多年前就做过了,ATmel有个英文文档的

使用特权

评论回复
板凳
yidou|  楼主 | 2010-3-25 21:10 | 只看该作者
:D呵呵,菜鸟看看,老鸟就顶顶吧

使用特权

评论回复
地板
lpydidi| | 2010-3-25 21:25 | 只看该作者
菜鸟···

使用特权

评论回复
5
xiaomifan| | 2010-3-25 21:36 | 只看该作者
留个印

使用特权

评论回复
6
yidou|  楼主 | 2010-3-27 23:08 | 只看该作者
外部中断0的中断服务函数还是挺好的

使用特权

评论回复
7
hotpower| | 2010-7-27 19:39 | 只看该作者
顶起来

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

391

帖子

1

粉丝