历史上的今天
返回首页

历史上的今天

今天是:2025年03月08日(星期六)

2018年03月08日 | 51mcu模拟ps2键盘发送数据程序

2018-03-08 来源:eefocus

这个是程序是来自我以前开发的一个项目,其中里面的的void ps_send(uchar x) 这个函数,便可实现向电脑发送按键的数据 你只要对照 ps2 扫描码的表填入适当的参数即可
#include "STC89C51.H"
#include"keyboard.h"
#include
#define nop()  _nop_()


uchar *receive_buf;//接收来自计算机的数据

//uchar key;
unsigned char key_buf[21];
/******延时子程序********/
void delay_ms(uchar a)
{uchar i;
uchar j;

    for(j=0;jfor(i=200;i>0;i--);
}
 
void delay_us(void)//30us
{uchar i;

      for(i=0;i<7;i++)
 {  _nop_();
 }
}

    /************行列转换成索引号*****************/
/*
uchar code_chang(uchar ini_code)
 {uchar  i;
i=ini_code;
 switch(i)
    {case 0x01:return(1);break;
    case 0x02:return(2);break;
    case 0x04:return(3);break;
    case 0x08:return(4);break;
    case 0x10:return(5);break; 
  default:;
    }
  
  
 }
*/
//初始化按键端口
void init_key(void)
{
  
 unsigned char i=0;
  
//右按键板
P2=0xff;

    //左按键板
P0=0xff;

    k_num_5 = 1;
k_num_4 = 1;
k_num_7 = 1;
k_num_8 = 1;
k_num_9 = 1;
//  LED=0;
  for(i=0;i<21;i++)
  {
      key_buf[i]=1;
    
  }

     
}

    //读按键值并将其转换为索引号
unsigned char read_key(void)
{unsigned char i;
 key_buf[0]=k_esc; 
 key_buf[1]=k_F1; 
 key_buf[2]=k_F3; 
 key_buf[3]=k_F2;
 key_buf[4]=k_F5; 
 key_buf[5]=k_F4; 
 key_buf[6]=k_menu; 
 key_buf[7]=k_num_LOCk;
 
 key_buf[8]=k_num_6;
 key_buf[9]=k_num_1;
 key_buf[10]=k_num_2 ;
 key_buf[11]=k_num_3 ;
 key_buf[12]=k_num_0;
 key_buf[13]=k_del;
 key_buf[14]=k_enter;
 key_buf[15]=k_back;
 key_buf[16]=k_num_5;
 
 key_buf[17]=k_num_4;
 key_buf[18]=k_num_7;
 key_buf[19]=k_num_8;
 key_buf[20]=k_num_9;
 
 for(i=0;i<21;i++) 
   {if(0==key_buf[i])
   {
   key_buf[i]=1;
   return i;
   break;
   }
    }
}

     /********代码转换**************/
uchar change_code(uchar key)  //返回一个ASCII键值
{uchar i;
 statIC bit shitf_direct=0,key_flat=1;

    i=key;
 if(7==i&&1==key_flat)
 {key_flat=0;
 shitf_direct=1;
 }
 else if(7==i&&0==key_flat)
 {key_flat=1;
 shitf_direct=0;
 }
 else
 {}
    if ( 1==shitf_direct)//转到方向盘(1为方向盘,0为数字盘)
 {  lock_LED =0;
 switch(i)

       {
   case 12:return(0x2D);break;//insert
     case 9:return(0x23);break;//end
     case 10:return(0x28);break;//down
   case 11:return(0x22);break;//pagedown
   case 17:return(0x25);break;//left
   case 16:return(0x0C);break;//NC
   case 8:return(0x27);break;//right
   case 18:return(0x24);break;//home
   case 19:return(0x26);break;//up
   case 20:return(0x21);break;//pageup
   default:;
  }
 }
 else
      {lock_LED =1;
    return(trdata[i]);
    }
}
/*************键盘扫描*****************/ 
/*
void int1() interrupt 2 using 1
{//uchar sCANkb(void)
uchar sCCode,recode;
 
 if((P0&0x0f)!=0x0f)//有键按下
  {delay_ms(10);
    if((P0&0x0f)!=0x0f)//仍然有键按下
    {recode=P0|0xf0; //列号保存
    P0=0x0f;
     sccode=0xfe;
    while((sccode&0x40)!=0)//移位没完
        {
      P2=sccode;//行扫描开始
      if(P0 != 0x0F) //若在该行
       {
     P0=0x0f;
           P2=0; 
          //return(code_chang(~sccode)+5*code_chang(~recode));//返回Keyword
      key=code_chang(~sccode)+5*code_chang(~recode);break;
       }
         else 
    {sccode=(sccode<<1)|0x01;}//不在该行则扫下一行
    }
    }
  }
// return(0);
}

    */

    
/** ps/2发送数据  ***/
void ps_send(uchar x)
{  uchar i,temp,char_temp;
  bit flat_check=1;
 delay_ms(3);
 temp=x;
 for(i=0;i<8;i++)
 {char_temp=temp&0x01;
  if(char_temp==0x01)
  {flat_check=!flat_check;
  }
 temp>>=1;
 }
 k_clk = 1;

     while(!k_clk);

     k_clk=1;
 k_data=1;
 if(k_clk==1)
 {delay_us();//30us
 }
 if(k_clk==1&&k_data==1)
 {k_data=0;
 nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();//delay10us;
    k_clk=0;
 nop();nop();nop();nop();nop();//delay5us;
 temp=x;
  for(i=0;i<8;i++)
  {k_clk=1;
  nop();nop();nop();nop();nop();//delay5us;
  char_temp=temp&0x01;
   if(char_temp==0x01)
   {
   k_data=1;
   }
   else
   {
   k_data=0;
   }
  nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();//delay10us;
  k_clk=0;
  nop();nop();nop();nop();nop();//delay5us;
  temp>>=1;
  }
 k_clk=1;
 nop();nop();nop();nop();nop();//delay5us;
 k_data=flat_check;
 nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();//delay10us;
 k_clk=0;
 nop();nop();nop();nop();nop();//delay5us;
 k_clk=1;
 nop();nop();nop();nop();nop();//delay5us;
 k_data=1;
 nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();//delay10us;
 k_clk=0;
 nop();nop();nop();nop();nop();//delay5us;
 k_clk=1;
 delay_us();
 k_clk=1;
 k_data=1;
 if(k_clk==1&&k_data==0)
 {
 return;//goto receive PC of data 
 }
 }
}

     

    /*****************************************************************************************
串行通讯
采用11位带奇偶效检串口异步通信
******************************************************************************************/
/******串口发送***********/
/*
void series_sent(uchar keyword)
{uchar i,key_L;
 uint j;
 bit odd=0;
 key_L=keyword;
 for(i=0;i<8;i++)
 {odd=odd ^ key_L^7;
 key_L<<=1;
 }
SBUF=keyword;
TB8=odd;//odd=1为奇数 ,odd=0为偶数
while(TI==0);
for(j=0;j<500;j++);
  
 }

    */

    /****************串口中断***************************/
/*
void UART() interrupt 4 using 2
{bit odd,odd_check;
uchar i, buf;

    if(RI)
{
 buf=SBUF;
 odd=RB8;
 for(i=0;i<8;i++)
 {odd_check=odd_check ^ buf ^7;
 buf<<=1;
 }
 if(odd_check!=odd)//校验出错发送错误代码0x55
 {
  
  SBUF=0x55;//错误代码0x55
  while(!TI);//等待发送完成
  TI=0;//清除发送标志
 }
 else
 {*receive_buf=SBUF;//将来自计算机的数据保存
 }
 RI=0;//清除接收标志
}
}

    */
/************************************************************
//mcu初始化
**************************************************************/
void ini(void)
{
TMOD=0X20;                /*定时器1八位自动重装*/
TL1=0XFA;TH1=0XFA;        /*12MHz,9600波特,误差8.5%*/
//SCON=0Xd8;PCON=0X10;      /*11位异步,定时器控制*/
//TR1=1;
  AUXR=0xbf;        //12T:0xbf    1T:0x40
  RCAP2H=0XFF;    //设T2为波特率发生器  12M----9600----0xFFD9
  RCAP2L=0Xd9;
  TR2=1;
// T2IE=1;
// T2RSE=1;
  ET2=1;
  TCLK=1;
  RCLK=1;
  TMOD=0x11;  //设T1为定时方式1,设T0为定时方式1
  TH1=0xec;  //5ms
  TL1=0X78;
  TH0=0xff;  //100us  ff9b
  TL0=0xaa;
  PCON=0x00;
//  SCON=0xD0;      //串行口工作方式3
//  ES=1;            //开串行口中断
  EA=1;
  ET0=1;          //T0开中断
  ET1=1;          //T1开中断
  IT0=1;  //外部中断0边沿触发, 
  EX0=1;//中断允许
  IT1=1;  // 外部中断1边沿触发?
  EX1=1;//中断允许
  TR1=1;          //启动T1
  TR0=1;          //启动T0
}

    /**********看门狗***************/
void watchdog()
{
 WDT_CONTR = 0x3f;
}

    /***************************/
void main(void)
{uchar chg_code,key;

    
ini();
init_key();
watchdog();//看门狗

     for(;;)
 { 
// key=scankb();//键盘扫描
    key= read_key();
 chg_code=change_code(key);//代码转换
// series_sent(chg_code);//串口发送
 ps_send(chg_code);//PS/2发送
 watchdog();
 }

    }


推荐阅读

史海拾趣

CNC Tech公司的发展小趣事

CNC Tech公司的创立源于几位电子工程领域的资深专家对于高精度数控加工技术的共同追求。他们发现,随着电子行业的快速发展,对高精度、高效率的数控加工技术的需求日益迫切。于是,他们决定集结力量,共同创立CNC Tech公司,专注于研发和生产先进的数控加工设备。凭借着对技术的执着和热情,CNC Tech在创立初期就成功开发出多款具有竞争力的产品,奠定了其在行业内的技术基石。

Frequency Devices公司的发展小趣事

面对快速变化的市场需求,Frequency Devices公司展现出了敏锐的市场洞察力。在21世纪初,随着无线通信技术的快速发展,对高频电子元件的需求急剧增加。公司及时调整产品策略,加大了对无线通信领域高频产品的研发投入,并成功推出了一系列适用于手机、基站等通信设备的高频滤波器、功率放大器等关键元件。这些产品不仅满足了市场需求,还进一步巩固了公司在行业内的市场地位。

C&K Switches公司的发展小趣事

2022年,C&K Switches公司被Littelfuse以5.4亿美元的企业价值收购。Littelfuse是一家工业技术制造公司,致力于打造一个可持续、互联和更安全的世界。两家公司在工业、通讯以及车载领域有着相近的市场布局和业务高度互补。收购完成后,C&K成为Littelfuse电子业务部门的一部分,双方共同为客户提供更全面的解决方案。这一收购不仅加强了C&K的市场地位,还为其未来的发展注入了新的活力和机遇。

Fischer Elektronik公司的发展小趣事

Fischer Elektronik深知每个客户的需求都是独特的,因此公司非常注重提供客户定制化的解决方案。公司拥有一支专业的研发团队和先进的生产设备,能够根据客户的具体需求,设计并生产出符合其要求的产品。这种高度定制化的服务模式,赢得了众多客户的信赖和好评,也为公司赢得了更多的市场份额。

EXXELIA Group公司的发展小趣事

Fischer Elektronik深知每个客户的需求都是独特的,因此公司非常注重提供客户定制化的解决方案。公司拥有一支专业的研发团队和先进的生产设备,能够根据客户的具体需求,设计并生产出符合其要求的产品。这种高度定制化的服务模式,赢得了众多客户的信赖和好评,也为公司赢得了更多的市场份额。

Avalon Photonics公司的发展小趣事

Avalon Photonics深知技术创新是公司发展的核心动力。因此,公司每年都将大量资金投入研发领域,不断推动技术创新。公司研发团队积极探索新技术、新材料,在光子学领域取得了多项重要突破。这些技术创新不仅提升了Avalon产品的竞争力,也为公司在市场上赢得了良好的声誉。

问答坊 | AI 解惑

自适应无线电提高无线连接的频谱利用效率

现在的无线通信依赖大量的独立设备,每种设备都有自己的协议并在一个固定的频段上工作。因为这些设备彼此不能通信,所以它们一起创造的无线环境工作效率非常低。此外,每种设备的发射和接收都有可能对其它设备产生干扰,尤其是当高功率发射器与高灵 ...…

查看全部问答>

SDRAM工作原理

这里是一个SDRAM的工作原理,个人感觉还可以,拿出来大家看看。…

查看全部问答>

LINUX操作系统下MC55的问题

S3C2410上有两个串囗,一个接了超级终端,一个接了MC55,在S3C2410装了一个LINUX系统,如何在超级终端上操作MC55,我那个MC55模块没有串囗接囗的,MC55串囗只有接了S3C2410的一个串囗,请问能在LINUX系统下用超级终端直接操作MC55吗…

查看全部问答>

CE5.0下线程优先级

我做一个键盘鼠标驱动,开了一个线程采集数据.在CPU不忙时能几个毫秒采集一次,CPU很忙时,特别是打开media play进,采集间隔一下子就变成了几十毫秒.我的线程优先级用cesetthreadpriority曾经提到过0,还是不起作用,不知道还需要设置什么? 各位帮帮忙, ...…

查看全部问答>

急!急!急!请教一个关于udp通信的问题

我想在一个多任务程序中用udp方式实现任务之间的通信,应该属于在本地机上实现通信,不知道怎么做啊,把ip设成一样的127.0.0.1就可以了吗?…

查看全部问答>

watch window为什么不能看变量

程序是汇编语言,为什么添加变量到watch window总是说没有定义呢? 是不是只能看c语言的变量?…

查看全部问答>

USB may fail USB certification if the EPI module is operating

这个问题这么严重,勘误手册说尚未解决。这个意思岂不是EPI和USB模块不能同时使用了?…

查看全部问答>

电容式单触摸传感器套件

电容式单触摸传感器套件工具…

查看全部问答>

C2000晒晒 + Piccolo MCU experimenter kits 外加大量资料下载!

不多说,看图!东西是前段时间买的,最近一直忙别的,这个还是没开封的呢!同时也买了个350W通信电源,准备把它改成数控的。就用C2000控制!顺便给大家提供些资料,共同学习! [ 本帖最后由 phimas 于 2011-11-25 22:16 编辑 ]…

查看全部问答>

ti c2000与c2400的关系

大家好,小弟有个白痴级问题,ti的c2000系列与c2400以及2800有什么关系?如果ucosii移植到c2400的版本,能直接在c2000系列的tms320f28069芯片上运行吗?谢谢各位大牛!!!…

查看全部问答>