单片机课程设计单片机实现PC机键盘控制器设计.docx
《单片机课程设计单片机实现PC机键盘控制器设计.docx》由会员分享,可在线阅读,更多相关《单片机课程设计单片机实现PC机键盘控制器设计.docx(32页珍藏版)》请在冰豆网上搜索。
![单片机课程设计单片机实现PC机键盘控制器设计.docx](https://file1.bdocx.com/fileroot1/2022-11/24/9a068bb4-41ae-4e4a-8b6f-109636677cd6/9a068bb4-41ae-4e4a-8b6f-109636677cd61.gif)
单片机课程设计单片机实现PC机键盘控制器设计
《单片机原理及应用》
课程设计报告书
课题名称
单片机实现PC机键盘控制器设计
姓名
学号
专业
指导教师
机电与控制工程学院
年月日
任务书
设计课题:
单片机实现PC机键盘控制器设计
设计任务及要求:
目的:
掌握单片机扫瞄键盘原理,以及单片机与PC机通信方法。
内容:
单片机通过扫描键盘确定键盘(有键按下时),然后通过232串口将键盘值发送给PC机。
要求:
进一步学习单片机应用技术,接口电路及应用程序,巩固与综合基础及专业知识,综合分析的思维与创新能力,能根据查阅相关手册与资料,提高一定的自学能力和独立分析问题的能力,解决问题的能力。
1、绪论………………………………………………………………………4
2、键盘工作原理……………………………………………………………5
3、PS/2通信协议……………………………………………………………7
4、程序及硬件设计…………………………………………………………8
5、单片机与PC机通讯……………………………………………………34
6、技术小结…………………………………………………………………40
7、致谢………………………………………………………………………41
8、参考文献…………………………………………………………………42
9、硬件调试…………………………………………………………43
1、绪论
到目前为止,人们已设计的键盘有83键、84键、101键、102键等多种,采用的一般都是由单片机(8048、8035、8044等)扫描、编码的智能化键盘。
当前人们所用的一般都是非编码键盘,它仅仅是按行、列排列起来的的矩阵开关,键盘内部使用的单片机能够自动地识别键的按下与释放,自动生成相应的扫描码(即行列位置码),并以串行方式送往接口。
此外,它还具有若干个键扫描码的缓冲能力和出错下的自动重发能力,但是,由于是非编码键盘,所以它向接口提供的只是键的行列位置码(即键盘扫描码),而不是键的含义和功能直接对应的ASCII码,因此设计时需要将键盘扫描码转化成反映键意的ASCII码。
由于最初人们设计的键盘只有83键,它的键号(即ASCII码)与键盘扫描码是一致的,随着键盘功能和按键数目的扩充,为了实现各种不同功能和按键数目键盘与PC机之间的兼容性,84/101/102等键盘的键盘扫描码还是采用了83键的键盘的那83个键盘扫描码,只是在送到PC机以后再由PC机来完成将83个键盘扫描码转化成相应个数的系统扫描码。
2、Ps/2键盘工作原理
到目前为止,人们设计的键盘有83键、84键、101键、102键等多种,采用的一般是由单片机(8048、8035、8044等)扫描、编制的智能化键盘。
当前人们所用的都是非编码键盘,它仅仅是按行、列排列起来的矩阵开关,键盘内部使用的单片机能够自动的识别键的按下与释放,自动生成相应的扫描码(即行列位置码),并以串行方式送至往接口。
此外,它还具有若干个键扫描码的缓冲能力和出错下自动重发能力,但是,由于是非编码键盘,所以它向接口提供的只是键的行列位置码(即键盘扫描码)而不是与键的含义和功能直接对应的ASCLL码,因此设计时需要将键盘扫描码转化成反映键意的ASCLL码。
由于最初人们设计的键盘只有83键,它的键号(即ASCLL码)与键盘扫描码是一致的,随着键盘功能和按键数目的扩充,为了实现不同功能和按键数目键盘与PC机之间的兼容性,84/101/102等键盘的键盘扫描码还是采用了83键的键盘的那83个键盘扫描码,只是在送到PC机以后在有PC机来完成将83个键盘扫描码转化成相应个数的系统扫描码。
键盘对按键的识别和行列位置扫描码(即键盘扫描码)产生是有键盘内部的单片机通过译码来实现的。
单片机在列行扫描的同时,读回扫描信号的结果,判断是否有键按下,并计算位置得到行列位置码(及键盘扫描码)。
当有键按下时,键盘分两次将行列位置扫描码发送到键盘接口。
按下时发送一次叫接通扫描码,释放时在发送一次叫断开扫描码,断开扫描码与接通扫描码之间是有一定关系的,断开扫描码有两个字节,第一个是表明键已释放的的前缀FOH,第二个字节与接通扫描码。
目前已有的键盘扫描码共有三套,我们现在使用的一般是第二套键盘扫描码(101,102,104键),其接通扫描码编码表如下:
KEY
CODE
KEY
CODE
KEY
CODE
A
1C
9
46
[
54
B
32
0e
Insert
E0,70
C
21
-
4e
Home
E0,6c
D
23
=
55
PGUP
E0,7D
E
24
\
5D
DELETE
E0,71
F
2B
BKSP
66
END
E0,69
G
34
SPACE
29
PGDN
E0,7A
H
33
TAB
0D
UARROW
E0,75
I
43
CAPS
58
LARROW
E0,6B
J
3B
LSHIFT
12
DARROW
E0,72
K
42
RSHIFT
14
RARROW
E0,74
L
4B
LWIN
E0,1F
NUM
77
M
3A
LALT
11
KP/
E0,4A
N
31
RSHIFT
59
KP*
7C
O
44
RCTRL
E0,14
KP-
7B
P
4D
RWIN
E0,27
KP+
79
Q
15
RALT
E0,11
KPEN
E0,5A
R
2D
APPS
E0,2F
KP.
71
S
1B
ENTER
5A
KP0
70
T
2C
ESC
76
KP1
69
U
3C
F1
05
KP2
72
V
2A
F2
06
KP3
7A
W
1D
F3
04
KP4
6B
X
22
F4
0C
KP5
73
Y
35
F5
02
KP6
74
Z
1A
F6
0B
KP7
6C
0
45
F7
83
KP8
75
1
16
F8
0A
KP9
7D
2
1E
F9
01
;
4C
3
26
F10
09
.
52
4
25
F11
78
41
5
2E
F12
07
‘
49
6
36
PRINT
E0,12
/
4A
7
3D
7E
7E
】
5B
8
3E
E1,14
E1,14
上表中的数据均为16进制数。
(一)PS/2硬件接口
硬盘与其他硬件的接口采用PS/2硬件接口,其物理连接方式通常有两种:
5-pinDIN和6-pinmini-DIN,目前所用的连接方式一般是后一种,其引脚排列和外形如下图所示:
3、ps/2通讯协议
ps/2通讯协议时键盘与其他硬件通信时的半双通讯协议,键盘通过Data线向外发送数据,数据时钟由键盘产生,在协议中数据的传送格式为短帧格式,一般为11位,各位的含义如下图所示;
Start
D0
D1
D2
D3
D4
D5
D6
D7
Parity
Stop
Start:
起始位,总为“0”(低电平)
D1~D7:
八位数据位(低位在前,高位在后)
Parity:
奇偶校验位(为基校验)
Stop:
停止位,总为“1”(高电平)
键盘向外发送数据的时序图如下图所示:
键盘首先检查Clock线和Data线是否同时为高电平,若是,则键盘产生Clock信号,并将待发的数据按照数据帧的格式逐位放在数据线上,数据线在时钟的高电平期间改变状态时钟的下降沿将数据锁定到数据线上,此时外界就可以到数据线上读取数据,键盘同步时钟的最大频率为33KHZ,一般情况下使用10~20KHZ的频率。
4、程序及硬件设计
本次设计需要设计以下五个部分:
串并转换程序,时钟分频程序,缓程序,扫描码与ASCLL码转换程序,LED显示驱动程序。
其中部分程序实现的功能简要称述如下:
串并转换程序
该程序主要是接受只有键盘Data线发送过来的11位串行数据。
用的是11位移位寄存器的基本原理。
时钟分频程序
改程序只要是实现将硬件箱上的25.175M的时钟分频。
用的是计数器的基本原理。
缓冲程序
该部分程序主要实现的功能是将键盘按下的32个键进行缓存,在硬件箱上实现人为控制显示。
用的是FIFO(先入先出堆栈)的基本原理。
扫描码与ASCLL码转换程序
该部分程序实现将有键盘发送过来的键盘扫描码转换成ASCLL码。
三、源程序
1602显示程序
#include"1602.h"
#include"delay.h"
#defineCHECK_BUSY
sbitRS=P2^1;//定义端口
sbitRW=P1^5;
sbitEN=P1^6;
#defineRS_CLRRS=0
#defineRS_SETRS=1
#defineRW_CLRRW=0
#defineRW_SETRW=1
#defineEN_CLREN=0
#defineEN_SETEN=1
#defineDataPortP0/
判忙函数
bitLCD_Check_Busy(void)
{
#ifdefCHECK_BUSY
DataPort=0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return(bit)(DataPort&0x80);
#else
return0;
#endif
}
写入命令函数
voidLCD_Write_Com(unsignedcharcom)
{
while(LCD_Check_Busy());//忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort=com;
_nop_();
EN_CLR;
}
写入数据函数
voidLCD_Write_Data(unsignedcharData)
{
while(LCD_Check_Busy());//忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort=Data;
_nop_();
EN_CLR;
}
清屏函数
voidLCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
写入字符串函数
voidLCD_Write_String(unsignedcharx,unsignedchary,unsignedchar*s)
{
if(y==0)
{
LCD_Write_Com(0x80+x);//表示第一行
}
else
{
LCD_Write_Com(0xC0+x);//表示第二行
}
while(*s)
{
LCD_Write_Data(*s);
s++;
}
}
写入字符函数
voidLCD_Write_Char(unsignedcharx,unsignedchary,unsignedcharData)
{
if(y==0)
{
LCD_Write_Com(0x80+x);
}
else
{
LCD_Write_Com(0xC0+x);
}
LCD_Write_Data(Data);
}
初始化函数
voidLCD_Init(void)
{
LCD_Write_Com(0x38);/*显示模式设置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08);/*显示关闭*/
LCD_Write_Com(0x01);/*显示清屏*/
LCD_Write_Com(0x06);/*显示光标移动设置*/
DelayMs(5);
LCD_Write_Com(0x0C);/*显示开及光标设置*/
}
1602引脚定义
引脚定义如下:
1-VSS2-VDD3-V04-RS5-R/W6-E7-14DB0-DB715-BLA16-BLK
#include//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include
#ifndef__1602_H__
#define__1602_H__
bitLCD_Check_Busy(void);
voidLCD_Write_Com(unsignedcharcom);
voidLCD_Write_Data(unsignedcharData);
voidLCD_Clear(void);
voidLCD_Write_String(unsignedcharx,unsignedchary,unsignedchar*s);
voidLCD_Write_Char(unsignedcharx,unsignedchary,unsignedcharData);
voidLCD_Init(void);
#endif
REG52.H
#ifndef__REG52_H__
#define__REG52_H__
/*BYTERegisters*/
sfrP0=0x80;
sfrP1=0x90;
sfrP2=0xA0;
sfrP3=0xB0;
sfrPSW=0xD0;
sfrACC=0xE0;
sfrB=0xF0;
sfrSP=0x81;
sfrDPL=0x82;
sfrDPH=0x83;
sfrPCON=0x87;
sfrTCON=0x88;
sfrTMOD=0x89;
sfrTL0=0x8A;
sfrTL1=0x8B;
sfrTH0=0x8C;
sfrTH1=0x8D;
sfrIE=0xA8;
sfrIP=0xB8;
sfrSCON=0x98;
sfrSBUF=0x99;
/*8052Extensions*/
sfrT2CON=0xC8;
sfrRCAP2L=0xCA;
sfrRCAP2H=0xCB;
sfrTL2=0xCC;
sfrTH2=0xCD;
/*BITRegisters*/
/*PSW*/
sbitCY=PSW^7;
sbitAC=PSW^6;
sbitF0=PSW^5;
sbitRS1=PSW^4;
sbitRS0=PSW^3;
sbitOV=PSW^2;
sbitP=PSW^0;//8052only
/*TCON*/
sbitTF1=TCON^7;
sbitTR1=TCON^6;
sbitTF0=TCON^5;
sbitTR0=TCON^4;
sbitIE1=TCON^3;
sbitIT1=TCON^2;
sbitIE0=TCON^1;
sbitIT0=TCON^0;
/*IE*/
sbitEA=IE^7;
sbitET2=IE^5;//8052only
sbitES=IE^4;
sbitET1=IE^3;
sbitEX1=IE^2;
sbitET0=IE^1;
sbitEX0=IE^0;
/*IP*/
sbitPT2=IP^5;
sbitPS=IP^4;
sbitPT1=IP^3;
sbitPX1=IP^2;
sbitPT0=IP^1;
sbitPX0=IP^0;
/*P3*/
sbitRD=P3^7;
sbitWR=P3^6;
sbitT1=P3^5;
sbitT0=P3^4;
sbitINT1=P3^3;
sbitINT0=P3^2;
sbitTXD=P3^1;
sbitRXD=P3^0;
/*SCON*/
sbitSM0=SCON^7;
sbitSM1=SCON^6;
sbitSM2=SCON^5;
sbitREN=SCON^4;
sbitTB8=SCON^3;
sbitRB8=SCON^2;
sbitTI=SCON^1;
sbitRI=SCON^0;
/*P1*/
sbitT2EX=P1^1;//8052only
sbitT2=P1^0;//8052only
/*T2CON*/
sbitTF2=T2CON^7;
sbitEXF2=T2CON^6;
sbitRCLK=T2CON^5;
sbitTCLK=T2CON^4;
sbitEXEN2=T2CON^3;
sbitTR2=T2CON^2;
sbitC_T2=T2CON^1;
sbitCP_RL2=T2CON^0;
#endif
INTRINS.H
#ifndef__INTRINS_H__
#define__INTRINS_H__
externvoid_nop_(void);
externbit_testbit_(bit);
externunsignedchar_cror_(unsignedchar,unsignedchar);
externunsignedint_iror_(unsignedint,unsignedchar);
externunsignedlong_lror_(unsignedlong,unsignedchar);
externunsignedchar_crol_(unsignedchar,unsignedchar);
externunsignedint_irol_(unsignedint,unsignedchar);
externunsignedlong_lrol_(unsignedlong,unsignedchar);
externunsignedchar_chkfloat_(float);
#endif
#ifndef__DELAY_H__
#define__DELAY_H__
/*------------------------------------------------
uS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下T=tx2+5uS
------------------------------------------------*/
voidDelayUs2x(unsignedchart);
/*------------------------------------------------
mS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
voidDelayMs(unsignedchart);
#endif
#include"delay.h"
/*------------------------------------------------
uS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下T=tx2+5uS
------------------------------------------------*/
voidDelayUs2x(unsignedchart)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
voidDelayMs(unsignedchart)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
#ifndef__DELAY_H__
#define__DELAY_H__
/*------------------------------------------------
uS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下T=tx2+5uS
------------------------------------------------*/
voidDelayUs2x(unsignedchart);
/*------------------------------------------------
mS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
voidDelayMs(unsignedchart);
#end