<li id="8g3ty"><tbody id="8g3ty"><th id="8g3ty"></th></tbody></li>
    <label id="8g3ty"><samp id="8g3ty"></samp></label>
  • <span id="8g3ty"></span>

    1. <center id="8g3ty"><optgroup id="8g3ty"></optgroup></center>
    2. <bdo id="8g3ty"><meter id="8g3ty"><bdo id="8g3ty"></bdo></meter></bdo><center id="8g3ty"><optgroup id="8g3ty"></optgroup></center>
      <label id="8g3ty"><samp id="8g3ty"></samp></label>

    3. 電子開發(fā)網(wǎng)

      電子開發(fā)網(wǎng)電子設計 | 電子開發(fā)網(wǎng)Rss 2.0 會員中心 會員注冊
      搜索: 您現(xiàn)在的位置: 電子開發(fā)網(wǎng) >> 電子開發(fā) >> 單片機 >> 正文

      單片機系統(tǒng)中PS/2鍵盤驅(qū)動程序的設計

      作者:佚名    文章來源:本站原創(chuàng)    點擊數(shù):    更新時間:2008-10-31

          在單片機系統(tǒng)中,經(jīng)常使用的鍵盤都是專用鍵盤.此類鍵盤為單獨設計制作的,成本高、使用硬件連接線多,且可靠性不高,這一狀況在那些要求鍵盤按鍵較多的應用系統(tǒng)中更為突出.與此相比,在PC系統(tǒng)中廣泛使用PS/2鍵盤具有價格低、通用可靠,且使用連接線少(僅使用2根信號線)的特點,并可滿足多種系統(tǒng)的要求.因此在單片機系統(tǒng)中應用PS/2鍵盤是一種很好的選擇.
          文中在介紹PS/2協(xié)議和PS/2鍵盤工作原理與特點的基礎上,給出了一個在單片機上實現(xiàn)對PS/2鍵盤支持的硬件連接與驅(qū)動程序設計實現(xiàn).該
      設計實現(xiàn)了在單片機系統(tǒng)中對PS/2標準104鍵盤按鍵輸入的支持.使用Keil C51開發(fā)的驅(qū)動程序接口和庫函數(shù)可以方便地移植到其他單片機或嵌入式系統(tǒng)中.所有程序在Keil uVision2上編譯通過,在單片機AT89C51上測試通過.

      1 PS/2協(xié)議
      目前,PC機廣泛采用的PS/2接口為mini-DIN 6pin的連接器,如圖1所示.
      PS/2接口圖 
          PS/2設備有主從之分,主設備采用Female插座,從設備采用Male插頭.現(xiàn)在廣泛使用的PS/2鍵盤鼠標均在從設備方式下工作.PS/2接口的時鐘
      與數(shù)據(jù)線都是集電極開路結(jié)構,必須外接上拉電阻(一般上拉電阻設置在主設備中).主從設備之間數(shù)據(jù)通信采用雙向同步串行方式傳輸,時鐘信號由從設備產(chǎn)生.

      1.1 從設備到主設備的通信
          當從設備向主設備發(fā)送數(shù)據(jù)時,首先檢查時鐘線,以確認時鐘線是否為高電平.如果是高電平,從設備就可以開始傳輸數(shù)據(jù);反之,從設備要等待獲得總線的控制權,才能開始傳輸數(shù)據(jù).傳輸?shù)拿恳粠?1位組成,發(fā)送時序及每一位的含義如圖2所示.
      從設備到主設備的通信 
          每一幀數(shù)據(jù)中開始位總是為0,數(shù)據(jù)校驗采用奇校驗方式,停止位始終為1.從設備到主設備通信時,從設備總是在時鐘線為高時改變數(shù)據(jù)線狀態(tài),主設備在時鐘下降沿讀人數(shù)據(jù)線狀態(tài).

      1.2 主設備到從設備的通信
          主設備與從設備進行通信時,主設備首先將時鐘線和數(shù)據(jù)線設置為“請求發(fā)送”狀態(tài),具體方式為:首先下拉時鐘線至少100us抑制通信,然后下拉數(shù)據(jù)線“請求發(fā)送”,最后釋放時鐘線.在此過程中,從設備在不超過10us的間隔內(nèi)必須檢查這個狀態(tài),當設備檢測到這個狀態(tài)時,它將開始產(chǎn)生時鐘信號.此時數(shù)據(jù)傳輸?shù)拿恳粠?2位構成,其時序和每一位含義如圖3所示.
      主設備到從設備的通信 
          與從設備到主設備通信相比,其每幀數(shù)據(jù)多了一個ACK位.這是從設備應答接收到字節(jié)的應答位,由從設備通過拉低數(shù)據(jù)線產(chǎn)生,應答位ACK總
      是為0.主設備到從設備通信過程中,主設備總是在時鐘線為低電平時改變數(shù)據(jù)線的狀態(tài),從設備在時鐘上升沿讀人數(shù)據(jù)線狀態(tài).

      2 PS/2鍵盤的編碼與命令集
      2.1 PS/2鍵盤的編碼
          目前,PC機使用的PS/2鍵盤都默認采用第2套掃描碼集.掃描碼有兩種不同的類型:“通碼(make code)”和“斷碼(break code)”.當一個鍵被按下或持續(xù)按住時,鍵盤會將該鍵的通碼發(fā)送給主機;而當一個鍵被釋放時,鍵盤會將該鍵的斷碼發(fā)送給主機.根據(jù)鍵盤按鍵掃描碼的不同,可將按鍵分為3類:
      第1類按鍵 通碼為一個字節(jié),斷碼為0xF0+通碼形式.如A鍵,其通碼為0x1C;斷碼為0xF0 0x1C.
      第2類按鍵 通碼為兩字節(jié)0xE0+0xXX形式,斷碼為0xE0+0xF0+0xXX形式.如Right Ctrl鍵,其通碼為0xE0 0x14;斷碼為0xE0 0xF0 0x14.
      第3類特殊按鍵 有兩個,Print Screen鍵,其通碼為0xE0 0x12 0xE0 0x7C;斷碼為0xE0 0xF0 0x7C 0xE0 0xF0 0x12.Pause鍵,其通碼為0xE1 0x14 0x77 0xE1 0xF0 0xl4 0xF0 0x77;斷碼為空.
          組合按鍵掃描碼的發(fā)送是按照按鍵發(fā)生的次序,如按下面順序按左Shift十A鍵:① 按下左Shift鍵;② 按下A鍵;③ 釋放A鍵;④ 釋放左Shift鍵,那么計算機上接收到的一串數(shù)據(jù)為0x12 0x1C 0xF0 0x1C 0xF0 0x12.
          在文中的驅(qū)動程序設計中,就是根據(jù)按鍵的分類對其分別進行處理.

      2.2 PS/2鍵盤的命令集
          主機可通過向PS/2鍵盤發(fā)送命令對鍵盤進行設置或者獲得鍵盤的狀態(tài)等操作.每發(fā)送一個字節(jié),主機都會從鍵盤獲得一個應答0xFA(“重發(fā)
      resend”和“回應echo”命令例外).驅(qū)動程序在鍵盤初始化過程中所用的指令:0xED,主機在該命令后跟隨發(fā)送一個參數(shù)字節(jié),用于指示鍵盤上Num Lock,Caps Lock,Scroll Lock Led的狀態(tài);0xF3,主機在這條命令后跟隨發(fā)送一個字節(jié)參數(shù)定義鍵盤機打的速率和延時;0xF4,用于當主機發(fā)送0xF5禁止鍵盤后,重新使能鍵盤.

      3 PS/2鍵盤與單片機的連接電路
          PS/2鍵盤與AT89C51單片機的連接方式如圖4所示.P1.0接PS/2數(shù)據(jù)線;P3.2(INT0)接PS/2時鐘線.因為單片機的P1,P3口內(nèi)部是帶上拉電阻的,所以PS/2的時鐘線和數(shù)據(jù)線可以直接與單片機的P1,P3相連接.
       

      4 驅(qū)動程序設計
          驅(qū)動程序的開發(fā)使用Keil C51語言以及KeiluVision2編程環(huán)境.PS/2 104鍵盤驅(qū)動程序主要任務是實現(xiàn)單片機與鍵盤間PS/2通信,同時將接收到的按鍵掃描碼轉(zhuǎn)換為該按鍵的鍵值KeyVal,提供給系統(tǒng)上層軟件使用.

      4.1 單片機與鍵盤間PS/2通信的程序設計
          在PS/2通信過程中,主設備(文中是單片機)是在時鐘信號為低時發(fā)送和接收數(shù)據(jù)信號.因為單片機向鍵盤發(fā)送的是指令,需要鍵盤回應,所以這
      部分程序采用查詢方式;而單片機接收鍵盤數(shù)據(jù)時,數(shù)據(jù)線上的信號在時鐘為低時已經(jīng)穩(wěn)定,所以這部分程序采用中斷方式,且不需要在程序中加入延時程序.
          單片機向PS/2鍵盤發(fā)送數(shù)據(jù)程序代碼為:
      void ps2_sentchar(unsigned char sentchar){//ps2主設備向從設備發(fā)送數(shù)據(jù)
      unsigned char sentbit_cnt= 0x00;
      unsigned char sentchar_chk = 0x00;
      EX0=0; //關外部中斷0
      //發(fā)起一個傳送,發(fā)起始位
      PS2_SGN_CLOCK = 0; //將時鐘線拉低并保持100 us
      delay100us();
      PS2_SGN_DATA= 0; //起始位
      PS2_SGN_CLOCK = 1;
      //發(fā)送DATA0-7
      for(sentbit_cnt=0;sentbit_cnt< 8;sentbit_cnt++){
      while(PS2_SGN_CLOCK) _nop_(); //等待時鐘線變?yōu)榈?BR>PS2_SGN_DATA = sentchar& 0x01;//發(fā)送數(shù)據(jù)
      if(PS2_SGN_DATA) sentchar_chk++; //計算校驗
      while(!PS2_SGN_CL0CK) _nop_(); //等待時鐘線變高
      sentchar>>=1; //待發(fā)送數(shù)據(jù)右移一位
      }
      //發(fā)送校驗位
      while(PS2_SGN_CLOCK) _nop_(); //等待時鐘線變低
      switch(sentchar_chk){
      case 0:
      case 2:
      case 4:
      case 6:PS2_SGN_DATA =1;break;//奇校驗
      case 1:
      case 3:
      case 5:
      case 7:PS2_SGN_DATA = 0;break;//奇校驗
      default;break;
      )
      while(!PS2_SGN_CLOCK) _nop_(); //等待時鐘線變高
      while(PS2_SGN_CLOCK) _nop_(); //等待時鐘線變低
      PS2_SGN_DATA =1;//發(fā)送停止位,停止位總為1
      while(!PS2_SGN_CLOCK) _nop_(); //等待時鐘線變高
      while(PS2_SGN_CLOCK) _nop_(); //等待時鐘線變低
      //接收ACK
      //if(PS2_SGN_DATA) error();
      //ACK信號由鍵盤發(fā)出,總為低電平
      while(!PS2_SGN_CLOCK) _nop_(); //等待時鐘線變高
      EX0= 1; //開外部中斷0
      }

      單片機由PS/2鍵盤接收數(shù)據(jù)程序:外部中斷0設置為下降沿觸發(fā)
      void int0() interrupt 0 using 0 {//
      EX0=0; //關外部中斷0
      switch(ps2_revchar_cnt){
      case 1:
      ……
      case 8:mcu_revchar<<=1;
      if(PS2_SGN_DATA) mcu_revchar |= 0x01;
      ps2_revchar_cnt++;
      break;
      case 0:ps2_revchar_cnt++;break; //開始位,
      case 9:ps2_revchar_cnt++;break; //校驗位,可添加校驗程序
      case 10: _nop_();//停止位
      ps2_revchar_cnt= 0;
      revchar_flag=1;//置接收到數(shù)據(jù)標識位
      break;
      default:break;
      }
      EX0=1;//開外部中斷0
      }

      4.2 鍵盤掃描碼轉(zhuǎn)換程序設計
          由于鍵盤掃描碼無規(guī)律可循,因此由鍵盤掃描碼獲得相應按鍵的鍵值(字符鍵為其ASCII值,控制鍵如F1,Ctrl等為自定義值),只能通過查表的方式獲得.由于按鍵的3種類型及部分按鍵對應著兩個鍵值(如A鍵的鍵值根據(jù)Caps和Shift鍵狀態(tài)有0x41(A)和0x61(a)兩種),因此綜合考慮查表轉(zhuǎn)換速度和資源消耗,設計中使用4個鍵盤表:鍵盤掃描碼轉(zhuǎn)換基本集和切換集(kb_plain_map[NR_KEYS]與kb_shift_map[NR_KEYS]);包含E0前綴的鍵盤掃描碼轉(zhuǎn)換基本集和切換集(kbeO_plain_map[NR_KEYS]與kbe0_shiftmap[NR_KEYS]).PS/2 104鍵盤按鍵掃描碼最大值為0x83,所以設置NR_KEYS為132.所有4個鍵盤表的定義均為如下形式:KB_MAP[MAKE CODE]=KEYVAL,如果掃描碼對應的按鍵為空(如KB_MAP[0x00]),則定義相應鍵值為NULL_KEY(0x00).以下是鍵盤掃描碼基本集的部分代碼實例:
      kb_plain_map[NR_KEYS]={……
      NULL_KEY;0x2C;0x6B;0x69;0x6F;0x30;0x39;
      NULL_KEY; //掃描碼0x40~0x47
      //對應按鍵空,逗號,K,I,O,0,9,空
      //對應鍵值0x00,',','k','i','o','O','9',0x00…… };
          如此設計鍵盤轉(zhuǎn)換表的另一個好處在于,以后如需擴展支持有ACPI、Windows多媒體按鍵鍵盤時,只需要將鍵表中相應處修改即可,如ACPI
      Power按鍵通碼為0xE0 0x37,修改kbe0_plain_map[0x37]=KB_ACPI_PWR即可.
          特殊按鍵Pause使用單獨程序處理,如果接收到0xE1就轉(zhuǎn)入這段程序.而Print Screen鍵則將其看作是兩個通碼分別為0xE0 0x12和0xE0 0x7C
      的“虛鍵”的組合鍵處理.在驅(qū)動程序中設定如下全局變量:led_status記錄Scroll Lock Led,Num Lock Led和Caps Lock Led的狀態(tài)(關為0,開為1);agcs_status記錄左右Shift Ctrl Gui Alt狀態(tài),相應鍵按下則對應位為1,釋放為0.E0_FLAG接到0xE0置1;E1_FLAG接收到0xE1置1;F0_FLAG接收到0xF0置1.按鍵鍵值通過KeyVal提供上層程序使用.PS/2鍵盤掃描碼鍵值轉(zhuǎn)換程序ps2_codetrans()流程框架如圖5所示.
      掃描碼鍵值轉(zhuǎn)換程序流程框架 

      第1類按鍵的掃描碼鍵值轉(zhuǎn)換程序代碼。
      if(F0_FLAG){//接收掃描碼為斷碼
      switch(mcu_revchar){//處理控制鍵
      case 0x11:ages_status&=0xF7;break;//左alt釋放
      case 0x12:ages_status&=0xFE;break;//左shift釋放
      case 0x14:agcs_status&=0xFD;break;//左ctrl釋放
      case 0x58;if(led_status&0x04) led_status &= 0x03; //caps lock
      else led_status |=0x04;
      ps2_ledchange();
      break;
      case 0x59: agcs_status &= 0xEF;break;//右shift釋放
      case 0x77: if(led_status&0x02)led_status&=0x05;//num lock
      else led_status |=0x02;
      ps2_ledchange();
      break;
      case 0x7E:if(led_status&0x01) led_status&=0x06;//scroll lock
      else led_status |=0x01;
      ps2_ledchange();
      break;
      default;break;
      }
      F0_FLAG=0;
      }
      else{//接收掃描碼為通碼
      if(led_status&0x04) caps_flag=1;else caps_flag = 0;
      if(led_status&0x02) num_flag =1;else num_flag =0;
      if(agcs_status&0x11) shift_flag = 1;else
      shift_flag=0;
      //掃描碼鍵值轉(zhuǎn)換
      if((caps_flag == shift_flag) || (!num_flag)) KeyVal=kb_plain_map[mcu_revchar];
      else KeyVal = kb_shift_map[mcu_revchar];
      switch(mcu_revchar)(//處理控制鍵或狀態(tài)鍵
      case 0x11:agcs_status|= 0x08;//左alt按下
      Case 0x12:agcs_status|= 0x01;//左shift按下
      case 0x14:agcs_status|= 0x02;//左ctrl按下
      case 0x59:agcs_status|= 0x10;//右shift按下
      default:break;
      }
      }
          第2類按鍵的掃描碼鍵值轉(zhuǎn)換程序與上面相似.注意:在退出該程序段時,對E0_FLAG和F0_FLAG標識清0.Pause鍵的處理程序,如果接收到0xE1,置E1_FLAG=1,然后順次將后續(xù)接收到的7個字節(jié)數(shù)據(jù)和Pause的通碼后7個字節(jié)比較,一致則返回KeyVal=KB_PAUSE;在比較完所有7個字節(jié)后清除E1_FLAG標識.鍵盤初始化程序kb_init()流程為:
      ① 上電后,接收鍵盤上電自檢通過信號0xAA,或者自檢出錯信號0xFC.單片機接收為0xAA則進入下一步,否則進行出錯處理.
      ② 關LED指示,單片機發(fā)送0xED,然后接收鍵盤回應0xFA,接著發(fā)送0x00接收0xFA.
      ③ 設置機打延時和速率:單片機發(fā)送0xF3,接收0xFA,發(fā)送0x00(250 ms,2.0 cps),接收0xFA.
      ④ 檢查LED,發(fā)送0xED,接收0xFA,發(fā)送0x07(開所有LED),接收0xFA.發(fā)送0xED,接收0xFA,發(fā)送0x00(關LED),接收0xFA.
      ⑤ 允許鍵盤,發(fā)送0xF4,接收0xFA.鍵盤LED改變ps2_ledchange()函數(shù)流程:發(fā)送0xED;接收0xFA;發(fā)送led_status;接收0xFA.

      5 結(jié)語
        該驅(qū)動程序經(jīng)Keil uVision2 編譯,在AT89C51單片機上運行通過,實現(xiàn)了對PS/2 104鍵盤的支持,實現(xiàn)了對字符按鍵大小寫切換,Num Lock切換、控制鍵及組合按鍵的支持.同時該程序?qū)ζ渌度胧交騿纹瑱C系統(tǒng)中PS/2鍵盤的應用也有借鑒意義.

      Tags:單片機,鍵盤設計,驅(qū)動程序設計  
      責任編輯:admin
      相關文章列表
      沒有相關文章
      請文明參與討論,禁止漫罵攻擊,不要惡意評論、違禁詞語。 昵稱:
      1分 2分 3分 4分 5分

      還可以輸入 200 個字
      [ 查看全部 ] 網(wǎng)友評論
      關于我們 - 聯(lián)系我們 - 廣告服務 - 友情鏈接 - 網(wǎng)站地圖 - 版權聲明 - 在線幫助 - 文章列表
      返回頂部
      刷新頁面
      下到頁底
      晶體管查詢
      主站蜘蛛池模板: 亚洲综合色7777情网站777| 亚洲国产精品综合一区在线| 精品福利一区二区三区精品国产第一国产综合精品 | 色综合天天综合中文网| 色婷婷综合中文久久一本| 老色鬼久久综合第一| 久久婷婷午色综合夜啪| 亚洲综合国产一区二区三区| 天天av天天翘天天综合网| 91精品国产综合久久久久久| 亚洲av无码兔费综合| 亚洲av无码国产综合专区| 亚洲综合精品一二三区在线 | 亚洲综合无码精品一区二区三区| 亚洲综合欧美色五月俺也去| 亚洲亚洲人成综合网络 | 久久久久综合中文字幕| 色综合伊人色综合网站| 亚洲国产精品成人综合色在线 | 亚洲欧美日韩综合俺去了| 97久久久精品综合88久久| 99久久综合狠狠综合久久aⅴ| 少妇熟女久久综合网色欲| 伊人久久大香线蕉综合电影网| 久久久久噜噜噜亚洲熟女综合| 国产综合在线观看视频| 色欲香天天综合网无码| 久久综合久久鬼色| 一本久久a久久精品vr综合| 亚洲国产综合91精品麻豆| 日韩亚洲人成在线综合日本| 久久精品国产9久久综合| 久久婷婷五月综合国产尤物app| 久久综合精品视频| 亚洲综合色婷婷在线观看| 五月天婷亚洲天综合网精品偷| 中文字幕亚洲综合久久男男| 亚洲狠狠婷婷综合久久久久| 亚洲国产精品综合久久久| 激情婷婷成人亚洲综合| 久久综合伊人77777|