注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
梦之旅的个人空间 https://home.eeworld.com.cn/space-uid-217607.html [收藏] [复制] [分享] [RSS]
日志

梦之旅同学松鼠1.0学习笔记(三)之矩阵键盘

已有 1461 次阅读2011-6-10 14:02

  这几天事情比较多,所以就一直没有更新,呵呵,今天早上没课,把之前写好代码整理一下,顺便说下思路,发上来,供大家参考参考。

  首先,本矩阵键盘硬件连接如下:

 

    思路:

  我的思路如下,首先,把纵向三线设置为推挽输出,然后把横向三线设置为下拉输入,然后读取横向三线的值,如果有接口的读数为1,说明有按键按下了,把该值与0x07相与后放到scana,然后左移4位放到result中,这之后把横向三线设置为推挽输出,纵向三线设置为下拉输入,然后读取纵向三线的值,把相应的键值保存到scanb中,然后通过移位使得低四位表示的是相应的按键所在横向的值,然后与result相或放到result的低四位,这样得到的result高四位就是按键所在纵向的值,低四位就是按键所在横向的值,由此就可以检测到那个按键被按下了。

    效果:按下相应的键盘,四个led灯会显示各种不同的状态,hoho,一共有9种状态。

    #include "stm32f10x_lib.h"
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void delay(void);
u8 KEY_GPIO_Scanning(void);

int main(void)
{
#ifdef DEBUG
  debug();
#endif
 RCC_Configuration();//配置系统时钟
 NVIC_Configuration();  //配置  NVIC 和 Vector Table
GPIO_Configuration(); //使用的GPIO口

  //主循环
  while (1)
  {
    //循环扫描按键 按键按下时 对应的LED亮
    switch ( KEY_GPIO_Scanning() )
    {
      case(0x18):
        GPIO_SetBits(GPIOB, GPIO_Pin_12);
        GPIO_ResetBits(GPIOB, GPIO_Pin_13);
        GPIO_ResetBits(GPIOB, GPIO_Pin_14);
        GPIO_ResetBits(GPIOB, GPIO_Pin_15);
        break;
      case(0x12):
        GPIO_ResetBits(GPIOB, GPIO_Pin_12);
        GPIO_SetBits(GPIOB, GPIO_Pin_13);
        GPIO_ResetBits(GPIOB, GPIO_Pin_14);
        GPIO_ResetBits(GPIOB, GPIO_Pin_15);
        break;
      case(0x14):
        GPIO_SetBits(GPIOB, GPIO_Pin_12);
        GPIO_SetBits(GPIOB, GPIO_Pin_13);
        GPIO_ResetBits(GPIOB, GPIO_Pin_14);
        GPIO_ResetBits(GPIOB, GPIO_Pin_15);
        break;
      case(0x28):
        GPIO_ResetBits(GPIOB, GPIO_Pin_12);
        GPIO_ResetBits(GPIOB, GPIO_Pin_13);
        GPIO_SetBits(GPIOB, GPIO_Pin_14);
        GPIO_ResetBits(GPIOB, GPIO_Pin_15);
        break;
      case(0x24):
        GPIO_SetBits(GPIOB, GPIO_Pin_12);
        GPIO_ResetBits(GPIOB, GPIO_Pin_13);
        GPIO_SetBits(GPIOB, GPIO_Pin_14);
        GPIO_ResetBits(GPIOB, GPIO_Pin_15);
        break;
      case(0x48):
        GPIO_SetBits(GPIOB, GPIO_Pin_12);
        GPIO_SetBits(GPIOB, GPIO_Pin_13);
        GPIO_SetBits(GPIOB, GPIO_Pin_14);
        GPIO_ResetBits(GPIOB, GPIO_Pin_15);
        break;
      case(0x42):
        GPIO_ResetBits(GPIOB, GPIO_Pin_12);
        GPIO_ResetBits(GPIOB, GPIO_Pin_13);
        GPIO_ResetBits(GPIOB, GPIO_Pin_14);
        GPIO_SetBits(GPIOB, GPIO_Pin_15);
        break;
      case(0x44):
        GPIO_SetBits(GPIOB, GPIO_Pin_12);
        GPIO_ResetBits(GPIOB, GPIO_Pin_13);
        GPIO_ResetBits(GPIOB, GPIO_Pin_14);
        GPIO_SetBits(GPIOB, GPIO_Pin_15);
        break;
      case(0x22):
        GPIO_SetBits(GPIOB, GPIO_Pin_12);
        GPIO_SetBits(GPIOB, GPIO_Pin_13);
        GPIO_SetBits(GPIOB, GPIO_Pin_14);
        GPIO_SetBits(GPIOB, GPIO_Pin_15);
        break;
    }
   
  }
}
void RCC_Configuration(void)
{
  ErrorStatus HSEStartUpStatus;
  RCC_DeInit(); //将外设 RCC寄存器重设为缺省值
  RCC_HSEConfig(RCC_HSE_ON); //设置外部高速晶振(HSE)
  HSEStartUpStatus = RCC_WaitForHSEStartUp();//等待 HSE 起振

  if(HSEStartUpStatus == SUCCESS)
  {
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//预取指缓存使能
    FLASH_SetLatency(FLASH_Latency_2);//设置代码延时值  FLASH_Latency_2  2 延时周期
    RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置 AHB 时钟(HCLK) RCC_SYSCLK_Div1  AHB 时钟 =  系统时钟
    RCC_PCLK2Config(RCC_HCLK_Div2);//设置高速 AHB 时钟(PCLK2)  RCC_HCLK_Div2  APB1 时钟  = HCLK / 2 
    RCC_PCLK1Config(RCC_HCLK_Div2);   //设置低速 AHB 时钟(PCLK1)RCC_HCLK_Div2  APB1 时钟  = HCLK / 2
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); // PLLCLK = 8MHz * 9 = 72 MHz 设置 PLL 时钟源及倍频系数
    RCC_PLLCmd(ENABLE);//使能或者失能 PLL
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待指定的 RCC 标志位设置成功 等待PLL初始化成功
    {
    }
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟(SYSCLK) 设置PLL为系统时钟源
    while(RCC_GetSYSCLKSource() != 0x08)  //等待PLL成功用作于系统时钟的时钟源 0x00:HSI 作为系统时钟  0x04:HSE作为系统时钟   0x08:PLL作为系统时钟 
    {
    }
  }
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能或者失能 APB2 外设时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
}
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15 ;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  //LED端口设置为 推挽输出
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  //键盘 横向 三线
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  //键盘 纵向 三线
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
 
}

void GPIO_Reconfiguration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  //键盘 横向 三线
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  //键盘 纵向 三线
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
 
}


/*******************************************************************************
* Function Name  : KEY_GPIO_Scanning
* Description    : 依次扫描4个按键 使用一个u8变量的低4位存储扫描结果
* Input          : None
* Output         : None
* Return         : 扫描的结果 有效数据是低4位
*******************************************************************************/
u8 KEY_GPIO_Scanning(void)
{
 u8 result;
 u8 scana;  //单个按键扫描变量
       u8 scanb;  //四个按键总的情况变量 scan_sum低四位的每一位对应一个按键

 scana = 0;
        scanb = 0;

 result = 0;
 
 GPIO_SetBits( GPIOA, GPIO_Pin_3);
 GPIO_SetBits( GPIOB, GPIO_Pin_1);
 GPIO_SetBits( GPIOB, GPIO_Pin_2);
 

        //扫描按键
 scana = GPIO_ReadInputData(GPIOA);
 scana = scana &  0x07;
 
        //如果按键按下 则延迟 再扫描 然后根据判断处理
  if(scana)
   {
   delay();
  scana = GPIO_ReadInputData(GPIOA);
  scana = scana &  0x07;

  //翻转,二次读取

  GPIO_Reconfiguration();
  GPIO_SetBits( GPIOA, GPIO_Pin_0);
  GPIO_SetBits( GPIOA, GPIO_Pin_1);
  GPIO_SetBits( GPIOA, GPIO_Pin_2);
                GPIO_ResetBits( GPIOA, GPIO_Pin_3);
                GPIO_ResetBits( GPIOB, GPIO_Pin_1);
                GPIO_ResetBits( GPIOB, GPIO_Pin_2);

  scanb = GPIO_ReadInputData(GPIOA);
  scanb = scanb &  (1<<3);

  scanb |= ( GPIO_ReadInputData(GPIOB) & ( (1<<1) | (1<<2) ) ) ;

  result = scana << 4;
  result |= scanb;

  GPIO_Configuration();
  
   }
 return result;
}

void NVIC_Configuration(void)
{
#ifdef  VECT_TAB_RAM
  /* Set the Vector Table base location at 0x20000000 */
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
}


void delay()
{
  int i;
  for (i=0; i<0xffff; i++)
    ;
}

#ifdef  DEBUG
void assert_failed(u8* file, u32 line)
{
  while (1)
  {
  }
}
#endif

 

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章