|
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è)用途,如有需要請(qǐng)聯(lián)系作者。 [注:AT89x51使用12M或11.0592M晶振,實(shí)測(cè)使用11.0592M]
[Keil uV2 7.01編譯運(yùn)行通過(guò) 程序中沒(méi)有做鍵盤數(shù)據(jù)的奇偶校驗(yàn)] [站長(zhǎng)在AT89S51+12M晶振+JHD 162A液晶上調(diào)試通過(guò)] =============================================================*/
#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//用于檢測(cè)LCM狀態(tài)字中的Busy標(biāo)識(shí) 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)識(shí),Shift是Shift鍵按下標(biāo)識(shí) static unsigned char BF = 0;//標(biāo)識(shí)是否有字符被收到 void main(void) { unsigned char TempCyc; Delay400Ms();//啟動(dòng)等待,等LCM講入工作狀態(tài) LCMInit();//LCM初始化 Delay5Ms();//延時(shí)片刻(可不要) DisplayListChar(0, 0, cdle_net); DisplayListChar(0, 1, email); ReadDataLCM();//測(cè)試用句無(wú)意義 for (TempCyc=0; TempCyc<10; TempCyc++) Delay400Ms();//延時(shí) 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();//檢測(cè)忙 LCM_Data = WDLCM; LCM_RS = 1; LCM_RW = 0; LCM_E = 0;//若晶振速度太高可以在這后加小的延時(shí) LCM_E = 0;//延時(shí) LCM_E = 1; } //寫指令 void WriteCommandLCM(unsigned char WCLCM,BuysC)//BuysC為0時(shí)忽略忙檢測(cè) { if (BuysC) ReadStatusLCM();//根據(jù)需要檢測(cè)忙 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);//檢測(cè)忙信號(hào) return(LCM_Data); } void LCMInit(void)//LCM初始化 { LCM_Data = 0; WriteCommandLCM(0x38,0);//三次顯示模式設(shè)置,不檢測(cè)忙信號(hào) Delay5Ms(); WriteCommandLCM(0x38,0); Delay5Ms(); WriteCommandLCM(0x38,0); Delay5Ms(); WriteCommandLCM(0x38,1);//顯示模式設(shè)置,開始要求每次檢測(cè)忙信號(hào) WriteCommandLCM(0x08,1);//關(guān)閉顯示 WriteCommandLCM(0x01,1);//顯示清屏 WriteCommandLCM(0x06,1);// 顯示光標(biāo)移動(dòng)設(shè)置 WriteCommandLCM(0x0F,1);// 顯示開及光標(biāo)設(shè)置 } //按指定位置顯示一個(gè)字符 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)要顯示第二行時(shí)地址碼+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]);//顯示單個(gè)字符 ListLength++; X++; } } } //5ms延時(shí) void Delay5Ms(void) { unsigned int TempCyc = 5552; while(TempCyc--); } //400ms延時(shí) 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時(shí)為1到最高位 } IntNum++; while (!Key_CLK);//等待PS/2CLK拉高 if (IntNum > 10) { IntNum = 0;//當(dāng)中斷10次后表示一幀數(shù)據(jù)收完,清變量準(zhǔn)備下一次接收 BF = 1;//標(biāo)識(shí)有字符輸入完了 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,也就是說(shuō)shift的通碼+G的通碼+shift的斷碼+G的斷碼 { unsigned char TempCyc; if (!Key_UP)//當(dāng)鍵盤松開時(shí) { 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沒(méi)按下 { 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)鍵松開時(shí)不處理判碼,如G 34H F0H 34H 那么第二個(gè)34H不會(huì)被處理 { case 0x12 :// 左 SHIFT Shift = 0; break; case 0x59 :// 右 SHIFT Shift = 0; break; } } BF = 0;//標(biāo)識(shí)字符處理完了 } 以下為 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', };
|