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

📄 key_scan.c

📁 硬件平台:C8051F314 包括键盘扫描程序
💻 C
字号:
// 现在由本机判断按下-〉释放为一个完整的击键后报告给MAIN MCU

//------------------------------------------------------------------------------------
//
// FILE NAME      : KEY_SCAN.c
// TARGET DEVICE  : C8051F314
// CREATED ON     : 07/14/06
// CREATED BY     : Jzp
//
// Revision 1.0  
//
//------------------------------------------------------------------------------------

// 键盘扫描程序
// - Pinout:
//    P1.0 -> 键盘矩阵列选线0
//    P1.1 -> 键盘矩阵列选线1
//    P1.2 -> 键盘矩阵列选线2
//    P1.3 -> 键盘矩阵列选线3
//    P1.4 -> 键盘矩阵行选线0
//    P1.5 -> 键盘矩阵行选线1
//    P1.6 -> 键盘矩阵行选线2
//    P1.7 -> 键盘矩阵行选线3
//    P2.0 -> 键盘矩阵行选线4
//    P2.1 -> 键盘矩阵行选线5
//    P2.2 -> 键盘矩阵行选线6
//    P2.3 -> 键盘矩阵行选线7
//    P2.4 -> 键盘矩阵行选线8
//    P2.5 -> 键盘矩阵行选线9
//    P2.6 -> 键盘矩阵行选线10
//    P2.7 -> alpha LED
//    P0.6 -> 键盘中断请求线
//
//------------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------------
#include <c8051f310.h>                       // SFR declarations
#include <math.h>
#include "..\\inc\\DEFINE.H"
#define KEY_SCAN_GLOBALS
#include "..\\inc\\key_scan.h"

//------------------------------------------------------------------------------------
// 全局变量
//------------------------------------------------------------------------------------
UCHAR KbIsPressed;        //=0 表示有键值MAIN MCU未读取
UCHAR PreKeyValue;      //当次扫描前的按键键值
                        //=0x00 表示无按键
                        //=0xff 表示为无效值 
// 键盘状态变量
UCHAR AltKeyOn;            //=1 表示当前ALT键切换为ON状态,键值转义
UCHAR AlfaKeyOn;           //=1 表示当前alpha键切换为ON状态,键值转义
UCHAR CtlKeyOn;            //=1 表示当前ctrl键切换为ON状态,键值转义
UCHAR CapsKeyOn;           //=1 表示当前Caps键切换为ON状态,键值转义
UCHAR ShiftKeyOn;          //=1 表示当前Caps键切换为ON状态,键值转义
UCHAR KbIsValid;           //=1 表示缓冲当前为有效值

UCHAR xdata KeyBlOn_Count;       //键盘背光打开计时
UCHAR xdata second;              // 秒计时
UCHAR xdata intcount;            // 10ms interrupt counter
UCHAR xdata KeyDelayCount;
//UCHAR KeyBuffer[8];        //记录按键扫描码,当按键为通码时,第二个字节放扫描码,第一个
                           //字节放0xd0,该字节是内部标识符,iic发送程序通过它判断需发送机个字节

extern UINT Tmr0Reload;
extern UCHAR Tmr0High;
extern UCHAR Tmr0Low;

//------------------------------------------------------------------------------------
// 函数原型声明
//------------------------------------------------------------------------------------
UCHAR GetKeyMatrix(void);
void KEY_ROW_LOW(UCHAR index);

//SCHAR OutputPortBit(char PortNum, char Bit, char Value);
//------------------------------------------------------------------------------------
// 常量定义
//------------------------------------------------------------------------------------
#define COLNUM 4
#define ROWNUM 11
//------------------------------------------------------------------------------------
// 键码表 
//------------------------------------------------------------------------------------
UCHAR code key_table[][2] = {
	0x01, '1',//0x31,
	0x02, '2',//0x32,
	0x04, '3',//0x33,
	0x08, '4',//0x34,
	0x11, '5',//0x35,
	0x12, '6',//0x36,
	0x13, '7',//0x37,
	0x14, '8',//0x38,
	0x21, '9',//0x39,
	0x22, ':',//0x3a,
	0x24, ';',//0x3b,
	0x28, '<',//0x3c,
	0x31, '=',//0x3d,
	0x32, '>',//0x3e,
	0x34, '?',//0x3f,
	0x38, '@',//0x40,
	0x41, 'A',//0x41,
	0x42, 'B',//0x42,
	0x44, 'C',//0x43,
	0x48, 'D',//0x44,
	0x51, 'E',//0x45,
	0x52, 'F',//0x46,
	0x54, 'G',//0x47,
	0x58, 'H',//0x48,
	0x61, 'I',//0x49,
	0x62, 'J',//0x4a,
	0x64, 'K',//0x4b,
	0x68, 'L',//0x4c,
	0x71, 'M',//0x4d,
	0x72, 'N',//0x4e,
	0x74, 'O',//0x4f,
	0x78, 'P',//0x50,
	0x81, 'Q',//0x51,
	0x82, 'R',//0x52,
	0x84, 'S',//0x53,
	0x88, 'T',//0x54,
	0x91, 'U',//0x55,
	0x92, 'V',//0x56,
	0x94, 'W',//0x57,
	0x98, 'X',//0x58,
	0xa1, 'Y',//0x59,
	0xa2, 'Z',//0x5a,
	0xa4, '[',//0x5b,
	0xa8, '\\',//0x5c,
	0xff, 0
	};

//UCHAR code key_table[][2] = {
//	0x01, 1,
//	0x02, 2,
//	0x04, 3,
//	0x08, 4,
//	0x11, 5,
//	0x12, 6,
//	0x13, 7,
//	0x14, 8,
//	0x21, 9,
//	0x22, 10,
//	0x24, 11,
//	0x28, 12,
//	0x31, 13,
//	0x32, 14,
//	0x34, 15,
//	0x38, 16,
//	0x41, 17,
//	0x42, 18,
//	0x44, 19,
//	0x48, 20,
//	0x51, 21,
//	0x52, 22,
//	0x54, 23,
//	0x58, 24,
//	0x61, 25,
//	0x62, 26,
//	0x64, 27,
//	0x68, 28,
//	0x71, 29,
//	0x72, 30,
//	0x74, 31,
//	0x78, 32,
//	0x81, 33,
//	0x82, 34,
//	0x84, 35,
//	0x88, 36,
//	0x91, 37,
//	0x92, 38,
//	0x94, 39,
//	0x98, 40,
//	0xa1, 41,
//	0xa2, 42,
//	0xa4, 43,
//	0xa8, 44,
//	0xff, 0
//	};
	
/************************************************************
-----键盘扫描及取键值程序-----
功能: 扫描键盘
入口参数: 无
出口参数:有按键则键值=阵列号,无按键则键值=0xff 
//UCHAR GetKeyMatrix(void)
*************************************************************/

UCHAR GetKeyMatrix(void)
{
  UCHAR i;//,j;
  UCHAR ColValue = 0;    //列线0-3的读取电平存储值
  UCHAR CurKeyValue;  //初始化无按键
  // 扫描开始
  CurKeyValue = PreKeyValue;
  KEY_ROW_ALL_LOW;           //初始行线全部行线输出低电平,试探有无按键 
  ColValue = P1&0x0f;        //读取列线电平
  if(ColValue == 0x0f)       //当前无按键
  {
    if(KbIsPressed == 0)     //之前无按键
    {
      CurKeyValue = 0xff;    //=0x00 表示无按键
      PreKeyValue = 0xff; 
      return CurKeyValue;    //返回无效键值
    }
    else                     //有按键释放 
    {
      KbIsPressed = 0;
      KbIsValid = 1;         //等待MAIN MCU读取
      return CurKeyValue;
    }
  }
  //开始逐行扫描 
  for(i = 0; i < ROWNUM; i++)
  {
    KEY_ROW_LOW(i);          //驱动第i列行线
    ColValue = P1&0x0f;      //读取列线电平
    if(ColValue != 0x0f)
    {
      KeyDelayCount = 2;     //防抖动20ms
      while(KeyDelayCount == 0);       
      ColValue = P1&0x0f;    //读取列线电平
      if(ColValue != 0x0f)   //确实有键按下
      {
        KeyBlOn_Count = 4;   // 背光延时重新计数
        KbBlCtl = 1;         // 点亮键盘背光
        CurKeyValue = ((i << 4)&0xf0) + (~ColValue&0x0f);
        KbIsPressed = 1;
        break;
      }  //end if(ColValue != 0x0f) 2
    }  //end if(ColValue != 0x0f) 1
  }  //end for
  PreKeyValue = CurKeyValue; // 替换原键值
  return CurKeyValue;
}

/************************************************************
-----键值转换为扫描码处理程序-----
功能:对特殊功能键作相应处理
入口参数:GetKeyMatrix函数取得的键值
影响:根据键值将相应的特殊键状态赋值,处理有优先级
//void SpeKeyDeal(UCHAR key)
*************************************************************/

void SpeKeyDeal(UCHAR key)
{
  switch(key){
  	case 0x21:               // 有CTRL键切换动作
  		if(CtlKeyOn == 1) 
  		  CtlKeyOn = 0;
  		else
  		  CtlKeyOn = 1;
  		break;
    case 0x22:               // 有ALT键切换动作
    	if(AltKeyOn == 1)
    	  AltKeyOn = 0;
    	else
    	  AltKeyOn = 1;
      break;
    case 0x24:               // 有ALPHA键切换动作
    	if(AlfaKeyOn == 1)
    	  AlfaKeyOn = 0;
    	else
    	  AlfaKeyOn = 1;
      break;
    case 0x88:               // 有SHIFT键切换动作
    	if(ShiftKeyOn == 1)
    	  ShiftKeyOn = 0;
    	else
    	  ShiftKeyOn = 1;
      break;
    default:                 // 其他键不做处理
      break;
  	}
}
 
/************************************************************
键值转换为扫描码处理程序
//void PutKbBuff(UCHAR KeyVal)
功能:将键值转换为扫描码,及其无效键处理。
*************************************************************/
/************************************************************
-----键值转换为扫描码处理程序-----
功能:将键值转换为扫描码,及其无效键处理
入口参数:查键值转换表所得扫描码
影响:将扫描码填入KeyBuffer[],等待主机查询
//void SpeKeyDeal(UCHAR key)
*************************************************************/

void PutKbBuff(UCHAR KeyVal)
{
  if((AltKeyOn == 1) || (AlfaKeyOn == 1) || (ShiftKeyOn == 1) || (CtlKeyOn == 1))
  {
    if(AltKeyOn == 1)                     // ALT组合键
    {
      KeyBuffer[0] = '!';//0x21;//0xb0;
      KeyBuffer[1] = KeyVal;
    }
    else if(AlfaKeyOn == 1)               // 字母键
    {
      if(ShiftKeyOn == 1)
      {
        KeyBuffer[0] = '"';//0x22;//0xc0;              // 大写
        KeyBuffer[1] = KeyVal;
      }
      else
      {  
      	KeyBuffer[0] = '#';//0x23;//0xd0;              // 小写
        KeyBuffer[1] = KeyVal;
      }
    }
    else if(ShiftKeyOn == 1)              // shift组合键
    {
      KeyBuffer[0] = '$';//0x24;//0xe0;
      KeyBuffer[1] = KeyVal;
    }
    else if(CtlKeyOn == 1)              // ctrl组合键
    {
      KeyBuffer[0] = '%';//0x25; //0xf0;
      KeyBuffer[1] = KeyVal;
    }
  }
  else
  {
    KeyBuffer[0] = '&';//0x26;//0xa0;                 // 常规按键
    KeyBuffer[1] = KeyVal;
  }
}

/************************************************************
-----查表程序-----
功能: 通过行列号查找键号
参数: 行列号(ex。0x31 表示第3行第1列) 
//说明: 
//UCHAR lookup_table(UCHAR matrix)
*************************************************************/

UCHAR lookup_table(UCHAR matrix)
{
  UCHAR i;
  UCHAR ret_key;
  for(i = 0; ((i < 44) && (key_table[i][0] != 0xff)); i++)
  {
    if(key_table[i][0] == matrix )
    {
      ret_key = key_table[i][1];        // 找到行列号,转换成键号
      break;
    }
  }
  return ret_key;
}

/************************************************************
-----键扫描任务-----
功能: 主程序调用该任务
参数: 行列号(ex。0x31 表示第3行第1列) 
//说明: 
//void task_keyscan(void)
*************************************************************/

void task_keyscan(void)
{
  UCHAR i;
  UCHAR temp_mat,temp_code;
  temp_mat = 0;
  temp_code = 0;
  
  temp_mat = GetKeyMatrix();   //取得键盘阵列号
  if(KbIsValid == 1)
  {
    SpeKeyDeal(temp_mat);
    temp_code = lookup_table(temp_mat);    //转换为键号
    PutKbBuff(temp_code);
    KbIrqOut = 0;                // 发起中断
    for(i = 0; i < 10; i++);
    KbIrqOut = 1;
  }
}

/************************************************************
-----键扫描相关变量初始化-----
功能: 主程序调用该函数
参数: 
//说明: 
//void init_keyscan(void)
*************************************************************/

void init_keyscan(void)
{
  UCHAR i;
  for(i = 0; i < 2; i++)
    KeyBuffer[i] = 0;
  KbIsPressed = 0;
  AltKeyOn = 0;            //=1 表示当前ALT键切换为ON状态,键值转义
  AlfaKeyOn = 0;           //=1 表示当前alpha键切换为ON状态,键值转义
  CtlKeyOn = 0;            //=1 表示当前ctrl键切换为ON状态,键值转义
  CapsKeyOn = 0;           //=1 表示当前Caps键切换为ON状态,键值转义
  ShiftKeyOn = 0;          //=1 表示当前Caps键切换为ON状态,键值转义
  KbIsValid = 0;           //=1 表示缓冲当前为有效值     
  KbBlCtl = 1;             //复位时点亮背光
  KeyBlOn_Count = 4;       //背光点亮定时4秒
}


/************************************************************
-----行线输出扫描程序-----
说明: 根据index,将指定行线驱动低电平,其余为高电平
       
//void KEY_ROW_LOW(UCHAR index)
*************************************************************/

void KEY_ROW_LOW(UCHAR index)
{
//  UCHAR i;
  UCHAR p1_shift;
  UCHAR p2_shift;
  UCHAR p2_bit7;
  UCHAR temp;
  
  p2_bit7 = P2&0x80;         // 暂存P2^7电平
  p1_shift = 0x10;           // 初始化p1移位初始值
  p2_shift = 0x01;           // 初始化p2移位初始值,因为P2.7为LED驱动,所以要保持他的值不变
  
//  for(i = 0; i < index; i++)
//  {
  if(index < 4)
  { 
    p1_shift = p1_shift << index;
    p1_shift = ~p1_shift;
    P1 = p1_shift;
    P2 = (P2&0x80)|0x7f;
  }
  else                   //if((i >= 4) && (i < 7))
  {
    temp = index;
	temp = ~(~temp + 4);      // 作减4求绝对值运算
//	  p2_shift <<= abs(4 - index);
    p2_shift <<= temp;
    P2 = (~p2_shift) | p2_bit7;
    P1 = 0xff;
  }
//  }
}


void Timer0_ISR (void) interrupt 1
{
  TR0 = 0;
//  TMR0 = Tmr0Reload;
  TH0 = Tmr0High;
  TL0 = Tmr0Low;
  if(KeyDelayCount != 0) KeyDelayCount--;
  if(++intcount == 100)
  { 
    intcount = 0;
//    if(KeyBlOn_Count != 0) KeyBlOn_Count--;
//    if(KeyBlOn_Count != 0)   
//    {
//      KbBlCtl = 1;     // 点亮背光
//    }
//    else
//    {
//      KbBlCtl = 0;     // 关闭背光
//    }
//    KbBlCtl = ~KbBlCtl;
    AlphaLed = ~AlphaLed;
  }
  TF0 = 0;
  TR0 = 1;
}

⌨️ 快捷键说明

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