矩阵键盘的按键识别方法_矩阵键盘扫描程序

电子说

1.3w人已加入

描述

  矩阵键盘的按键识别方法

  矩阵键盘的按键识别方法来自简单日记网精选推荐。在学习有关矩阵键盘的时候,往往要学会矩阵键盘的按键识别方法,那么矩阵键盘的按键识别方法有哪些呢?小编带着你来了解。

  方法一:行扫描法

  1、判断键盘中有无键按下 将全部行线p1.4-p1.7置低电平,当然p1.0-p1.3为高电平(或许芯片内部已经将这些引脚它上拉),然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。若所有列线均为高电平,则键盘中无键按下。

  2、判断闭合键所在的位置 在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。

  方法二:先从p1口的高四位输出低电平,低四位输出高电平,从p1口的低四位读取键盘状态。再从p1口的低四位输出低电平,高四位输出高电平,从p1口的高四位读取键盘状态。将两次读取结果组合起来就可以得到当前按键的特征编码。

  矩阵键盘扫描程序

  使用芯片STM8S003

  所用端口:PD2~PD6, PA1~PA3

  其中,PD3~PD6为输出,PA1~PA3 / PD2为输入(默认上拉)

  /*

  PortCom BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0

  PD6 PD5 PD4 PD3 PD2 PA3 PA2 PA1

  */

  程序如下:

  /* 添加包含芯片的头文件 */

  #include《iostm8s103f3.h》

  volatile unsigned char CF[4]; //按键触发标志(表示4列,每一列同一行的

  //值是一样的但列标不一样来区分不同列的键)

  volatile unsigned char Cont[4];

  unsigned char KeyVal; //键值

  //unsigned char KeyOut[4] = {0xef,0xdf,0xbf,0x7f}; //4X4按输出端控制

  //unsigned char KeyOut[4] = {0x7f,0xbf,0xdf,0xef};

  unsigned char KeyOut[4] = {0x3f,0x5f,0x6f,0x77}; //两个端口组合4x4端口输出控制

  unsigned char PortCom; //两个端口组合的端口

  unsigned char cIn0,cIn1,cIn2,cIn3;

  /*******************************************************************************

  **函数名称:void delay(unsigned int ms) Name: void delay(unsigned int ms)

  **功能描述:大概延时

  **入口参数:unsigned int ms 输入大概延时数值

  **输出:无

  *******************************************************************************/

  void delay(unsigned int ms)

  {

  unsigned int x , y;

  for(x = ms; x 》 0; x--)

  for(y = 1000 ; y 》 0 ; y--);

  }

  /*

  **描述:新型4X4按键扫描程序 放在1ms-10ms中断内使用(十分稳定不需要再写消抖程序)

  **备注:按键弹起时 keyVal = 0 单键按下 keyVal 有16个值,你自己程序可以针对不同值

  **进行不同程序操作 keyVal单键值分别为

  **0x01,0x02,0x04,0x08,

  **0x11,0x12,0x14,0x18,

  **0x21,0x22,0x24,0x28,

  **0x31,0x32,0x34,0x38,

  */

  void Key_Head()

  {

  unsigned char ReadData[4];

  static unsigned char i;

  /*

  PortCom BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0

  PD6 PD5 PD4 PD3 PD2 PA3 PA2 PA1

  */

  cIn0 = 0;

  cIn1 = 0;

  cIn2 = 0;

  cIn3 = 0;

  if(++i》=4)i=0;

  // PortCom = KeyOut[i]|0x0f; //忽略低4位

  //输出扫描

  PD_ODR = KeyOut[i];

  //输入侦测

  cIn0 = PA_IDR_bit.IDR1;

  cIn1 = PA_IDR_bit.IDR2;

  cIn2 = PA_IDR_bit.IDR3;

  cIn3 = PD_IDR_bit.IDR2;

  PortCom = (cIn3《《3) | (cIn2《《2) | (cIn1《《1) | cIn0;

  ReadData[i] = (PortCom|0xf0)^0xff; //忽略高4位 取反

  CF[i] = ReadData[i] & (ReadData[i] ^ Cont[i]);

  Cont[i] = ReadData[i];

  //输出键值

  switch(CF[i])//第i列

  {

  case 0x08: KeyVal = ((i《《4)+8);break;

  case 0x04: KeyVal = ((i《《4)+4);break;

  case 0x02: KeyVal = ((i《《4)+2);break;

  case 0x01: KeyVal = ((i《《4)+1);break;

  default:KeyVal = 0;break;

  }

  delay(30);

  }

  /*******************************************************************************

  **函数名称:void ALL_LED_Init() Name: void ALL_LED_Init()

  **功能描述:初始化LED灯的IO口设为输出

  **入口参数:无

  **输出:无

  *******************************************************************************/

  void ALL_LED_Init()

  {

  //LED1 Init

  // PD_DDR_bit.DDR2 = 1; //设置端口PD-》2的输入输出方向寄存器为输出方向

  // PD_CR1_bit.C12 = 1; //设置PD2为推挽输出

  // PD_CR2_bit.C22 = 1; //设置PD2的输出最大速度为10MHZ

  //LED2 Init

  PC_DDR_bit.DDR7 = 1; //设置端口PC-》7的输入输出方向寄存器为输出方向

  PC_CR1_bit.C17 = 1; //设置PC7为推挽输出

  PC_CR2_bit.C27 = 1; //设置PC7的输出最大速度为10MHZ

  //LED3 Init

  PC_DDR_bit.DDR6 = 1; //设置端口PC-》6的输入输出方向寄存器为输出方向

  PC_CR1_bit.C16 = 1; //设置PC6为推挽输出

  PC_CR2_bit.C26 = 1; //设置PC6的输出最大速度为10MHZ

  //LED4 Init

  PC_DDR_bit.DDR3 = 1; //设置端口PC-》3的输入输出方向寄存器为输出方向

  PC_CR1_bit.C13 = 1; //设置PC3为推挽输出

  PC_CR2_bit.C23 = 1; //设置PC3的输出最大速度为10MHZ

  }

  /*******************************************************************************

  **函数名称:ALLKeyInit()

  **功能描述:配置Key1 , Key2 , Key3输入按键

  **入口参数:无

  **输出:无

  *******************************************************************************/

  void ALLKeyInit()

  {

  //PA1_Init

  PA_DDR_bit.DDR1 = 0; //GPA-》PIN3 设置为输入模式

  PA_CR1_bit.C11 = 1; //GPA-》PIN3 带上拉电阻输入

  PA_CR2_bit.C21 = 0; //GPA-》PIN3 禁止外部中断

  //PA2_Init

  PA_DDR_bit.DDR2 = 0; //GPA-》PIN3 设置为输入模式

  PA_CR1_bit.C12 = 1; //GPA-》PIN3 带上拉电阻输入

  PA_CR2_bit.C22 = 0; //GPA-》PIN3 禁止外部中断

  //PA3_Init

  PA_DDR_bit.DDR3 = 0; //GPA-》PIN3 设置为输入模式

  PA_CR1_bit.C13 = 1; //GPA-》PIN3 带上拉电阻输入

  PA_CR2_bit.C23 = 0; //GPA-》PIN3 禁止外部中断

  //PD2_Init

  PD_DDR_bit.DDR2 = 0; //GPD-》PIN3 设置为输入模式

  PD_CR1_bit.C12 = 1; //GPD-》PIN3 带上拉电阻输入

  PD_CR2_bit.C22 = 0; //GPD-》PIN3 禁止外部中断

  //PD3_Init

  PD_DDR_bit.DDR3 = 1; //GPD-》PIN3 设置为输入模式

  PD_CR1_bit.C13 = 1; //GPD-》PIN3 带上拉电阻输入

  PD_CR2_bit.C23 = 1; //GPD-》PIN3 禁止外部中断

  //PD4_Init

  PD_DDR_bit.DDR4 = 1; //GPD-》PIN3 设置为输入模式

  PD_CR1_bit.C14 = 1; //GPD-》PIN3 带上拉电阻输入

  PD_CR2_bit.C24 = 1; //GPD-》PIN3 禁止外部中断

  //PD5_Init

  PD_DDR_bit.DDR5 = 1; //GPC-》PIN5 设置为输入模式

  PD_CR1_bit.C15 = 1; //GPC-》PIN5 带上拉电阻输入

  PD_CR2_bit.C25 = 1; //GPC-》PIN5 禁止外部中断

  //PD6_Init

  PD_DDR_bit.DDR6 = 1; //GPC-》PIN5 设置为输入模式

  PD_CR1_bit.C16 = 1; //GPC-》PIN5 带上拉电阻输入

  PD_CR2_bit.C26 = 1; //GPC-》PIN5 禁止外部中断

  }

  int main(void)

  {

  CLK_CKDIVR = 0x00; //内部时钟为1分频

  ALL_LED_Init(); //调用LED1初始化函数

  ALLKeyInit(); //调用按钮初始化函数

  while(1)

  {

  Key_Head();

  switch(KeyVal)

  {

  case 0x01:

  {

  PC_ODR ^= 0x80; //异或取反LED2使其亮灭

  break;

  }

  case 0x02:

  {

  PC_ODR ^= 0x40; //异或取反LED3使其亮灭

  break;

  }

  case 0x04:

  {

  PC_ODR ^= 0x08; //异或取反LED4使其亮灭

  break;

  }

  case 0x08:

  {

  PC_ODR ^= 0x80; //异或取反LED2使其亮灭

  PC_ODR ^= 0x40; //异或取反LED3使其亮灭

  break;

  }

  case 0x11:

  {

  PC_ODR ^= 0x80; //异或取反LED2使其亮灭

  break;

  }

  case 0x12:

  {

  PC_ODR ^= 0x40; //异或取反LED3使其亮灭

  break;

  }

  case 0x14:

  {

  PC_ODR ^= 0x08; //异或取反LED4使其亮灭

  break;

  }

  case 0x18:

  {

  PC_ODR ^= 0x80; //异或取反LED2使其亮灭

  PC_ODR ^= 0x40; //异或取反LED3使其亮灭

  break;

  }

  case 0x21:

  {

  PC_ODR ^= 0x80; //异或取反LED2使其亮灭

  break;

  }

  case 0x22:

  {

  PC_ODR ^= 0x40; //异或取反LED3使其亮灭

  break;

  }

  case 0x24:

  {

  PC_ODR ^= 0x08; //异或取反LED4使其亮灭

  break;

  }

  case 0x28:

  {

  PC_ODR ^= 0x80; //异或取反LED2使其亮灭

  PC_ODR ^= 0x40; //异或取反LED3使其亮灭

  break;

  }

  case 0x31:

  {

  PC_ODR ^= 0x80; //异或取反LED2使其亮灭

  break;

  }

  case 0x32:

  {

  PC_ODR ^= 0x40; //异或取反LED3使其亮灭

  break;

  }

  case 0x34:

  {

  PC_ODR ^= 0x08; //异或取反LED4使其亮灭

  break;

  }

  case 0x38:

  {

  PC_ODR ^= 0x80; //异或取反LED2使其亮灭

  PC_ODR ^= 0x40; //异或取反LED3使其亮灭

  break;

  }

  default:

  {

  KeyVal = 0;

  break;

  }

  }

  }

  }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分