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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應用 > 51單片機模擬PS2協(xié)議制作5X5矩陣工業(yè)鍵盤

          51單片機模擬PS2協(xié)議制作5X5矩陣工業(yè)鍵盤

          作者: 時間:2016-11-23 來源:網(wǎng)絡 收藏
          根據(jù)客戶的要求利用單片機制作一個小的工控鍵盤,將下面對應的鍵值發(fā)送到電腦顯示,利用的協(xié)議就是PS2,單片機型號為stc89c52rc,晶振為12M;
             10
          65432
          789減號等號
          yuiop
          qwert


          #include
          #include "PS2.H"

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

          BYTE PS2RecChar=0xCC;
          BOOL KeyBoardFlag=FALSE;
          #define Key_line P0//鍵盤行入口
          #define Key_list P2//鍵盤列入口

          #define PS2_1 0 //16
          #define PS2_0 1 //45
          #define PS2_6 2//36
          #define PS2_5 3 //2e
          #define PS2_4 4 //25
          #define PS2_3 5 //26
          #define PS2_2 6 //1e
          #define PS2_7 7 //3d
          #define PS2_8 8 //3e
          #define PS2_9 9 //46
          #define PS2_dec 10 //4e
          #define PS2_eq 11 //55
          #define PS2_y 12 //35
          #define PS2_u 13//3c
          #define PS2_i 14 //43
          #define PS2_o 15 //44
          #define PS2_p 16//4d
          #define PS2_q 17 //15
          #define PS2_w 18//1d
          #define PS2_e 19 //24
          #define PS2_r 20 //2d
          #define PS2_t 21 //2c

          //第二套鍵盤碼

          unsigned char PS2Value[22]={0x16,0x45,0x36,0x2e,0x25,0x26,0x1e,0x3d,0x3e,0x46,0x4e,0x55,0x35,0x3c,
          0x43,0x44,0x4d,0x15,0x1d,0x24,0x2d,0x2c};

          unsigned char Key_Press(void)
          {
          unsigned temp3;
          unsigned char flag=0; //設(shè)定標志位
          Key_line=0xe0; //將P0口低5位全部設(shè)置位0
          temp3=Key_list; //讀取P2口的狀態(tài),若果P2口的值temp3:(temp3&0xff)!=0xff成立,表示有鍵按下
          if(((temp3&0xff)!=0xff)) //有鍵按下條件判斷
          {
          flag=1;
          //Key_line=0XFF; //清零鍵盤行端口
          Key_list=0xff; //清零鍵盤列端口
          }
          else
          flag=0; //無鍵按下標志
          return flag;
          }
          void delay(unsigned int ms)
          {
          unsigned int i,j;
          for(i=ms;i>0;i--)
          for(j=100;j>0;j--);
          }

          unsigned char Key_Scan(void)
          {
          unsigned char temp2=0,temp3=0; //temp2用來保存行鍵盤數(shù)據(jù),temp3保存列鍵盤數(shù)據(jù)
          unsigned char temp=0,flag=0; //函數(shù)返回值temp
          unsigned char i=0,key=0; //i位循環(huán)控制變量,給行送數(shù)據(jù),key保存檢測鍵盤按下的標志位
          if((key=Key_Press())!=0) //判斷是否有鍵按下
          {
          delay(30);
          if((key=Key_Press())!=0)
          {
          for(i=0x01;i!=0x20;i=i<<1) //循環(huán)控制變量,掃描5行
          {
          Key_line=(~i); //將循環(huán)控制變量賦值行地址
          temp2 =(~i); //保存行地址
          //temp2=Key_line;
          temp3=Key_list;//讀取列地址數(shù)據(jù)
          switch((temp3&0xff))//判斷是那列有鍵按下
          {
          case 0xfe://第一列有鍵按下
          switch((temp2&0xff)) //判斷第一列有鍵按下時,對應的行按鍵
          {
          case 0xfe:
          temp=23; //第一行有鍵按下
          break; //該鍵無鍵盤號定義
          case 0xfd: //第二行有鍵按下
          temp=PS2_6;flag=1; //對應鍵值位PS2鍵盤的數(shù)字6,對應的鍵盤掃描碼為0x36
          break;
          case 0xfb: //第三行有鍵按下
          temp=PS2_7; flag=1;//對應鍵值位PS2鍵盤的數(shù)字7,對應的鍵盤掃描碼為0x3d
          break;
          case 0xf7: //第四行有鍵按下
          temp=PS2_y; flag=1; //對應鍵值位PS2鍵盤的字母y,對應的鍵盤掃描碼為0x35
          break;
          case 0xef: //第五行有鍵按下
          temp=PS2_q ;flag=1; //對應鍵值位PS2鍵盤的字母q,對應的鍵盤掃描碼為0x15
          break;
          }
          break;

          case 0xfd:
          switch((temp2&0xff)) // 第二列有鍵按下
          {
          case 0xfe: //第一行有鍵按下
          temp=23; //該鍵無鍵盤號定義
          break;
          case 0xfd: //第二行有鍵按下
          temp=PS2_5;flag=1; //對應鍵值位PS2鍵盤的數(shù)字5,對應的鍵盤掃描碼為0x2e
          break;
          case 0xfb: //第三行有鍵按下
          temp=PS2_8;flag=1; //對應鍵值位PS2鍵盤的數(shù)字8,對應的鍵盤掃描碼為0x8e
          break;
          case 0xf7: //第四行有鍵按下
          temp=PS2_u;flag=1; //對應鍵值位PS2鍵盤的字母u,對應的鍵盤掃描碼為0x3c
          break;
          case 0xef: //第五行有鍵按下
          temp=PS2_w ; flag=1; //對應鍵值位PS2鍵盤的字母w,對應的鍵盤掃描碼為0x1d
          break;
          }
          break;

          case 0xfb:
          switch((temp2&0xff)) // 第三列有鍵按下
          {
          case 0xfe: //第一行有鍵按下
          temp=23;//該鍵無鍵盤號定義
          break;
          case 0xfd: //第二行有鍵按下
          temp=PS2_4;flag=1;//對應鍵值位PS2鍵盤的數(shù)字4,對應的鍵盤掃描碼為0x25
          break;
          case 0xfb: //第三行有鍵按下
          temp=PS2_9;flag=1;//對應鍵值位PS2鍵盤的數(shù)字9,對應的鍵盤掃描碼為0x46
          break;
          case 0xf7: //第四行有鍵按下
          temp=PS2_i;flag=1;//對應鍵值位PS2鍵盤的字母i,對應的鍵盤掃描碼為0x43
          break;
          case 0xef: //第五行有鍵按下
          temp=PS2_e; flag=1; //對應鍵值位PS2鍵盤的字母e,對應的鍵盤掃描碼為0x24
          break;
          }
          break;

          case 0xf7:
          switch((temp2&0xff)) // 第四列有鍵按下
          {
          case 0xfe: //第一行有鍵按下
          temp=PS2_1;flag=1; //對應鍵值位PS2鍵盤的數(shù)字1,對應的鍵盤掃描碼為0x16
          break;
          case 0xfd: //第二行有鍵按下
          temp=PS2_3;flag=1; //對應鍵值位PS2鍵盤的數(shù)字3,對應的鍵盤掃描碼為0x26
          break;
          case 0xfb: //第三行有鍵按下
          temp=PS2_dec;flag=1; //對應鍵值位PS2鍵盤的減號,對應的鍵盤掃描碼為0x4e
          break;
          case 0xf7: //第四行有鍵按下
          temp=PS2_o;flag=1; //對應鍵值位PS2鍵盤的字母o,對應的鍵盤掃描碼為0x44
          break;
          case 0xef: //第五行有鍵按下
          temp=PS2_r; flag=1; //對應鍵值位PS2鍵盤的字母r,對應的鍵盤掃描碼為0x2d
          break;
          }
          break;

          case 0xef:
          switch((temp2&0xff)) // 第五列有鍵按下
          {
          case 0xfe: //第一行有鍵按下
          temp=PS2_0;flag=1;//對應鍵值位PS2鍵盤的數(shù)字0,對應的鍵盤掃描碼為0x45
          break;
          case 0xfd: //第二行有鍵按下
          temp=PS2_2;flag=1; //對應鍵值位PS2鍵盤的數(shù)字2,對應的鍵盤掃描碼為0x1e
          break;
          case 0xfb: //第三行有鍵按下
          temp=PS2_eq;flag=1; //對應鍵值位PS2鍵盤的等號,對應的鍵盤掃描碼為0x55
          break;
          case 0xf7: //第四行有鍵按下
          temp=PS2_p;flag=1; //對應鍵值位PS2鍵盤的字母p,對應的鍵盤掃描碼為0x4d
          break;
          case 0xef: //第五行有鍵按下
          temp=PS2_t;flag=1; //對應鍵值位PS2鍵盤的字母t,對應的鍵盤掃描碼為0x2c
          break;
          }
          break;
          }
          //P0=0XFF; //每當檢測完一行時清零行端口和列端口
          //P2=0xff;
          if((key=Key_Press())!=0);
          delay(30);
          }
          }
          }
          else temp=23; //無鍵按下返回數(shù)字23,對應數(shù)組內(nèi)的0;
          if(flag==1)
          return temp;//返回按鍵掃描值
          else
          return 23;
          }
          void OnKeyBoardOnline(BOOL i)
          {
          KeyBoardFlag=i;
          }
          //---------------------------------------------------------------------------
          void OnPS2ReceiveChar(BYTE ReceChar,BOOL P)
          {
          BOOL ParityBit=0;
          ACC=ReceChar;
          CY=P;
          ParityBit=(BOOL)(CY?0x00:0x80);//奇校驗位
          if(P==ParityBit);
          PS2RecChar=ReceChar;
          }
          //---------------------------------------------------------------------------
          void OnPS2SendChar(BYTE dat)
          {
          BOOL ParityBit;
          BYTE i;
          ACC=dat;
          CY=P;
          ParityBit=(BOOL)(CY?0x00:0x80);//奇校驗位

          CLSSIGNAL();

          CT_KB=OFF;
          EX0=0;

          H_DATA=0;Delay10us();//start bit
          H_CLK=1;
          Delay10us();
          H_CLK=0;
          Delay30us();

          for(i=0;i<8;i++)
          {
          if(dat&0x01==0x01){H_DATA=1;Delay10us();}
          else {H_DATA=0;Delay10us();}
          dat>>=1;
          H_CLK=1;
          Delay10us();
          H_CLK=0;
          Delay30us();
          }

          H_DATA=ParityBit;Delay10us();//parity bit
          H_CLK=1;
          Delay10us();
          H_CLK=0;
          Delay30us();

          H_DATA=1;Delay10us();//stop bit
          H_CLK=1;
          Delay10us();
          H_CLK=0;
          Delay30us();

          IE0=0;
          EX0=1;
          H_CLK=1;
          H_DATA=1;
          CT_KB=ON;
          Delay30us();
          }
          //---------------------------------------------------------------------------
          void ExternInterrupt0(void) interrupt 0
          {
          BOOL ParityBit=0,CLKFlag=1;
          BYTE i=0,j=8,dat=0x00;

          EX0=0;

          while(CLKFlag)
          {
          i++;
          if(H_CLK==1)CLKFlag=0;
          if(i>0xEE)
          {
          IE0=0;
          EX0=1;
          return ;
          }
          }
          while(j--)//延時等待大鍵盤的動作
          {
          for(i=0;i<0x88;i++)//檢查是否有數(shù)據(jù)處理0x88
          {
          if(H_CLK==0)//有動作則是大鍵盤存在
          {
          OnKeyBoardOnline(TRUE);//大鍵盤存在,開機由大鍵盤應答
          IE0=0;
          EX0=1;
          return ;//存在的話置標志位,并返回
          }
          }
          }
          OnKeyBoardOnline(FALSE);//大鍵盤不存在,由小鍵盤應答

          //轉(zhuǎn)到接收
          for(i=0;i<8;i++)//read 8bit
          {
          Delay30us();
          H_CLK=0;
          Delay30us();
          H_CLK=1;
          dat=dat>>1;
          if(H_DATA)dat|=0x80;

          if(H_CLK==0){return;}//如果時鐘被拉低,則有錯誤發(fā)生
          }

          Delay30us();
          H_CLK=0;
          Delay30us();
          H_CLK=1;
          if(H_DATA)ParityBit=1;
          else ParityBit=0;

          Delay30us();
          H_CLK=0;
          Delay30us();
          H_CLK=1;//STOP BIT H_DATA 0 ERR

          Delay10us();
          H_DATA=0;//ACK bit
          Delay10us();
          H_CLK=0;
          Delay30us();Delay30us();
          H_CLK=1;
          Delay30us();
          H_DATA=1;

          OnPS2ReceiveChar(dat,ParityBit);

          IE0=0;
          EX0=1;
          return ;
          }
          //---------------------------------------------------------------------------
          void ProcessPS2(void)
          {
          if(KeyBoardFlag==FALSE)//大鍵盤不存在
          {
          if(PS2RecChar==0xF3)//1
          {
          OnPS2SendChar(0xFA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0x00)//11
          {
          OnPS2SendChar(0xFA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0x02)//111
          {
          OnPS2SendChar(0xFA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0x20)//1111
          {
          OnPS2SendChar(0xFA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xED)//2
          {
          OnPS2SendChar(0xFA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xF0)//3
          {
          OnPS2SendChar(0xFA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xF2)//4
          {
          OnPS2SendChar(0xFA);
          Delay30us();
          OnPS2SendChar(0xAB);
          Delay30us();
          OnPS2SendChar(0x83);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xEF)//5
          {
          OnPS2SendChar(0xFA);
          Delay30us();
          OnPS2SendChar(0xBF);
          Delay30us();
          OnPS2SendChar(0xB0);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xF3)//6
          {
          OnPS2SendChar(0xFA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xFE)//7 //resend
          {
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xEE)//8
          {
          OnPS2SendChar(0xEE);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xEE)//9
          {
          OnPS2SendChar(0xEE);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xF1)//10
          {
          OnPS2SendChar(0xFA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xF4)//11
          {
          OnPS2SendChar(0xFA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xAA)//12
          {
          OnPS2SendChar(0xAA);
          PS2RecChar=0xCC;
          }
          else if(PS2RecChar==0xFF)//13
          {
          OnPS2SendChar(0xFA);
          Delay30us();
          OnPS2SendChar(0xAA);
          Delay30us();
          PS2RecChar=0xCC;
          }
          else ;
          }
          }
          //---------------------------------------------------------------------------
          void PS2Init(void)
          {
          IT0=0;//低電平觸發(fā)中斷
          PX0=1;
          EX0=1;
          }
          //---------------------------------------------------------------------------

          extern void ProcessPS2(void);
          extern void PS2Init(void);
          void main(void)
          {
          unsigned char tem;
          PS2Init();
          ProcessPS2();
          while(1)
          {
          tem=Key_Scan();
          switch(tem&0xff)
          {
          case 23 :
          break;
          default:
          {
          OnPS2SendChar(PS2Value[tem]);
          }
          break;
          }
          //開機應答,使電腦能識別到鍵盤
          //other code
          }
          }
          仿真矩陣鍵盤電路圖,該電路未連接PS2,但可通過LED燈觀察每個按鍵按下之后的鍵值返回知否和第二套鍵盤碼對應一致


          第二套鍵值碼對應表:




          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁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); })();