⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2key.c

📁 单片机与PS2键盘相连的应用
💻 C
字号:
/*============================================================
        使用1602液晶显示和PS/2键盘    
        -------------------------------------------------

[程序中没有做键盘数据的奇偶校验]

=============================================================*/
#include <Reg51.h>
#include "scancodes.h"
#define uchar  unsigned  char
#define uint   unsigned  int
#define LCM_Data  P0 
sbit LCM_RW=P1^3;  //定义LCD引脚
sbit LCM_RS=P1^1; 
sbit LCM_E=P1^2; 
sbit Key_Data=P1^0;  //定义Keyboard引脚
sbit Key_CLK=P3^2; 

#define Busy    0x80  //用于检测LCM状态字中的Busy标识

void LCMInit(void);
void DisplayOneChar(uchar X, uchar Y, uchar DData);
void DisplayListChar(uchar X, uchar Y, uchar code *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void Decode(uchar ScanCode);
void WriteDataLCM(uchar WDLCM);
void WriteCommandLCM(uchar WCLCM,BuysC);

uchar ReadDataLCM(void);
uchar ReadStatusLCM(void);
uchar code cdle_net[] = {"--cug--"};
uchar code email[] = {"0628jun@163.com"};
uchar code Cls[] = {"                "};
static uchar IntNum = 0; //中断次数计数
static uchar KeyV; //键值
static uchar DisNum = 0; //显示用指针
static uchar Key_UP=0, Shift = 0;//Key_UP是键松开标识,Shift是Shift键按下标识
static uchar BF = 0; //标识是否有字符被收到

void main(void)
{
	uchar TempCyc;
	Delay400Ms(); //启动等待,等LCM讲入工作状态
	LCMInit(); //LCM初始化
	Delay5Ms(); //延时片刻(可不要)
	DisplayListChar(0, 0, cdle_net);
	DisplayListChar(0, 1, email);
	ReadDataLCM();//测试用句无意义
	for (TempCyc=0; TempCyc<10; TempCyc++)
	Delay400Ms(); //延时
	DisplayListChar(0, 1, Cls);	
	IT0 = 1;  //外部中断0位下降沿触发
	EA = 1;
	EX0 = 1; //开外部中断0
   	do
		{
			if (BF)
				Decode(KeyV);
			else
				EA = 1; //开中断
		}
	while(1);
}

//写数据
void WriteDataLCM(uchar WDLCM) 
{
	ReadStatusLCM(); //检测忙
	LCM_Data=WDLCM;
	LCM_RS=1;
	LCM_RW=0;
	LCM_E=0; //若晶振速度太高可以在这后加小的延时
	LCM_E=0; //延时
	LCM_E=1;
}

//写指令
void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测
{
	if (BuysC) ReadStatusLCM(); //根据需要检测忙
	LCM_Data = WCLCM;
	LCM_RS = 0;
	LCM_RW = 0;	
	LCM_E = 0;
	LCM_E = 0;
	LCM_E = 1;	
}

//读数据
uchar ReadDataLCM(void)
{
	LCM_RS = 1; 
	LCM_RW = 1;
	LCM_E = 0;
	LCM_E = 0;
	LCM_E = 1;
	return(LCM_Data);
}

//读状态
uchar ReadStatusLCM(void)
{
	LCM_Data=0xFF; 
	LCM_RS=0;
	LCM_RW=1;
	LCM_E=0;
	LCM_E=0;
	LCM_E=1;
	while(LCM_Data & Busy); //检测忙信号
	return(LCM_Data);
}

void LCMInit(void) //LCM初始化
{
	LCM_Data=0;
	WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
	Delay5Ms(); 
	WriteCommandLCM(0x38,0);
	Delay5Ms(); 
	WriteCommandLCM(0x38,0);
	Delay5Ms(); 

	WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
	WriteCommandLCM(0x08,1); //关闭显示
	WriteCommandLCM(0x01,1); //显示清屏
	WriteCommandLCM(0x06,1); // 显示光标移动设置
	WriteCommandLCM(0x0F,1); // 显示开及光标设置
}

//按指定位置显示一个字符
void DisplayOneChar(uchar X, uchar Y, uchar DData)
{
	Y &= 0x1;
	X &= 0xF; //限制X不能大于15,Y不能大于1
	if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
	X |= 0x80; //算出指令码
	WriteCommandLCM(X, 1); //发命令字
	WriteDataLCM(DData); //发数据
}

//按指定位置显示一串字符
void DisplayListChar(uchar X, uchar Y, uchar code *DData)
{
	uchar ListLength;

  ListLength = 0;
	Y &= 0x1;
	X &= 0xF; //限制X不能大于15,Y不能大于1
	while (DData[ListLength]>0x20) //若到达字串尾则退出
		{
			if (X <= 0xF) //X坐标应小于0xF
				{
					DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
					ListLength++;
					X++;
				}
		}
}

//5ms延时
void Delay5Ms(void)
{
	uint TempCyc = 5552;
	while(TempCyc--);
}

//400ms延时
void Delay400Ms(void)
{
	uchar TempCycA = 5;
	uint TempCycB;
	while(TempCycA--)
		{
			TempCycB=7269;
			while(TempCycB--);
		};
}
//由于没有做奇偶校验,所以键盘扫描码为10位,1位起始位,总是为0
//接下来是8位数据位,1位停止位,总是为1,最后为1位应答位
void Keyboard_out(void) interrupt 0
{
	if ((IntNum > 0) && (IntNum < 9))
		{			
			KeyV = KeyV >> 1; //因键盘数据是低>>高,所以右移一位
			if (Key_Data) KeyV = KeyV | 0x80; //当键盘数据线为1时为1到最高位
		}
	IntNum++;
	while (!Key_CLK); //等待PS/2CLK拉高

	if (IntNum > 10)
		{
			IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收
			BF = 1; //标识有字符输入完了
			EA = 0; //关中断等显示完后再开中断 
		}
}

void Decode(uchar ScanCode) //注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,也就是说shift的通码+G的通码+shift的断码+G的断码
{
 uchar TempCyc;	
  if (!Key_UP)                //当键盘松开时
   {
      if (ScanCode==0xF0) //接收到断码0xF0说明按键已经松开,因为大多数按键的断码都是0xF0开头
          Key_UP = 1;	        //按键松开后,不再显示
         if (DisNum > 15)
           {
             DisplayListChar(0, 1, Cls);//清LCD第二行
             DisNum = 0; 
           }											 
  for(TempCyc = 0; (Shifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表,寻找对应
           
	             if (UnShifted[TempCyc][0] == ScanCode)
	                {
	                     DisplayOneChar(DisNum, 1, UnShifted[TempCyc][1]); DisNum++;
	                }
	         
   }		
 BF = 0; //标识字符处理完了
} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -