关于PS2键盘的C程序

来源:网络时间:2011-06-24 15:03:14

  用51操作和检测PS2键盘,接收数据已经搞定了,可是发送数据却出错,不知道怎么回事。给它的命令和它所执行的完全不同,请高手指教下,到底是哪里错了,还是没错,电路接得不对??接收函数是这样的。
  void send(uchar Data)
  {
  uchar i,high=0;
  EA=0;
  EX0=0;//关闭中断
  CLK=0;
  delay10us(11);
  DATA=0;
  delay10us(2);
  CLK=1;
  while(CLK==1);
  //开始发送八位数据
  for(i=0;i<=7;i++)
  {
  if(Data & 0x01)
  {
  DATA=1;
  high++;
  }
  DATA=(Data>>1);
  while(CLK==0);
  while(CLK==1);
  }
  if(high%2==0) DATA=1; //设置奇校验位
  else DATA=0;
  while(CLK==0);
  while(CLK==1);
  DATA=1;
  while(DATA==1);
  while(CLK==1);
  while(DATA==0);
  while(CLK==0);
  EA=1;
  EX0=1;//写数据程序结束后开中断
  }

  全部程序是这样的:
  #include <reg52.H>
  #include <intrins.H>
  #include <head.h>
  #define uchar unsigned char
  #define uint unsigned int
  #define LCD_DATA P2 //数据口
  sbit RS = P1^5; //并行的指令/数据选择信号, H数据, L命令
  sbit RW = P1^7; //并行读写选择信号, H读, L写
  sbit E = P1^6; //并行使能端, H有效, L无效
  sbit PSB = P1^1; //并/串接口选择, H并,L串
  sbit RET = P1^4; //复位, L有效
  sbit DATA=P0^2;
  sbit CLK=P3^2;
  uchar count,ASCII=65,Data;
  void trains(uchar Code);
  void send (uchar Data);
  //检测LCD是否处于忙状态, 若忙返回1, 空闲返回0
  bit checkBusy()
  {
  bit busy;
  RS = 0;
  RW = 1;
  E = 1;
  delayUs();
  busy = (bit)(LCD_DATA&0x80);
  E = 0;
  return busy;
  }
  //等待LCD到空闲
  void wait()
  {
  while(checkBusy());
  }
  //写命令
  void writeCmd(uchar cmd)
  {
  wait();
  RS = 0;
  RW = 0;
  E = 0;
  delayUs();
  LCD_DATA = cmd;
  delayUs();
  E = 1;
  delayUs();
  E = 0;
  }

  //写数据
  void writeData(uchar dat)
  {
  wait();
  RS = 1;
  RW = 0;
  E = 0;
  delayUs();
  LCD_DATA = dat;
  delayUs();
  E = 1;
  delayUs();
  E = 0;
  }
  //初始化LCD
  void init()
  {
  PSB = 1; //并口方式
  writeCmd(0x30); //基本指令, 扩充指令为34H
  delayMs(10);
  writeCmd(0x0c); //显示开, 关光标
  writeCmd(0x01); //清屏
  delayMs(10);
  }
  void init2()
  {
  PSB = 1; //并口方式
  RET=0; //复位
  delayUs(); //延时
  RET=1; //复位置高
  writeCmd(0x36);
  delayMs(10);
  writeCmd(0x3E);
  delayMs(10);
  writeCmd(0x01); //清屏
  delayMs(10);
  }
  void setPosition(uchar x, uchar y)
  {
  uchar p;
  switch(x%4)
  {
  case 0: p = 0x80; break; //第一行开始地址

  case 1: p = 0x90; break; //第二行
  case 2: p = 0x88; break; //第三行
  case 3: p = 0x98; break; //第四行
  }
  p += y;
  writeCmd(p);
  }
  void writeString(uchar * str)
  {
  uchar i = 0;
  while(str[i] != '\0')
  {
  writeData(str[i++]);
  }
  }

#p#副标题#e#
  void DisplayGraphic(unsigned char code *adder)
  {
  int i,j;
  //*******显示上半屏内容设置
  for(i=0;i<32;i++) //
  {
  writeCmd(0x80 + i); //SET 垂直地址 VERTICAL ADD
  writeCmd(0x80); //SET 水平地址 HORIZONTAL ADD
  for(j=0;j<16;j++)
  {
  writeData(*adder);
  adder++;
  }
  }
  //*******显示下半屏内容设置
  for(i=0;i<32;i++) //
  {
  writeCmd(0x80 + i); //SET 垂直地址 VERTICAL ADD
  writeCmd(0x88); //SET 水平地址 HORIZONTAL ADD
  for(j=0;j<16;j++)
  {
  writeData(0xff);
  adder++;
  }
  }
  }
  void initkb() //键盘初始化函数
  {
  EA=1;//?
  EX0=1;
  IT0=1;
  count=0;
  }
  void exter0() interrupt 0
  {
  count++;
  if(count>=2 && count<=9)
  {

  Data=(Data>>1);
  if(DATA==1)
  Data|=0x80;
  }
  }
  void trains(uchar scancode)
  {
  static uchar up=0,shift=0; //up为通、断码标志,shift为shift键按下标志
  uchar i;
  if (!up) //已接收的11位数据是通码(up为0)
  {
  switch (scancode)//开始翻译扫描码
  {
  case 0xF0: //键盘释放标志(随后的一个字节是断码)
  up=1; //设置up为断码标志
  break;
  case 0x12: //左shift键按下
  shift=1; //设置shift为按下标志
  break;
  case 0x59: //右shift键按下
  shift=1; //设置shift为按下标志
  break;
  default:
  if(!shift) //如果shift键没有按下
  { //查找unshifted表,表中左列是扫描码,右列是对应的ASCII码
  for(i=0;unshifted[i][0]!=scancode&&unshifted[i][0];i++);
  if(unshifted[i][0]==scancode)
  {
  ASCII=unshifted[i][1];
  }
  }
  else //如果shift键按下
  { //查找shifted表
  for(i=0;shifted[i][0]!=scancode&&shifted[i][0];i++);
  if(shifted[i][0]==scancode)
  {
  ASCII=shifted[i][1];
  }
  }
  break;
  }
  }
  else //已接收的11位数据是断码(up为1)
  {

  up = 0; //将断码标志复位
  switch (scancode) //检测shift键释放
  {
  case 0x12 : //左shift键
  shift = 0;
  break;
  case 0x59 : //右shift键
  shift = 0;
  break;
  default:
  break;
  }
  }
  }
  void main()
  {
  delayMs(500);
  init();
  initkb();
  setPosition(0, 0);
  writeString(datas1);
  send(0x03);
  setPosition(1, 0);
  writeString(datas2);
  while(1)
  {
  if(count==11)
  {
  count=0;
  trains(Data);
  // send(0xED);
  }
  setPosition(2, 0);
  writeData(ASCII);
  if(count==0)
  {
  setPosition(3, 0);
  writeString(datas3);
  }
  else
  {
  setPosition(3, 0);
  writeString(datas4);
  count=0;
  }
  }
  }
  //以下是给键盘发数据函数
  void send(uchar Data)
  {
  uchar i,high=0;

  EA=0;
  EX0=0;//?
  CLK=0;
  delay10us(11);
  DATA=0;
  delay10us(2);
  CLK=1;
  while(CLK==1);
  //开始发送八位数据
  for(i=0;i<=7;i++)
  {
  if(Data & 0x01)
  {
  DATA=1;
  high++;
  }
  DATA=(Data>>1);
  while(CLK==0);
  while(CLK==1);
  }
  if(high%2==0) DATA=1;
  else DATA=0;
  while(CLK==0);
  while(CLK==1);
  DATA=1;
  while(DATA==1);
  while(CLK==1);
  while(DATA==0);
  while(CLK==0);
  EA=1;
  EX0=1;//写数据程序结束后开中断
  }

#p#副标题#e#
  head.h头文件:
  #define uchar unsigned char
  #define uint unsigned int
  uchar code datas1[] = {"PS2 键盘检测实验"};
  uchar code datas2[] = {"检测的按键为"};
  uchar code datas3[] = {"按键检测正确"};
  uchar code datas4[] = {"检测有误 "};
  uchar code unshifted[][2]= //shift键没按下译码表
  {
  0x0e,'`',
  0x15,'q',
  0x16,'1',
  0x1a,'z',
  0x1b,'s',
  0x1c,'a',
  0x1d,'w',
  0x1e,'2',
  0x21,'c',
  0x22,'x',
  0x23,'d',
  0x24,'e',

  0x25,'4',
  0x26,'3',
  0x29,' ',
  0x2a,'v',
  0x2b,'f',
  0x2c,'t',
  0x2d,'r',
  0x2e,'5',
  0x31,'n',
  0x32,'b',
  0x33,'h',
  0x34,'g',
  0x35,'y',
  0x36,'6',
  0x39,',',
  0x3a,'m',
  0x3b,'j',
  0x3c,'u',
  0x3D,'7',
  0x3e,'8',
  0x41,',',
  0x42,'k',
  0x43,'i',
  0x44,'o',
  0x45,'0',
  0x46,'9',
  0x49,'.',
  0x4a,'/',
  0x4b,'l',
  0x4c,';',
  0x4d,'p',
  0x4e,'-',
  0x52,'\'',
  0x54,'[',
  0x55,'=',
  0x5b,']',
  0x5d,'\\',
  0x61,'<',
  0x69,'1',
  0x6b,'4',
  0x6c,'7',
  0x70,'0',
  0x71,'.',
  0x72,'2',
  0x73,'5',
  0x74,'6',
  0x75,'8',
  0x79,'+',
  0x7a,'3',
  0x7b,'-',
  0x7c,'*',
  0x7d,'9',
  0,0
  };
  uchar code shifted[][2]= //shift键按下译码表
  {

  0x0e,'~',
  0x15,'Q',
  0x16,'!',
  0x1a,'Z',
  0x1b,'S',
  0x1c,'A',
  0x1d,'W',
  0x1e,'@',
  0x21,'C',
  0x22,'X',
  0x23,'D',
  0x24,'E',
  0x25,'$',
  0x26,'#',
  0x29,' ',
  0x2a,'V',
  0x2b,'F',
  0x2c,'T',
  0x2d,'R',
  0x2e,'%',
  0x31,'N',
  0x32,'B',
  0x33,'H',
  0x34,'G',
  0x35,'Y',
  0x36,'^',
  0x39,'L',
  0x3a,'M',
  0x3b,'J',
  0x3c,'U',
  0x3d,'&',
  0x3e,'*',
  0x41,'<',
  0x42,'K',
  0x43,'I',
  0x44,'O',
  0x45,')',
  0x46,'(',
  0x49,'>',
  0x4a,'?',
  0x4b,'L',
  0x4c,':',
  0x4d,'P',
  0x4e,'_',
  0x52,'"',
  0x54,'{',
  0x55,'+',
  0x5b,'}',
  0x5d,'|',
  0x61,'>',
  0x69,'1',
  0x6b,'4',
  0x6c,'7',
  0x70,'0',
  0x71,'.',
  0x72,'2',
  0x73,'5',
  0x74,'6',
  0x75,'8',
  0x79,'+',
  0x7a,'3',
  0x7b,'-',
  0x7c,'*',
  0x7d,'9',
  0,0
  };
  //延时约2us
  void delayUs()
  {
  _nop_();_nop_();
  }

  //延时 a * 1ms
  void delayMs(uint a)
  {
  uint i, j;
  for(i = a; i > 0; i--)
  for(j = 100; j > 0; j--);
  }
  void delay10us(uchar i) //10us延时程序
  { uchar a=14;
  uchar b;
  for(b=0;b<i;b++)
  { while(a--);a=14;}
  }#p#副标题#e#

文章内容来源于网络,不代表本站立场,若侵犯到您的权益,可联系我们删除。(本站为非盈利性质网站) 联系邮箱:rjfawu@163.com