/******************************************************************** * 描述 : 这个程序用来做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