📄 key_b.c
字号:
/****************************************************************************
*函数功能:本程序主要通过外部中断INT0及3.3端口读取PS2键盘值并通过LCD1602显示,
*键扫描码的解码通过数组方式解码,程序的解码功能主要针对数字及大小写字母和常用
*标点符号
*创建者: 曹兴
*创建日期:2008-10-11
*版本号: 2008101101
*****************************************************************************/
#include"reg51.h"
#include"stdio.h"
/*****************************端口定义***************************************/
#define DATA P0 //LCD数据传输端口
sbit RS = P2^7; //LCD控制端口定义
sbit RW = P2^6;
sbit EP = P2^5;
sbit k_data = P3^3; //PS/2数据线端口
sbit k_clk = P3^2; //PS/2时钟线端口
unsigned char bitcount = 11; //PC键盘数据长度计数
unsigned char input = 0; //缓冲区读指针
unsigned char k_buf[32]; //键盘缓冲区
//没有按下shift键的PC键盘扫描码
unsigned char code unshifted[][2]=
{28,'a',50,'b',33,'c',35,'d',36,'e',43,'f',52,'g',51,'h',67,'i',59,'j',
66,'k',75,'l',58,'m',49,'n',68,'o',77,'p',21,'q',45,'r',27,'s',44,'t',
60,'u',42,'v',29,'w',34,'x',53,'y',26,'z',69,'0',22,'1',30,'2',38,'3',
37,'4',46,'5',54,'6',61,'7',62,'8',70,'9',14,'`',78,'-',85,'=',
84,'[',91,']',76,';',65,',',73,'.',74,'/'};
//按下shift键的PC键盘扫描码
unsigned char code shifted[][2]=
{28,'A',50,'B',33,'C',35,'D',36,'E',43,'F',52,'G',51,'H',67,'I',59,'J',
66,'K',75,'L',58,'M',49,'N',68,'O',77,'P',21,'Q',45,'R',27,'S',44,'T',
60,'U',42,'V',29,'W',34,'X',53,'Y',26,'Z',69,')',22,'!',30,'@',38,'#',
37,'$',46,'%',54,'^',61,'&',62,'*',70,'(',14,'~',78,'_',85,'+',93,'|',
84,'{',91,'}',76,':',82,'"',65,'<',73,'>',74,'?'};
/*****************************************************************************
*函数名称:put_k_buf
*函数功能:将解码后的字符放入键盘缓冲区内
*入口参数:k_char
*出口参数:无
*****************************************************************************/
void put_k_buf(unsigned char k_char)
{
k_buf[input] = k_char; //送键盘值ASCII码到键盘缓冲区
if(input<31)
input++;
else
input = 0;
return;
}
/*****************************************************************************
*函数名称:decode
*函数功能:解码函数,将接收到的数据转化为其对应的字符
*入口参数:k_code
*出口参数:无
*****************************************************************************/
void decode(unsigned char k_code)
{
static unsigned char shift,up,shiftup;
unsigned i;
if(k_code==0xf0) //按键释放
{
up = 1;
return;
}
if(up==1) //shift键开关
{
up = 0;
if((k_code==0x12)|(k_code==0x59))
shift = 0;
return;
}
switch(k_code)
{
case 0x12: //检测左shift键
{
shift = 1;
shiftup = 1;
}
case 0x59: //检测右shift键
{
shift = 1;
shiftup = 1;
}
default:
{
if(shift==0) //找出没有按下shift键的字符码将其存日键盘缓冲区中
{
for(i=0;unshifted[i][0]!=k_code&&unshifted[i][0];i++);
if(unshifted[i][0]==k_code)
put_k_buf(unshifted[i][1]);
}
else //找出按下shift键的字符码将其存日键盘缓冲区中
{
for(i=0;shifted[i][0]!=k_code&&shifted[i][0];i++);
if(shifted[i][0]==k_code)
put_k_buf(shifted[i][1]);
}
}
}
}
/*****************************************************************************
*函数名称:Keyboard_out
*函数功能:中断函数接受键盘发来的数据
*入口参数:无
*出口参数:无
*****************************************************************************/
void Keyboard_out(void) interrupt 0 using 0
{
static unsigned char dat;
switch(bitcount)
{
case 11: //接收起始位
{
if(k_data ) //若数据线为高则返回
return ;
else //若数据线为低则bitcount减1准备接收数据
bitcount--;
break;
}
case 2: //奇校验位
{
bitcount--;
break;
}
case 1: //停止位
{
bitcount--;
if(!k_data ) //若数据线为0,则主机禁止接收放弃数据
{
bitcount = 11;
return;
}
else //若数据线为1,则接受停止位
{
bitcount = 11;
decode(dat); //将数据进行解码
}
break;
}
default: //通过移位保存接收的8位数据
{
dat = (dat>>1);
if(k_data )
dat|=0x80;
bitcount--;
}
}
}
/*****************************************************************************
*函数名称:delayns
*函数功能:LCD延时子程序
*入口参数:time
*出口参数:无
*****************************************************************************/
void delayns(unsigned char time)
{
unsigned char i;
for(;time>0;time--)
for(i = 0; i< 250; i++) ;
}
/*****************************************************************************
*函数名称:lcd_buzy
*函数功能:测试LCD忙碌状态
*入口参数:无
*出口参数:result
*****************************************************************************/
bit lcd_buzy()
{
bit result;
RS = 0;
RW = 1;
EP = 1;
delayns(1); //此处延时特别重要 (必不可少)
result = (bit)(DATA & 0x80);
delayns(1);
EP = 0;
return result;
}
/*****************************************************************************
*函数名称:lcd_w_order
*函数功能:写指令数据到LCD子程序
*入口参数:cmd
*出口参数:无
*****************************************************************************/
void lcd_w_order(unsigned char cmd)
{
while(lcd_buzy()); //判断LCD是否忙碌
RS = 0;
RW = 0;
EP = 1;
DATA = cmd;
delayns(1);
EP = 0;
}
/*****************************************************************************
*函数名称:lcd_w_data
*函数功能:写入显示数据到LCD子程序
*入口参数:dat
*出口参数:五
*****************************************************************************/
void lcd_w_data(unsigned char dat)
{
while(lcd_buzy()); //判断LCD是否忙碌
RS = 1;
RW = 0;
EP = 1;
DATA = dat;
delayns(1);
EP = 0;
}
/*****************************************************************************
*函数名称:lcd_post
*函数功能:设定显示位置子程序
*入口参数:pos
*出口参数:无
*****************************************************************************/
void lcd_post(unsigned char pos)
{
lcd_w_order(pos | 0x80);
}
/*****************************************************************************
*函数名称:lcd_init
*函数功能:LCD初始化子程序
*入口参数:无
*出口参数:无
*****************************************************************************/
void lcd_init()
{
lcd_w_order(0x38); //显示模式设置
delayns(1);
lcd_w_order(0x0c); //显示光标设置,开显示
delayns(1);
lcd_w_order(0x06); //显示光标移动(右移)
delayns(1);
lcd_w_order(0x01); //清屏
delayns(1);
}
/*****************************************************************************
*函数名称:main
*函数功能:本程序主要通过外部中断INT0及3.3端口读取PS2键盘值并通过LCD1602显示,键
*扫描码的解码通过数组方式解码,程序的解码功能主要针对数字及大小写字母和常用标点
*符号
*入口参数:无
*出口参数:无
*****************************************************************************/
void main()
{
unsigned char j,i=0;
EA = 1;
IT0 = 1;
EX0 = 1;
while(1)
{
i=0;
lcd_init(); // 初始化LCD
delayns(10);
lcd_post(0x00); //设置显示位置
while(i<input)
{
lcd_w_data(k_buf[i]); //显示字符
i++;
if(i==16)
{
lcd_post(0x40); // 设置显示位置
}
}
for (j=0;j<20;j++)
delayns(200);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -