电子大神的日记本,供应链专家的功夫茶盘,在这里记录、分享与共鸣。

登录以开始

第四十四课 PS\2之一 键盘+LCD1602显示

第四十四课 PS\2之一 键盘+LCD1602显示

 PS/2 通信协议

PS/2 通信协议是键盘与其他硬件通信时的一种半双工通信协议,键盘通过 Data 线向外发送数据,数据时钟由键盘产生,在协议中数据的传送格式为短帧格式,一般为 11 位,各位的含义如下图所示:

Start:起始位,总为‘0’(低电平)

D0~D7:8 位数据位(低位在前,高位在后)

Parity:奇偶校验位(为奇校验)

Stop:停止位,总为‘1’(高电平)

键盘向外发送数据的时序图如下图所示:

键盘首先检查 Clock 线和 Data 线是否同时为高电平时,若是,则键盘产生 Clock 信号,并将待发的数据按照数据帧的格式逐位放在数据线上,数据线在时钟的高电平期间改变状态,时钟的下降沿将数据锁定到数据线上,此时外界就可以到数据线上读取数据。键盘同步时钟的最大频率为 33KHZ,一般情况下使用 10~20KHZ 的频率。

 程序讲解

1、头文件PS_keyboard.H

/*--------------------------------------------------------------*/
//File: PS/2-keyboard头文件
//Date: 2009-4-18
//Time: 21:29

/*--------------------------------------------------------------*/
//防止被重复定义引用
#ifndef __PS_keyboard_H__
#define __PS_keyboard_H__
//包含头文件
#include "LCD_ASCII.H"   //键盘通码表

/*--------------------------------------------------------------*/
sbit keyboard_sda = P3^2;  //PS/2数据线 (对应开发板硬件)
sbit keyboard_clk = P3^3;  //PS/2时钟线

/*--------------------------------------------------------------*/
//数据定义
unsigned char n;                      //循环变量
unsigned int  keyboard_word; //接收字16bits
unsigned char keyboard_data; //接收字节
unsigned char keyboard_ascii; //查表得到的字符
bit shift_flag;                           //shift标志位
unsigned char r_ok;                //接收数据有效

/*--------------------------------------------------------------*/
//函数声明
void INT1_init(void);                   //外部中断INT0初始化
void keyboard_read_dat(void);    //读出数据
void keyboard_init(void);             //键盘初始化
void look_ascii(void);                  //查表字符

/*--------------------------------------------------------------*/
//外部中断INT0初始化
void INT1_init(void) 
{
 EA  = 1;    //总中断
 EX1 = 1;   //外部中断
 PX1 = 1;   //中断优先级
 IT1 = 0;     //低电平触发
}

/*--------------------------------------------------------------*/
//奇校验
bit check_parity(void)

 ACC = keyboard_data;
 if(~P == (bit)(keyboard_word & 0x0200)) return 1; //奇校验成功则返回1
 else          return 0;                                                   //奇校验失败则返回0
}

/*--------------------------------------------------------------*/
//读出字节数据
void keyboard_read_dat(void)
{
 keyboard_data = (unsigned char)(keyboard_word >> 1);//去掉最高两位和最后一位
 if(check_parity()) keyboard_word = 0;                   //奇校验成功//清接收数据字
 else    keyboard_data = 0;                                      //置零
 if(keyboard_data == 0xe0 | keyboard_data == 0xf0){;}  //忽略0xe0和0xf0字节
 else 
  if(keyboard_data == 0x12 | keyboard_data == 0x59) shift_flag = ~shift_flag;//shift按键检测
  else {r_ok++; if(r_ok == 2) EX1 = 0;}  //忽略通码,取断码,接收有效,断开中断,按键处理
}

/*--------------------------------------------------------------*/
//查表字符
void look_ascii(void)
{
 unsigned char i;
 for(i = 0; i < 48; i++)
 {
  if(KB_ASCII[i][2] == keyboard_data)        //查找按键通码
  {
   keyboard_ascii = KB_ASCII[i][shift_flag];  //得到相应字符
  }
 }
}

/*--------------------------------------------------------------*/
//外部中断INT0服务
//接收11位数据:1START-8DATA-1PARITY-1STOP
void INT1_intservice(void) interrupt 2  
{
 keyboard_word >>= 1;                                     //先向右空移一位
 if(keyboard_sda) keyboard_word |= 0x0400;    //先接收最低位
 n++; if(n == 11) {keyboard_read_dat(); n = 0;} //接收完成则读出数据
}

/*--------------------------------------------------------------*/
//键盘初始化
void keyboard_init(void)
{
 INT1_init();   //外部中断INT0初始化
}

/*--------------------------------------------------------------*/
#endif

 

本节重点:

1、11位数据的组成部分。

2、处理键盘发过来的数据的思路是:时钟信号为低(触发外部中断),这时单片机从数据端口取一位数据,当时钟信号再次为低时,单片机再取一位数据...如此循环11次即取出键盘发过来的11位数据。最后对取到的数据进行处理即可!

 

演示视频:

相关程序:http://space.ednchina.com/Upload/2009/6/10/0734af50-892c-47dd-8885-3fb3a2c2c332.rar

相关协议:pdf

博主
lmjxf
lmjxf's Blog
51入门成高手:http://group.ednchina.com/2031/  
点击跳转