硬汉嵌入式论坛

 找回密码
 立即注册
查看: 6279|回复: 3
收起左侧

[有问必答] STM32F10x按矩阵键盘疑问

[复制链接]

13

主题

20

回帖

59

积分

初级会员

积分
59
发表于 2014-8-26 22:37:24 | 显示全部楼层 |阅读模式
如下图,是我做的一个键盘矩阵(原本是6x6的,这里为说明精减了),想用中断的方式来完成。如下图,列线PC11-13先置为0,一旦有键按下,就会产生下降沿中断。然后在中断中置相关标志位,再进行按键扫描。程序大致如下:
未命名.JPG


struct io_port {
  GPIO_TypeDef *GPIO_x;
  uint16_t GPIO_pin;
};

static struct io_port key_input[2] = {
  {GPIOC, GPIO_Pin_5},
  {GPIOC, GPIO_Pin_6},
};

static struct io_port key_output[3] = {
  {GPIOC, GPIO_Pin_11},
  {GPIOC, GPIO_Pin_12},
  {GPIOC, GPIO_Pin_13}
};

volatile uint8_t it_flag = 0;
volatile uint8_t key[3][2];

void gpio_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC, ENABLE);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                //输入
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                //输出
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  
  GPIO_ResetBits(GPIOC, GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13);   //输出全置低,以便按键按下产生下降沿中断
}

void nvic_init(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  EXTI_InitTypeDef EXTI_InitStructure;  

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);      

  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;        //外部中断9-5
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;    //抢占优先级 0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        //使能
  NVIC_Init(&NVIC_InitStructure);

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5 | GPIO_PinSource6);

  EXTI_InitStructure.EXTI_Line = EXTI_Line5 | EXTI_Line6;    //PC5,PC6 作为键盘检测状态
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;        //中断模式
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;    //下降沿触发
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
}

void EXTI9_5_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line5) != RESET)                  //判别是否有键按下
  {
    EXTI_ClearITPendingBit(EXTI_Line5);                      //清除中断请求标志
   
    it_flag = 1;      //置标志位
  }

  //EXTI_Line6以下略
  ...
}

void key_scan(void)
{
  uint8_t i;

  if (1 == it_flag)
  {
    it_flag = 0;      //清标志位
    for (i = 0; i < 3; i++)
    {
      GPIO_SetBits(key_output.GPIO_x, key_output.GPIO_pin);  //输出引脚依次置1
     
      if (Bit_SET == GPIO_ReadInputDataBit(key_input[0].GPIO_x, key_input[0].GPIO_pin))
      {
        key[0] = 1;    //按下的键位置1
      }
      else
      {
        key[0] = 0;
      }
      GPIO_ResetBits(key_output.GPIO_x, key_output.GPIO_pin); //重新置0,以便下次按下扫描
    }
  }

  //EXTI_Line6以下略
  ......
}

void main(void)
{
  gpio_init();
  nvic_init();

  while(1)
  {
    //去抖先不理了,只是说明下
    key_scan();  //扫描按键
  }  
}
现在问题是,一按下某个按键后,在按键扫描中,
会先GPIO_SetBits(key_output.GPIO_x, key_output.GPIO_pin);  //输出引脚依次置1
再GPIO_ResetBits(key_output.GPIO_x, key_output.GPIO_pin); //重新置0,以便下次按下扫描
这样不是又会在行线PC5上再次产生下降沿么?从而又重新置标置位,又从新扫描了?是不是我的这个处理过程有问题呢?大家是怎么处理键盘中断扫描的?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107604
QQ
发表于 2014-9-9 17:58:55 | 显示全部楼层
不好意思啊,楼主,才看到你的代码。
回复

使用道具 举报

13

主题

20

回帖

59

积分

初级会员

积分
59
 楼主| 发表于 2014-9-15 11:54:55 | 显示全部楼层

回 eric2013 的帖子

eric2013:不好意思啊,楼主,才看到你的代码。 (2014-09-09 17:58) 
感觉中断对按键去抖,不好控制啊。难道一中断就关中断再扫?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107604
QQ
发表于 2014-9-15 18:48:30 | 显示全部楼层

回 pigy0754 的帖子

pigy0754:感觉中断对按键去抖,不好控制啊。难道一中断就关中断再扫? (2014-09-15 11:54) 
必须得把中断关闭,要不按键抖动会使得重复进入中断。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-6-7 21:49 , Processed in 0.250691 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表