第四十四课 PS\2之一 键盘+LCD1602显示
PS/2 通信协议<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
PS/2 通信协议是键盘与其他硬件通信时的一种半双工通信协议,键盘通过 Data 线向外发送数据,数据时钟由键盘产生,在协议中数据的传送格式为短帧格式,一般为 11 位,各位的含义如下图所示:
Start:起始位,总为‘0’(低电平)
D0~D7:8 位数据位(低位在前,高位在后)
Parity:奇偶校验位(为奇校验)
Stop:停止位,总为‘1’(高电平)
键盘向外发送数据的时序图如下图所示:
键盘首先检查 Clock 线和 Data 线是否同时为高电平时,若是,则键盘产生 Clock 信号,并将待发的数据按照数据帧的格式逐位放在数据线上,数据线在时钟的高电平期间改变状态,时钟的下降沿将数据锁定到数据线上,此时外界就可以到数据线上读取数据。键盘同步时钟的最大频率为 33KHZ,一般情况下使用 10~20KHZ 的频率。
/*--------------------------------------------------------------*/
//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[2] == keyboard_data) //查找按键通码
{
keyboard_ascii = KB_ASCII[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位数据。最后对取到的数据进行处理即可!
相关程序:https://static.assets-stash.eet-china.com/album/old-resources/2009/6/10/0734af50-892c-47dd-8885-3fb3a2c2c332.rar
相关协议:
用户1584993 2009-6-11 11:04