⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key.c

📁 64位键盘扫描程序
💻 C
字号:
#include <reg51.h>
#include <absacc.h>
#include <intrins.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long

#define O   'O'
#define K   'K'
#define E   'E'
#define R   'R'
//--------------------------------------------------------
#define Wait_ti while(TI==0);TI=0              /*等待一帧发送完毕*/ 
#define Wait_ri while(RI==0);RI=0              /*等待一帧接收完毕*/
/**************************************
 -------------芯片管脚定义--------------
 ***************************************/
sbit   PowerLed=P1^4;
sbit   SHIFTLED=P1^5;
sbit   TestLED=P1^6;
sbit   Beep=P1^7;
sbit   KeyIn=P3^3;
sbit   KeyOut=P3^4;   //0:有键按下
//=====================================
#define OK 0
#define ER 1
//=====================================
/**********************************************
  -------------与主机通信命令名柄定义----------
  **********************************************/
#define GetKey          0x90  //有键直接返回键值
#define OpenBeep        0X91  //打开蜂鸣器,嘟... 嘟....,无返回值 
#define TestKey         0x94  //检测主板与键盘板IC的通信,回送主板Finish命令句柄
#define OpenMoneyBox    0x9a  //开钱箱命令句柄
#define CloseCat        0x9c  //关机
#define English         0x9d  //英文字母命令
#define Number          0x9e  //数字命令
//=====================================
bit err_rxd_flag;  //串口接收数据错误
bit rxd_flag;
uchar uc0;
uchar rs232buf[30];  //接收数据缓存
//=====================================
void rxd_order_232(); /*接收命令、数据*/
//=====================================
void ssio0(void) interrupt 4 using 1   //*串行中断0接收程序*
{
    ES=0;                               //*关串行中断*
    rxd_order_232();
    rxd_flag=1;
    ES=1;
}
//=====================================
void delayms(uint ti)                    //*延时程序~0.1ms,*
{              //延时时间=[ti(100)+1]*1.08us~=ti*0.108ms
  uint i;
  uchar t;
  for (i=0;i<ti;i++)
  {   
      t=99;
				  do{
			     t--;
				 }while(t!=0);
  } 
}
/*******************************************
 ---------- 初始化串行口来多机通信 ---------
 *******************************************/
void InitSBUF(void)     
{
		   TMOD=0x21;           /* T/C1定义为方式2 */
		   TL1=0xfd;            /* 9600时TH1,TL1=0xfd,1200时TH1,TL1=0XE8 */
		   TH1=0xfd; 
		   PCON=0x00;
		   SCON=0x50;           /* 串行口为方式1,SM2=1,TB8=0,RB8=0 */
		  /* SM0=0;*/
		   TR1=1;   ES=0;  /*ET0=1; ES=1; TR0=1;*/
		  /* SM2=1;   PS=1;*/
		   RI=0;    TI=0; EA=1;
}

//===================================
void sbuwork(uchar d)     /*发送一数据:c*/
{  
   uchar c;
   SBUF=d;             /*发送数据*/
   Wait_ti;             /*等待一帧发送完毕*/
   for(c=0;c<=0x05;c++);
}
//===================================================
/*void buzzer(uchar num,uchar on,uchar off)//蜂鸣器驱动
{  //unm:次数;on:鸣时间;off:停时间
   uchar n;
   if((num==0)|(on==0)){return;}
   for(n=0;n<(num-1);n++)
   {
      Beep=0;
      delayms(on);
      Beep=1;
      delayms(off);
   }
   Beep=0;
   delayms(on);
   Beep=1;
}*/
//=================================================
//
//          key 键盘操作程序
//
//==================================================
uchar key_press() //按键扫描程序
{ 
   uchar key_num;
   uchar n;
   uchar key_x;
   uchar keybuf[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
   key_num=0xff;
   if(P0==0xff){goto AD;}   //没键按下退出
   delayms(20);
   if(P0==0xff){goto AD;}   //没键按下
   KeyOut=1;                //消除按键标志
   Beep=0;
   for(n=0;n<8;n++)
   {
       P2=keybuf[n];
       if(P0<0xff){key_x=P0;key_num=n;goto AA;}
   }
   key_num=0xff;goto AD;//退出
AA:
   for(n=0;n<8;n++)
   {
       if(key_x==keybuf[n])
       {
            key_num=key_num*8;
            key_num=key_num+n;
            while(P0<0xff)//等待抬手
            {
               delayms(20);
            }
           // buzzer(1,120,2);
            goto AD;
       }
   }
AD:
   P0=0xff;
   P2=0x00;
   Beep=1;
   return key_num;
}
/********************************************************/ 
void rxd_by_232()     /*从232接收一个数据,并保存到uc0变量中*/
{ 
	   uchar counter; 
	   counter=0xfe;
	   do{
		     if(counter==0x00)
		     {RI=0;err_rxd_flag=1;return;}
		     else{counter--;}
	   }while(RI==0);
	   RI=0;   
	   uc0=SBUF;
	   err_rxd_flag=0;
}
//===============================
//--------------------------------------------------------------
/*命令格式:0x1b+0x10+命令句柄+数据包序号+命令长度+(命令参数)+CS*/
void rxd_order_232() /*接收命令、数据*/
{ 
		  uchar k,n;
		  uchar length;
		  RI=0;       
		  rs232buf[0]=SBUF;       /*接收包头:0x1b*/ 
		  rxd_by_232();           /*接收包头:0x10*/
		  if(err_rxd_flag==1){goto END;}
		  else{rs232buf[1]=uc0;} 
		  rxd_by_232();           /*接收命令句柄*/ 
		  if(err_rxd_flag==1){goto END;} 
		  else{rs232buf[2]=uc0;} 
		  rxd_by_232();           /*接收数据包序号*/ 
		  if(err_rxd_flag==1){goto END;} 
		  else{rs232buf[3]=uc0;}                
		  rxd_by_232();           /*接收数据长度*/  
		  if(err_rxd_flag==1){goto END;} 
		  else{rs232buf[4]=uc0;}   
		  length=uc0;          
		  if(length<5){n=length=5;}//goto AA;
		  else{_nop_();}  
		  for(k=5;k<(length+2);k++) 
		  {
		     rxd_by_232();       /*接收数据*/
		     if(err_rxd_flag==1){goto END;}                        
		     else{rs232buf[k]=uc0; }
		  }
END:
    TestLED=~TestLED;
}
//=============================================================
/* CRC-16的C程序. *ptr指向发送数据块的首地址, len是数据块以字节为单位的长度.*/
/* 按位计算CRC虽然代码简单,所占用的内存比较少,
   但其最大的缺点就是一位一位地计算会占用很多的处理器处理时间,*/
uint cal_crc(uchar len,uchar *ptr) //crc16计算
{
      uchar i;
      uint crc=0;
      while(len--!=0) 
      {
          for(i=0x80; i!=0; i/=2)
          {
             if((crc&0x8000)!=0) {crc*=2; crc^=0x8005;}     //* 余式CRC乘以2再求CRC *
             else{crc*=2;}
             if((*ptr&i)!=0){crc^=0x8005;}                   //* 再加上本位的CRC *
          }
           ptr++;
     }
     return(crc);
}
//===========================================
void return_OK(uchar d)
{
      uchar n;
      uint crc;
      rs232buf[0]=0x4f;
      rs232buf[1]=0x4b;          //OK
      rs232buf[2]=0x00;       //包序号 
      rs232buf[3]=0x05;       //命令长度
      rs232buf[4]=d;          //命令长度
      crc=cal_crc(5,rs232buf);//crc_16校验
      rs232buf[5]=crc>>8;
      rs232buf[6]=crc;
      for(n=0;n<7;n++){sbuwork(rs232buf[n]);}//发送数据
}
//===========================================
void main(void)
{
   uchar n;
   uchar handle;
   uchar key_num;
   uchar key_d;
   uchar KeyNum[20];
   ulong coun;
   InitSBUF();
   P0=0xff;
   P2=0x00;
   for(n=0;n<20;n++)
   {KeyNum[n]=0xff;}
   key_num=0xff;
   ES=1;             //开串行中断
   coun=0;
   rxd_flag=0;
   while(1)
   {
      SHIFTLED=KeyOut;
     // if(coun==0x0ff){coun=0;TestLED=~TestLED;}
      coun++;
      key_d=key_press();
      if(key_d<0xff)
      {key_num=key_d;} 
      /*if(key_d<0xff)      //有键值
      {
          for(n=0;n<16;n++)
          {
              if(KeyNum[n]==0xff)
              {
                  KeyNum[n]=key_d;
              }           
          }
      }
      if(KeyNum[15]<0xff){KeyNum[15]=0xff;}
      if((KeyNum[0]<0xff)&&(key_num==0xff))
      {
          key_num=KeyNum[0];
          for(n=0;n<15;n++)
          {
             KeyNum[n]=KeyNum[n+1];
          }
      }*/
      if(key_num==0xff){KeyOut=1;}
      else{KeyOut=0;}  //消除按键标志
      if(rxd_flag==1)
      {
          rxd_flag=0;
          ES=0;
          return_OK(key_num);

          handle=rs232buf[2];//命今字
          //for(n=0;n<12;n++){sbuwork(rs232buf[n]);}//发送数据
 /*         //return_OK(key_num);
          switch(handle)
          {
              case GetKey:        //返回键值
                 {  
                     return_OK(key_num);
                     break;
                 }
              case OpenBeep:     //开蜂鸣器
                 { 
                     buzzer(rs232buf[5],120,120);
                     return_OK(key_num);
                     break;
                 }
              case TestKey:
                 {
                     return_OK(key_num);
                     break;
                 }
              case OpenMoneyBox:
                 {
                     return_OK(key_num);
                     break;
                 }
              case CloseCat:
                 { 
                     return_OK(key_num);
                     break;
                 }
              case English:
                 {  
                     return_OK(key_num);
                     break;
                 }
              case Number:
                 {  
                     return_OK(key_num);
                     break;
                 } 
              default:{break;}
           }
           key_num=0xff;
           ES=1;
           for(n=0;n<30;n++){rs232buf[n]=0;}//发送数据*/
          key_num=0xff;
          ES=1;
       }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -