久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 9253|回復: 3
打印 上一主題 下一主題
收起左側

51單片機模擬PS2協議制作5X5矩陣工業鍵盤

[復制鏈接]
跳轉到指定樓層
樓主
ID:76127 發表于 2015-4-18 00:40 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
根據客戶的要求利用單片機制作一個小的工控鍵盤,將下面對應的鍵值發送到電腦顯示,利用的協議就是PS2,單片機型號為stc89c52rc,晶振為12M;

 
 
 
1
0
6
5
4
3
2
7
8
9
減號
等號
y
u
i
o

p
q
w
e
r
t


#include <reg51.h>
#include "PS2.H"
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;   //設定標志位
Key_line=0xe0;        //將P0口低5位全部設置位0
temp3=Key_list;     //讀取P2口的狀態,若果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用來保存行鍵盤數據,temp3保存列鍵盤數據
unsigned char temp=0,flag=0;     //函數返回值temp
unsigned char i=0,key=0;   //i位循環控制變量,給行送數據,key保存檢測鍵盤按下的標志位
if((key=Key_Press())!=0)   //判斷是否有鍵按下
{
  delay(30);
  if((key=Key_Press())!=0)
  {
    for(i=0x01;i!=0x20;i=i<<1)  //循環控制變量,掃描5行
    {
     Key_line=(~i);        //將循環控制變量賦值行地址
     temp2 =(~i);     //保存行地址
     //temp2=Key_line;
     temp3=Key_list;      //讀取列地址數據
     switch((temp3&0xff)) //判斷是那列有鍵按下
     {
      case 0xfe:   //第一列有鍵按下
       switch((temp2&0xff)) //判斷第一列有鍵按下時,對應的行按鍵   
       {
        case 0xfe:
          temp=23;   //第一行有鍵按下
          break;  //該鍵無鍵盤號定義
        case 0xfd:    //第二行有鍵按下
          temp=PS2_6;flag=1;  //對應鍵值位PS2鍵盤的數字6,對應的鍵盤掃描碼為0x36
          break;
        case 0xfb:    //第三行有鍵按下
          temp=PS2_7; flag=1;//對應鍵值位PS2鍵盤的數字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鍵盤的數字5,對應的鍵盤掃描碼為0x2e
          break;
        case 0xfb:      //第三行有鍵按下
          temp=PS2_8; flag=1;  //對應鍵值位PS2鍵盤的數字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鍵盤的數字4,對應的鍵盤掃描碼為0x25
          break;
        case 0xfb:     //第三行有鍵按下
          temp=PS2_9; flag=1; //對應鍵值位PS2鍵盤的數字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鍵盤的數字1,對應的鍵盤掃描碼為0x16
                 break;
        case 0xfd:      //第二行有鍵按下
          temp=PS2_3; flag=1;  //對應鍵值位PS2鍵盤的數字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鍵盤的數字0,對應的鍵盤掃描碼為0x45
                 break;
        case 0xfd:         //第二行有鍵按下
          temp=PS2_2; flag=1;     //對應鍵值位PS2鍵盤的數字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;     //無鍵按下返回數字23,對應數組內的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++)//檢查是否有數據處理 0x88
  {
   if(H_CLK==0)//有動作則是大鍵盤存在
   {
    OnKeyBoardOnline(TRUE);//大鍵盤存在,開機由大鍵盤應答
    IE0=0;
    EX0=1;
    return ;//存在的話置標志位,并返回
   }
  }
}
OnKeyBoardOnline(FALSE);//大鍵盤不存在,由小鍵盤應答

//轉到接收
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; }//如果時鐘被拉低,則有錯誤發生
}
         
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; //低電平觸發中斷
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燈觀察每個按鍵按下之后的鍵值返回知否和第二套鍵盤碼對應一致



第二套鍵值碼對應表:





分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:135507 發表于 2016-7-30 09:02 | 只看該作者
這個 PS2.h的頭文件去哪里找呀
回復

使用道具 舉報

板凳
ID:135566 發表于 2016-7-30 23:54 | 只看該作者
不錯,挺好
回復

使用道具 舉報

地板
ID:258695 發表于 2018-3-13 16:43 | 只看該作者
"這個 PS2.h的頭文件去哪里找呀"
同問。。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 伊人狠狠 | 欧美www在线观看 | 国产精品av久久久久久久久久 | 午夜视频一区 | 暖暖成人免费视频 | 亚洲一区二区免费视频 | 欧美a区| 亚洲美女在线视频 | 久在线 | 日韩视频免费 | 在线观看免费观看在线91 | 岛国在线免费观看 | 精品国产欧美在线 | 亚洲综合无码一区二区 | 亚洲性人人天天夜夜摸 | 日韩中文久久 | 伊人色综合久久久天天蜜桃 | 欧美成人免费在线视频 | 91久久精品一区二区二区 | 天堂av中文在线 | 中文字幕免费视频 | 一区二区在线看 | 中文字幕一区二区三区在线观看 | 91久久国产综合久久 | 免费在线观看黄色av | 97视频在线免费 | 奇米影视在线 | 亚洲综合视频一区 | 男女羞羞视频在线免费观看 | www.五月天婷婷 | 欧产日产国产精品国产 | 久久中文字幕视频 | 久久久久久亚洲 | 亚洲欧美一区二区三区国产精品 | 国产欧美精品区一区二区三区 | 91极品视频 | 日韩激情在线 | 国产精品免费大片 | 国产成都精品91一区二区三 | 国产在线精品免费 | 午夜免费精品视频 |