基于STM32F407的4*4矩阵按键代码实现

注:第一篇文章,如有不足之处,敬请谅解

本文是通过寄存器的方式实现4*4按键的输入,采用逐行扫描的方式,并编写实现单次点击或者长按只接受一次数据。

4*4按键驱动

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

头文件:

#ifndef __KEY_H
#define __KEY_H

#include "stm32f4xx.h"

extern u8 only;

void Key_Init(void);
int Key_Scan(void);

#endif

驱动代码:

#include "key.h"

u8 only;                   //一次按键只打印一次标志位

/*********************************************************************
*按键用的PC6-PC9,PC11,PB6,PE5,PE6
*PC6-PC9为推挽输出
*PC11,PB6,PE5,PE6为下拉输入
*********************************************************************/

void Key_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
     
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);                       //使能C端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;     
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;                               //输出模式
    GPIO_InitStructure.GPIO_OType    = GPIO_OType_PP;                               //推挽式输出
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_UP;                                   //上拉
    GPIO_InitStructure.GPIO_Speed    = GPIO_Speed_50MHz;                               //50MHZ
     GPIO_Init(GPIOC, &GPIO_InitStructure);                                       //初始化
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);          //使能C端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;      
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN;                      //输入模式
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_DOWN;                  //下拉
     GPIO_Init(GPIOC, &GPIO_InitStructure);                          //初始化
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);          //使能B端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;      
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN;                      //输入模式
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_DOWN;                  //下拉
     GPIO_Init(GPIOB, &GPIO_InitStructure);                          //初始化
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);          //使能E端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;      
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN;                      //输入模式
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_DOWN;                  //下拉
     GPIO_Init(GPIOE, &GPIO_InitStructure);                          //初始化    

}


/*********************************************************************
*函数说明: 按键扫描
*返回值  :  按键值
*参数    :  void
**********************************************************************/
int Key_Scan(void)
{
    int keyValue=99;                                    //按键值

      GPIO_Write(GPIOC,(GPIOC->ODR & 0xfc3f )| 0x0040);//让PC6-9输出0001,检测第四行
      if((GPIOC->IDR & 0x0800) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOC->IDR & 0x0800) != 0x0000)
          {
              only = 1;
              while((GPIOC->IDR & 0x0800) != 0x0000);
              keyValue='D';
          }
      }
      if((GPIOB->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOB->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOB->IDR & 0x0040) != 0x0000);
              keyValue='#';
          }
      }
      if((GPIOE->IDR & 0x0020) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0020) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0020) != 0x0000);
              keyValue=0;
          }
      }
      if((GPIOE->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0040) != 0x0000);
              keyValue='*';
          }
      }
      
      GPIO_Write(GPIOC,(GPIOC->ODR & 0xfc3f )| 0x0080);//让PC6-9输出0010,检测第三行
      if((GPIOC->IDR & 0x0800) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOC->IDR & 0x0800) != 0x0000)
          {
              only = 1;
              while((GPIOC->IDR & 0x0800) != 0x0000);
              keyValue='C';
          }
      }
      if((GPIOB->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOB->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOB->IDR & 0x0040) != 0x0000);
              keyValue=9;
          }
      }
      if((GPIOE->IDR & 0x0020) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0020) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0020) != 0x0000);
              keyValue=8;
          }
      }
      if((GPIOE->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0040) != 0x0000);
              keyValue=7;
          }
      }
      
      GPIO_Write(GPIOC,(GPIOC->ODR & 0xfc3f )| 0x0100);//让PC6-9输出0100,检测第二行
      if((GPIOC->IDR & 0x0800) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOC->IDR & 0x0800) != 0x0000)
          {
              only = 1;
              while((GPIOC->IDR & 0x0800) != 0x0000);
              keyValue='B';
          }
      }
      if((GPIOB->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOB->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOB->IDR & 0x0040) != 0x0000);
              keyValue=6;
          }
      }
      if((GPIOE->IDR & 0x0020) != 0x0000)
      {
          delay_ms(5);//延时消抖
           if((GPIOE->IDR & 0x0020) != 0x0000)
           {
              only = 1;
              while((GPIOE->IDR & 0x0020) != 0x0000);
              keyValue=5;
           }
      }
      if((GPIOE->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0040) != 0x0000);
              keyValue=4;
          }
      }
      
      GPIO_Write(GPIOC,(GPIOC->ODR & 0xfc3f )| 0x0200);//让PC6-9输出1000,检测第一行
      if((GPIOC->IDR & 0x0800) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOC->IDR & 0x0800) != 0x0000)
          {
              only = 1;
              while((GPIOC->IDR & 0x0800) != 0x0000);
              keyValue='A';
          }
      }
      if((GPIOB->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOB->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOB->IDR & 0x0040) != 0x0000);
              keyValue=3;
          }
      }
      if((GPIOE->IDR & 0x0020) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0020) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0020) != 0x0000);
              keyValue=2;
          }
      }
      if((GPIOE->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0040) != 0x0000)
          {              
              only = 1;
              while((GPIOE->IDR & 0x0040) != 0x0000);
              keyValue=1;
          }
      }
      
    return keyValue;
}

主函数

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

int main(void)
{
    int     id;
    
    //设置NVIC分组(一个工程只能设置一个分组) 
    //第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    Delay_Init();
    Key_Init();

    while(1)
    {
        
        id = Key_Scan();
        delay_ms(50);
        if(only == 1)              //按一次打印一次
        {
            //这里写显示的方式,把接收显示出来
            only = 0;
        }
    }
}

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值