<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 使用1602液晶顯示和PS/2鍵盤的示例

          使用1602液晶顯示和PS/2鍵盤的示例

          作者: 時間:2016-11-22 來源:網絡 收藏
          //*============================================================

          使用1602液晶顯示和PS/2鍵盤的示例
          -------------------------------------------------

          ==============================================================

          本文引用地址:http://www.ex-cimer.com/article/201611/319616.htm

          SMC1602A(16*2)模擬口線接線方式
          連接線圖:
          ---------------------------------------------------
          |LCM-----51 | LCM-----51 | LCM------51 |
          --------------------------------------------------|
          |DB0-----P1.0 | DB4-----P1.4 | RW-------P2.1 |
          |DB1-----P1.1 | DB5-----P1.5 | RS-------P2.0 |
          |DB2-----P1.2 | DB6-----P1.6 | E--------P2.2 |
          |DB3-----P1.3 | DB7-----P1.7 | VLCD接1K電阻到GND|
          ---------------------------------------------------

          Keyboard接線
          PS/2--------51
          1 DATA------P3.4
          3 GND
          4 VCC
          5 CLK-------P3.3 接在51的外部中斷,觸發(fā)方式為低電平


          [注:AT89x51使用12M或11.0592M晶振,實測使用11.059M
          [Keil uV2 7.01編譯運行通過程序中沒有做鍵盤數(shù)據的奇偶校驗]

          =============================================================*
          #include
          #include "scancodes.h"

          #define LCM_RW P2_1 //定義LCD引腳
          #define LCM_RS P2_0
          #define LCM_E P2_2
          #define LCM_Data P0

          #define Key_Data P3_4 //定義Keyboard引腳
          #define Key_CLK P3_3

          #define Busy 0x80 //用于檢測LCM狀態(tài)字中的Busy標識

          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.pp51.com "};
          unsigned char code email[] = {"pp51com@163.com"};
          unsigned char code Cls[] = {" "};
          static unsigned char IntNum = 0; //中斷次數(shù)計數(shù)
          static unsigned char KeyV; //鍵值
          static unsigned char DisNum = 0; //顯示用指針
          static unsigned char Key_UP=0, Shift = 0;//Key_UP是鍵松開標識,Shift是Shift鍵按下標識
          static unsigned char BF = 0; //標識是否有字符被收到

          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; //設外部中斷1為低電平觸發(fā)
          EA = 1;
          EX1 = 1; //開中斷

          do
          {
          if (BF)
          Decode(KeyV);
          else
          EA = 1; //開中斷
          }
          while(1);
          }

          //寫數(shù)據
          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(); //根據需要檢測忙
          LCM_Data = WCLCM;
          LCM_RS = 0;
          LCM_RW = 0;
          LCM_E = 0;
          LCM_E = 0;
          LCM_E = 1;
          }

          //讀數(shù)據
          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); //三次顯示模式設置,不檢測忙信號
          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(unsigned char X, unsigned char Y, unsigned char DData)
          {
          Y &= 0x1;
          X &= 0xF; //限制X不能大于15,Y不能大于1
          if (Y) X |= 0x40; //當要顯示第二行時地址碼+0x40;
          X |= 0x80; //算出指令碼
          WriteCommandLCM(X, 1); //發(fā)命令字
          WriteDataLCM(DData); //發(fā)數(shù)據
          }

          //按指定位置顯示一串字符
          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) //若到達字串尾則退出
          {
          if (X <= 0xF) //X坐標應小于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ù)據是低>>高,結合上一句所以右移一位
          if (Key_Data) KeyV = KeyV | 0x80; //當鍵盤數(shù)據線為1時為1到最高位
          }
          IntNum++;
          while (!Key_CLK); //等待PS/2CLK拉高

          if (IntNum > 10)
          {
          IntNum = 0; //當中斷11次后表示一幀數(shù)據收完,清變量準備下一次接收
          BF = 1; //標識有字符輸入完了
          EA = 0; //關中斷等顯示完后再開中斷 (注:如這里不用BF和關中斷直接調Decode()則所Decode中所調用的所有函數(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) //當鍵盤松開時
          {
          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 (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) //當鍵松開時不處理判碼,如G 34H F0H 34H 那么第二個34H不會被處理
          {
          case 0x12 : // 左 SHIFT
          Shift = 0;
          break;

          case 0x59 : // 右 SHIFT
          Shift = 0;
          break;
          }
          }
          BF = 0; //標識字符處理完了
          }



          評論


          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();