这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » STC51单片机实例之42PS2键盘实验

共1条 1/1 1 跳转至

STC51单片机实例之42PS2键盘实验

高工
2014-09-13 22:42:18     打赏
/********************************************************************
* 描述    :  这个程序用来做PS2键盘的实验。
             按下键盘相应的键,会在1602上的第一行有相应的显示。			 

***********************************************************************/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include "delay.h"
#include "1602.h"
#include "ps2.h"

void main(void)
{


 LCD_Init();
 DelayMs(10);
 LCD_Clear();
 PS2_Init();
 LCD_Write_String(0,0," keyboard test ");
 LCD_Write_String(0,1,"press the key! ");
 

 while(1)
 {
  Read_KeyBoard(); //读取键盘值,循环显示到液晶
 }
}

 

/********************************************************************
* 描述    :  1602液晶显示驱动函数

***********************************************************************/
#include "1602.h"
#include "delay.h"

#define CHECK_BUSY

sbit RS = P2^5;   //定义端口 
sbit RW = P2^6;
sbit EN = P2^7;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
 bit LCD_Check_Busy(void) 
 { 
#ifdef CHECK_BUSY
 DataPort= 0xFF; 
 RS_CLR; 
 RW_SET; 
 EN_CLR; 
 _nop_(); 
 EN_SET;
 return (bit)(DataPort & 0x80);
#else
 return 0;
#endif
 }
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
 void LCD_Write_Com(unsigned char com) 
 {  
 while(LCD_Check_Busy()); //忙则等待
 RS_CLR; 
 RW_CLR; 
 EN_SET; 
 DataPort= com; 
 _nop_(); 
 EN_CLR;
 }
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
 void LCD_Write_Data(unsigned char Data) 
 { 
 while(LCD_Check_Busy()); //忙则等待
 RS_SET; 
 RW_CLR; 
 EN_SET; 
 DataPort= Data; 
 _nop_();
 EN_CLR;
 }

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
 void LCD_Clear(void) 
 { 
 LCD_Write_Com(0x01); 
 DelayMs(5);
 }
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
 {     
 if (y == 0) 
 	{     
	 LCD_Write_Com(0x80 + x);     //表示第一行
 	}
 else 
 	{      
 	LCD_Write_Com(0xC0 + x);      //表示第二行
 	}        
 while (*s) 
 	{     
 LCD_Write_Data( *s);     
 s ++;     
 	}
 }
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
 {     
 if (y == 0) 
 	{     
 	LCD_Write_Com(0x80 + x);     
 	}    
 else 
 	{     
 	LCD_Write_Com(0xC0 + x);     
 	}        
 LCD_Write_Data( Data);  
 }
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
 void LCD_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);    /*显示开及光标设置*/
   }
   

 

/*-----------------------------------------------
  名称:LCD1602.h
  论坛:www.doflye.net
  编写:shifang
  日期:2009.5
  修改:无
  内容:
  引脚定义如下:1-VSS 2-VDD 3-V0 4-RS 5-R/W 6-E 7-14 DB0-DB7 15-BLA 16-BLK
------------------------------------------------*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>

#ifndef __1602_H__
#define __1602_H__


 bit LCD_Check_Busy(void) ;

 void LCD_Write_Com(unsigned char com) ;

 void LCD_Write_Data(unsigned char Data) ;

 void LCD_Clear(void) ;

 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) ;

 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) ;

 void LCD_Init(void) ;
   
#endif

 

#include "delay.h"
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
 while(--t);
}
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
 while(t--)
 {
     //大致延时1mS
     DelayUs2x(245);
	 DelayUs2x(245);
 }
}

 

#ifndef __DELAY_H__
#define __DELAY_H__
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t);
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t);

#endif

 

/*-----------------------------------------------
说明:此程序使用标准PS2键盘输入,LCD1602液晶屏输出显示。此样例仅作测试使用
晶振使用12M或者11.0592M,本键盘使用部分字母和数字测试,其他按键不能使用,用
户可以自行扩展。由于开发板和程序的各种参数,程序中没有使用奇偶校验,不保证没有
误码,校验程序请自行添加。
-------------------------------------------------*/
//由于PS2接口我们固定在P1.6和P1.7
//所以使用的时候,需要把P1.6引脚和P3.2引脚连接,P1.7引脚和P3.3引脚连接

#include<reg52.h>        //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include "scancodes.h"
#include "ps2.h"
#include "1602.h"

sbit Key_Data = P3^3 ;   	//定义Keyboard引脚
sbit Key_CLK  = P3^2;      //使用中断

bit BF=0;          
bit Shift;               //定义上档键标志
bit Key_UP;              //定义通码断码标志
unsigned char KeyV;
unsigned char IntNum;
unsigned char DisNum;
/*-----------------------------------------------
              外部中断读入信息
-----------------------------------------------*/
void Keyboard_out(void) interrupt 0
{
if ((IntNum > 0) && (IntNum < 9))
   { 
	KeyV = KeyV >> 1;                //因键盘数据是低>>高,结合上一句所以右移一位
	if (Key_Data)
    	KeyV = KeyV | 0x80;          //当键盘数据线为1时到最高位
	}
	IntNum++;
	while (!Key_CLK);                //等待PS/2CLK拉高

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

/*-----------------------------------------------
                解码信息
注意:如SHIFT+G为12H 34H F0H 34H F0H 12H
也就是说shift的通码+G的通码+shift的断码+G的断码
-----------------------------------------------*/
void Decode(unsigned char ScanCode) //
{
unsigned char TempCyc,Val; 
if (!Key_UP)                        //当键盘按下时
	{
	switch (ScanCode)
			{
			case 0xF0 :             // 当收到0xF0,Key_UP置1表示断码开始
				Key_UP = 1;
				break;

			case 0x12 :             // 左 SHIFT
				Shift = 1;
				break;

			case 0x59 :             // 右 SHIFT
				Shift = 1;
				break;

			default: 
				if(!Shift)          //如果SHIFT没按下
					{
					for (TempCyc = 0;(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表显示
					if (UnShifted[TempCyc][0] == ScanCode)
						{
   						Val= UnShifted[TempCyc][1];
						LCD_Write_Char(DisNum%16,DisNum/16,Val);
						DisNum++;
   						if(DisNum==33)
     					  {
	  					  LCD_Clear(); //清屏
	  					  DisNum=0;    //重头写数据
	 				      }
 					     }
                     } 
				else //按下SHIFT
                    {
					for(TempCyc = 0; (Shifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表显示
					if (Shifted[TempCyc][0] == ScanCode)
                       {
  						Val= Shifted[TempCyc][1];
                        LCD_Write_Char(DisNum%16,DisNum/16,Val);
						DisNum++;
   						if(DisNum==33)
     					  {
	  					  LCD_Clear(); //清屏
	  					  DisNum=0;    //重头写数据
	 				      }
  						}
                      }
					break;
 			}
	}
else
	{ 
	Key_UP = 0;
	switch (ScanCode) //当键松开时不处理判码,如G 34H F0H 34H 那么第二个34H不会被处理
			{
			case 0x12 : // 左 SHIFT
				Shift = 0;
				break;

			case 0x59 : // 右 SHIFT
				Shift = 0;
				break;
			}
	}
BF = 0; //标识字符处理完了

} 

/*-----------------------------------------------
     ps2初始化(实际初始化外部中断)
-----------------------------------------------*/
void PS2_Init(void)
{
 IT1 = 0;                              //设外部中断1为低电平触发
 EA = 1;                               //外部中断开
 EX0 = 1;                              //开中断
}
/*-----------------------------------------------
                   读取键盘值
-----------------------------------------------*/
void Read_KeyBoard(void)
{

 if (BF)
   Decode(KeyV);
 else
   EA = 1; //开中断
}

 

#ifndef __PS2_H__
#define __PS2_H__


#include<reg52.h>        //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义


void PS2_Init(void);

void Read_KeyBoard(void);

void Decode(unsigned char ScanCode);

#endif

 

#ifndef __SCANCODES_H__
#define __SCANCODES_H__
unsigned char code UnShifted[59][2] = {
0x1C, 'a',
0x32, 'b',
0x21, 'c',
0x23, 'd',
0x24, 'e',
0x2B, 'f',
0x34, 'g',
0x33, 'h',
0x43, 'i',
0x3B, 'j',
0x42, 'k',
0x4B, 'l',
0x3A, 'm',
0x31, 'n',
0x44, 'o',
0x4D, 'p',
0x15, 'q',
0x2D, 'r',
0x1B, 's',
0x2C, 't',
0x3C, 'u',
0x2A, 'v',
0x1D, 'w',
0x22, 'x',
0x35, 'y',
0x1A, 'z',
0x45, '0',
0x16, '1',
0x1E, '2',
0x26, '3',
0x25, '4',
0x2E, '5',
0x36, '6',
0x3D, '7',
0x3E, '8',
0x46, '9',
0x0E, '`',
0x4E, '-',
0x55, '=',
0x5D, '\\',
0x29, ' ',
0x54, '[',
0x5B, ']',
0x4C, ';',
0x52, '\'',
0x41, ',',
0x49, '.',
0x4A, '/',
0x71, '.',
0x70, '0',
0x69, '1',
0x72, '2',
0x7A, '3',
0x6B, '4',
0x73, '5',
0x74, '6',
0x6C, '7',
0x75, '8',
0x7D, '9',
};

unsigned char code Shifted[59][2] = {
0x1C, 'A',
0x32, 'B',
0x21, 'C',
0x23, 'D',
0x24, 'E',
0x2B, 'F',
0x34, 'G',
0x33, 'H',
0x43, 'I',
0x3B, 'J',
0x42, 'K',
0x4B, 'L',
0x3A, 'M',
0x31, 'N',
0x44, 'O',
0x4D, 'P',
0x15, 'Q',
0x2D, 'R',
0x1B, 'S',
0x2C, 'T',
0x3C, 'U',
0x2A, 'V',
0x1D, 'W',
0x22, 'X',
0x35, 'Y',
0x1A, 'Z',
0x45, '0',
0x16, '1',
0x1E, '2',
0x26, '3',
0x25, '4',
0x2E, '5',
0x36, '6',
0x3D, '7',
0x3E, '8',
0x46, '9',
0x0E, '~',
0x4E, '_',
0x55, '+',
0x5D, '|',
0x29, ' ',
0x54, '{',
0x5B, '}',
0x4C, ':',
0x52, '"',
0x41, '<',
0x49, '>',
0x4A, '?',
0x71, '.',
0x70, '0',
0x69, '1',
0x72, '2',
0x7A, '3',
0x6B, '4',
0x73, '5',
0x74, '6',
0x6C, '7',
0x75, '8',
0x7D, '9',
};

#endif

 


共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]