|
SMC1602A(16*2)模擬口線接線方式 連接線圖: ------------------------------------------------ |LCM-----51 | LCM-----51 | LCM------51 | |-------------|--------------|------------------| |DB0-----P1.0 | DB4-----P1.4 | RW-------P2.0 | |DB1-----P1.1 | DB5-----P1.5 | RS-------P2.1 | |DB2-----P1.2 | DB6-----P1.6 | E--------P2.2 | |DB3-----P1.3 | DB7-----P1.7 | VLCD接1K電阻到GND| ------------------------------------------------- PS/2的電氣特性如下(電腦端): 
Keyboard接線 PS/2--------51單片機(jī) 1 DATA------P3.4 2 不接 3 GND 4 VCC 5 CLK-------P3.3 接在51的外部中斷,觸發(fā)方式為低電平 6 不接 本程序源碼只供學(xué)習(xí)參考,不得應(yīng)用于商業(yè)用途,如有需要請聯(lián)系作者。 [注:AT89x51使用12M或11.0592M晶振,實(shí)測使用11.0592M] [Keil uV2 7.01編譯運(yùn)行通過 程序中沒有做鍵盤數(shù)據(jù)的奇偶校驗(yàn)] [站長在AT89S51+12M晶振+JHD 162A液晶上調(diào)試通過] 
=============================================================*/
#include "reg51.h"#include "scancodes.h"#define LCM_RW P2_0//定義LCD引腳#define LCM_RS P2_1#define LCM_E P2_2#define LCM_Data P1#define Key_Data P3_4//定義Keyboard引腳#define Key_CLK P3_3#define Busy 0x80//用于檢測LCM狀態(tài)字中的Busy標(biāo)識void LCMInit(void);void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);void Delay5Ms(void);void Delay400Ms(void);void Decode(unsigned char ScanCode);void WriteDataLCM(unsigned char WDLCM);void WriteCommandLCM(unsigned char WCLCM,BuysC);unsigned char ReadDataLCM(void);unsigned char ReadStatusLCM(void);unsigned char code cdle_net[] = {"www.cdle.net--"};unsigned char code email[] = {"pnzwzw@cdle.net"};unsigned char code Cls[] = {" "};static unsigned char IntNum = 0;//中斷次數(shù)計(jì)數(shù)static unsigned char KeyV;//鍵值static unsigned char DisNum = 0;//顯示用指針static unsigned char Key_UP=0, Shift = 0;//Key_UP是鍵松開標(biāo)識,Shift是Shift鍵按下標(biāo)識static unsigned char BF = 0;//標(biāo)識是否有字符被收到void main(void){ unsigned char TempCyc; Delay400Ms();//啟動等待,等LCM講入工作狀態(tài) LCMInit();//LCM初始化 Delay5Ms();//延時片刻(可不要) DisplayListChar(0, 0, cdle_net); DisplayListChar(0, 1, email); ReadDataLCM();//測試用句無意義 for (TempCyc=0; TempCyc<10; TempCyc++) Delay400Ms();//延時 DisplayListChar(0, 1, Cls); IT1 = 0;//設(shè)外部中斷1為低電平觸發(fā) EA = 1; EX1 = 1;//開中斷 do { if (BF) Decode(KeyV); else EA = 1;//開中斷 } while(1);}//寫數(shù)據(jù)void WriteDataLCM(unsigned char WDLCM){ ReadStatusLCM();//檢測忙 LCM_Data = WDLCM; LCM_RS = 1; LCM_RW = 0; LCM_E = 0;//若晶振速度太高可以在這后加小的延時 LCM_E = 0;//延時 LCM_E = 1;}//寫指令void WriteCommandLCM(unsigned char WCLCM,BuysC)//BuysC為0時忽略忙檢測{ if (BuysC) ReadStatusLCM();//根據(jù)需要檢測忙 LCM_Data = WCLCM; LCM_RS = 0; LCM_RW = 0; LCM_E = 0; LCM_E = 0; LCM_E = 1;}//讀數(shù)據(jù)unsigned char ReadDataLCM(void){ LCM_RS = 1; LCM_RW = 1; LCM_E = 0; LCM_E = 0; LCM_E = 1; return(LCM_Data);}//讀狀態(tài)unsigned char 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);//三次顯示模式設(shè)置,不檢測忙信號 Delay5Ms(); WriteCommandLCM(0x38,0); Delay5Ms(); WriteCommandLCM(0x38,0); Delay5Ms(); WriteCommandLCM(0x38,1);//顯示模式設(shè)置,開始要求每次檢測忙信號 WriteCommandLCM(0x08,1);//關(guān)閉顯示 WriteCommandLCM(0x01,1);//顯示清屏 WriteCommandLCM(0x06,1);// 顯示光標(biāo)移動設(shè)置 WriteCommandLCM(0x0F,1);// 顯示開及光標(biāo)設(shè)置}//按指定位置顯示一個字符void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData){ Y &= 0x1; X &= 0xF;//限制X不能大于15,Y不能大于1 if (Y) X |= 0x40;//當(dāng)要顯示第二行時地址碼+0x40; X |= 0x80;//算出指令碼 WriteCommandLCM(X, 1);//發(fā)命令字 WriteDataLCM(DData);//發(fā)數(shù)據(jù)}//按指定位置顯示一串字符void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData){ unsigned char ListLength; ListLength = 0; Y &= 0x1; X &= 0xF;//限制X不能大于15,Y不能大于1 while (DData[ListLength]>0x19)//若到達(dá)字串尾則退出 { if (X <= 0xF)//X坐標(biāo)應(yīng)小于0xF { DisplayOneChar(X, Y, DData[ListLength]);//顯示單個字符 ListLength++; X++; } }}//5ms延時void Delay5Ms(void){ unsigned int TempCyc = 5552; while(TempCyc--);}//400ms延時void Delay400Ms(void){ unsigned char TempCycA = 5; unsigned int TempCycB; while(TempCycA--) { TempCycB=7269; while(TempCycB--); };}void Keyboard_out(void) interrupt 2{ if ((IntNum > 0) && (IntNum < 9)) { KeyV = KeyV >> 1;//因鍵盤數(shù)據(jù)是低>>高,結(jié)合上一句所以右移一位 if (Key_Data) KeyV = KeyV | 0x80;//當(dāng)鍵盤數(shù)據(jù)線為1時為1到最高位 } IntNum++; while (!Key_CLK);//等待PS/2CLK拉高 if (IntNum > 10) { IntNum = 0;//當(dāng)中斷10次后表示一幀數(shù)據(jù)收完,清變量準(zhǔn)備下一次接收 BF = 1;//標(biāo)識有字符輸入完了 EA = 0;//關(guān)中斷等顯示完后再開中斷 (注:如這里不用BF和關(guān)中斷直接調(diào)Decode()則所Decode中所調(diào)用的所有函數(shù)要聲明為再入函數(shù)) }}void Decode(unsigned char ScanCode)//注意:如SHIFT+G為12H 34H F0H 34H F0H 12H,也就是說shift的通碼+G的通碼+shift的斷碼+G的斷碼{ unsigned char TempCyc; if (!Key_UP)//當(dāng)鍵盤松開時 { switch (ScanCode) { case 0xF0 :// 當(dāng)收到0xF0,Key_UP置1表示斷碼開始 Key_UP = 1; break; case 0x12 :// 左 SHIFT Shift = 1; break; case 0x59 :// 右 SHIFT Shift = 1; break; default: if (DisNum > 15) { DisplayListChar(0, 1, Cls);//清LCD第二行 DisNum = 0; } if(!Shift)//如果SHIFT沒按下 { for (TempCyc = 0;(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++);//查表顯示 if (UnShifted[TempCyc][0] == ScanCode) DisplayOneChar(DisNum, 1, UnShifted[TempCyc][1]); DisNum++; } else//按下SHIFT { for(TempCyc = 0; (Shifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++);//查表顯示 if (Shifted[TempCyc][0] == ScanCode) DisplayOneChar(DisNum, 1, Shifted[TempCyc][1]); DisNum++; } break; } } else { Key_UP = 0; switch (ScanCode)//當(dāng)鍵松開時不處理判碼,如G 34H F0H 34H 那么第二個34H不會被處理 { case 0x12 :// 左 SHIFT Shift = 0; break; case 0x59 :// 右 SHIFT Shift = 0; break; } } BF = 0;//標(biāo)識字符處理完了}以下為 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',}; |