PS2键盘解码的基本原理是通过外部中断读取键盘输出的串行信号,在根据扫描码进行查表解码。键盘发送往主机的信号总是在时钟的下降沿因此此中断是在下降沿触发,且时钟信号是由键盘给出,因此使用P1口中断(已经在初始化端口时设置)。发送的数据位11位,第一位是起始位,总为0,紧接是8个数据位,然后是奇校验位,最后是停止位总为1.本程序只能对基本按键(即键被按下时产生三个字节的扫描码的按键)做出解码,包括所有的可显示字符键和Table,Back Space和Ente三个特殊功能键。基本按键的扫描码由三个字节组成,第1个字节为接通码,第2、3字节为断开码;其中第1字节和第3字节相同,中间字节为断开标志0xf0。例如:通码和断码是以什么样的序列发送到你的计算机使得字符G 出现在你的字处理软件里呢?因为这是一个大写字母需要发生这样的事件次序按下Shift 键按下G 键释放G 键释放Shift 键,与这些时间相关的扫描码如下:Shift 键的通码12h G键的通码34h G 键的断码F0h 34h Shift 键的断码F0h 12h 因此发送到你的计算机的数据应该是12h 34h F0h 34h F0h 12h如果按键按着不放会连续发送通码命令,可以连续显示字符(没有验证,实验验证是可以的)。
具体的说明都已经在程序中做了注释,主程序,中断服务函数中读取键盘发送的值:
- /*****************************************************
- 程序功能:接收并解码来自标准键盘的基本按键的扫描码
- 然后在1602液晶上显示。按BackSpace键可以前向删除显
- 示字符,按Space键可以后向删除显示字符。
- -----------------------------------------------------
- 将拨码开关的SN74LVC2454和LCD位拨至ON
- 读取键盘的信号需要电平转换,注意设置SN74LVC2454的转换方向
- 跳线设置:将跳线座J13的B8脚和P1.7脚短接
- -----------------------------------------------------
- 测试说明:敲定标准键盘上的按键,观察液晶显示
- *****************************************************/
- #include
- #include"cry1602.h"
- #include"cry1602.C"
- #include"S2Keyboard.h"
- #include"S2Keyboard.C"
- #defineSIDvalP5IN&BIT6
- #defineBufferSize32//显示缓存大小
- unsignedcharbitcount=11;//位计数变量
- unsignedcharkb_buffer[BufferSize];//显示缓存
- unsignedcharinput=0;//数据压入缓存位置指针
- unsignedcharoutput=0;//数据弹出缓存位置指针
- unsignedcharpebit=0xff;//奇偶校验标志位
- unsignedcharrecdata=0;//接收到的数据
- unsignedchartishi[]={"thisisademo!"};
- /****************主函数****************/
- voidmain(void)
- {
- uchardisptmp,i;
- ucharx=0,y=0;
- ucharfirst=1;
- WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
- P6DIR|=BIT26OUT&=~BIT2;//打开电平转换
- P2DIR|=BIT32OUT|=BIT3;//方向5V-->3.3V
- /*------选择系统主时钟为8MHz-------*/
- BCSCTL1&=~XT2OFF;//打开XT2高频晶体振荡器
- do
- {
- IFG1&=~OFIFG;//清除晶振失败标志
- for(i=0xFF;i>0;i--);//等待8MHz晶体起振
- }
- while((IFG1&OFIFG));//晶振失效标志仍然存在?
- BCSCTL2|=SELM_2;//主时钟选择高频晶振
- LcdReset();//复位液晶
- DispNchar(0,0,15,tishi);//液晶显示提示信息
- Init_KB();//初始化键盘端口
- _EINT();//打开全局中断
- while(1)
- {
- LPM3;//进入低功耗模式
- if(first)
- {
- first=0;
- LcdWriteCommand(0x01,1);//显示清屏
- LcdWriteCommand(0x0f,1);//打开游标
- }
- disptmp=GetChar();//读取键值对应的ASCII码
- if(disptmp!=0xff)//取出了一个有效字符
- {
- if(disptmp==8)//如果是退格键
- {
- if((x==0)&&(y==0))//如果游标在第1行第1位
- {
- x=15;
- y=1;
- Disp1Char(x,y,0x20);//0x20是空格的ASCII码
- LocateXY(x,y);
- }
- elseif((x==0)&&(y==1))//如果游标在第2行第1位
- {
- x=15;
- y=0;
- Disp1Char(x,y,0x20);
- LocateXY(x,y);
- }
- else
- {
- Disp1Char(--x,y,0x20);
|