野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10388|回复: 3

一个矩阵按键扫描函数,求大家帮忙看看

[复制链接]
发表于 2017-1-19 13:48:49 | 显示全部楼层 |阅读模式
#include "key.h"
#include "stm32f4xx.h"
#include "usart.h"

unsigned int NUM;
unsigned char KeySta[4][4] = {  //全部矩阵按键的当前状态
    {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
};

//配置所使用的GPIO端口
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

/*开启按键GPIO口的时钟*/
RCC_AHB1PeriphClockCmd(KEY_IN_1_GPIO_CLK|KEY_IN_2_GPIO_CLK|KEY_IN_3_GPIO_CLK|KEY_IN_4_GPIO_CLK,ENABLE);
RCC_AHB1PeriphClockCmd(KEY_OUT_1_GPIO_CLK|KEY_OUT_2_GPIO_CLK|KEY_OUT_3_GPIO_CLK|KEY_OUT_4_GPIO_CLK,ENABLE);


//配置四个输入引脚
  /*选择按键的引脚1*/
GPIO_InitStructure.GPIO_Pin = KEY_IN_1_PIN ;
    /*设置引脚为输入模式*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    /*设置引脚上拉*/
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
   /*使用上面的结构体初始化按键*/
GPIO_Init(KEY_IN_1_GPIO_PORT, &GPIO_InitStructure);  
    /*选择按键的引脚2*/
GPIO_InitStructure.GPIO_Pin = KEY_IN_2_PIN;
    /*使用上面的结构体初始化按键*/
GPIO_Init(KEY_IN_2_GPIO_PORT, &GPIO_InitStructure);
    /*选择按键的引脚3*/
  GPIO_InitStructure.GPIO_Pin = KEY_IN_3_PIN;
    /*使用上面的结构体初始化按键*/
GPIO_Init(KEY_IN_3_GPIO_PORT, &GPIO_InitStructure);
   /*选择按键的引脚4*/
GPIO_InitStructure.GPIO_Pin = KEY_IN_4_PIN;
    /*使用上面的结构体初始化按键*/
GPIO_Init(KEY_IN_4_GPIO_PORT, &GPIO_InitStructure);

   //配置四个输出引脚
  /*选择按键的引脚1*/
GPIO_InitStructure.GPIO_Pin = KEY_OUT_1_PIN ;
    /*设置引脚为输出模式*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    /*设置引脚上拉输出*/
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
   /*设置为推挽输出*/
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
   /*使用上面的结构体初始化按键*/
GPIO_Init(KEY_OUT_1_GPIO_PORT, &GPIO_InitStructure);
    /*选择按键的引脚2*/
GPIO_InitStructure.GPIO_Pin = KEY_OUT_2_PIN ;
    /*使用上面的结构体初始化按键*/
GPIO_Init(KEY_OUT_2_GPIO_PORT, &GPIO_InitStructure);
     /*选择按键的引脚3*/
GPIO_InitStructure.GPIO_Pin = KEY_OUT_3_PIN ;
    /*使用上面的结构体初始化按键*/
GPIO_Init(KEY_OUT_3_GPIO_PORT, &GPIO_InitStructure);
    /*选择按键的引脚4*/
GPIO_InitStructure.GPIO_Pin = KEY_OUT_4_PIN ;
    /*使用上面的结构体初始化按键*/
GPIO_Init(KEY_OUT_4_GPIO_PORT, &GPIO_InitStructure);



/*
GPIO_ResetBits(KEY_OUT_1_GPIO_PORT,KEY_OUT_1_PIN);
GPIO_ResetBits(KEY_OUT_2_GPIO_PORT,KEY_OUT_2_PIN);
GPIO_ResetBits(KEY_OUT_3_GPIO_PORT,KEY_OUT_3_PIN);
GPIO_ResetBits(KEY_OUT_4_GPIO_PORT,KEY_OUT_4_PIN);
*/

}

//按键驱动函数,在主循环当中调用
void KeyDriver(void)
{
    unsigned int i, j;
    static unsigned int backup[4][4] = {  //按键值备份,保存前一次的值
        {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
    };
   
    for (i=0; i<4; i++)  //循环检测4*4的矩阵按键
    {
        for (j=0; j<4; j++)
        {
            if (backup[i][j] != KeySta[i][j])    //检测按键动作
            {
                if (backup[i][j] != 0)           //按键按下时执行动作
                {
         NUM=4*i+j;
         //KeyAction(NUM);
                  printf("当前按键值为:%d\n",NUM);//调用按键动作函数
                }
                backup[i][j] = KeySta[i][j];     //刷新前一次的备份值
            }
        }
    }
}
//按键扫描函数,中断当中调用
void KeyScan(void)
{
    unsigned int i;
    static unsigned int keyout = 0;   //矩阵按键扫描输出索引
    static unsigned int keybuf[4][4] = {  //矩阵按键扫描缓冲区
        {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF},
        {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF}
    };
    //将一行的4个按键值移入缓冲区
    keybuf[keyout][0] = (keybuf[keyout][0] << 1) | GPIO_ReadInputDataBit(KEY_IN_1_GPIO_PORT,KEY_IN_1_PIN);
    keybuf[keyout][1] = (keybuf[keyout][1] << 1) | GPIO_ReadInputDataBit(KEY_IN_2_GPIO_PORT,KEY_IN_2_PIN);
    keybuf[keyout][2] = (keybuf[keyout][2] << 1) | GPIO_ReadInputDataBit(KEY_IN_3_GPIO_PORT,KEY_IN_3_PIN);
    keybuf[keyout][3] = (keybuf[keyout][3] << 1) | GPIO_ReadInputDataBit(KEY_IN_4_GPIO_PORT,KEY_IN_4_PIN);
    //消抖后更新按键状态
    for (i=0; i<4; i++)  //每行4个按键,所以循环4次
    {
        if ((keybuf[keyout][i] & 0x0F) == 0x00)
        {   //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下
            KeySta[keyout][i] = 0;
        }
        else if ((keybuf[keyout][i] & 0x0F) == 0x0F)
        {   //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起
            KeySta[keyout][i] = 1;
        }
    }
    //执行下一次的扫描输出
    keyout++;        //输出索引递增
    keyout &= 0x03;  //索引值加到4即归零
    switch (keyout)  //根据索引值,释放当前输出引脚,拉低下次的输出引脚
    {
        case 0: GPIO_SetBits(KEY_OUT_4_GPIO_PORT,KEY_OUT_4_PIN); GPIO_ResetBits(KEY_OUT_1_GPIO_PORT,KEY_OUT_1_PIN); break;
        case 1: GPIO_SetBits(KEY_OUT_1_GPIO_PORT,KEY_OUT_1_PIN); GPIO_ResetBits(KEY_OUT_2_GPIO_PORT,KEY_OUT_2_PIN); break;
        case 2: GPIO_SetBits(KEY_OUT_2_GPIO_PORT,KEY_OUT_2_PIN); GPIO_ResetBits(KEY_OUT_3_GPIO_PORT,KEY_OUT_3_PIN); break;
        case 3: GPIO_SetBits(KEY_OUT_3_GPIO_PORT,KEY_OUT_3_PIN); GPIO_ResetBits(KEY_OUT_4_GPIO_PORT,KEY_OUT_4_PIN); break;
        default: break;
    }
}


从51的程序上移植过来的,但在挑战者的板子上连接总会自动在串口出现j=0时的按键值(即NUM=0,4,8,12随机出现),请大家帮忙看看问题出在哪里?谢谢啦!
回复

使用道具 举报

发表于 2017-1-19 17:09:49 | 显示全部楼层
参考这个:发一个基于状态机的STM32驱动矩阵键盘扫描程序
http://www.firebbs.cn/forum.php? ... 5219&fromuid=64
(出处: 野火论坛)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-1-19 18:36:30 | 显示全部楼层
flyleaf 发表于 2017-1-19 17:09
参考这个:发一个基于状态机的STM32驱动矩阵键盘扫描程序
http://www.firebbs.cn/forum.php?mod=viewthrea ...

好,谢谢
回复 支持 反对

使用道具 举报

发表于 2017-7-10 23:08:52 | 显示全部楼层
我的程序也是跟你差不多,但是不成功
不知道你的问题是否成功解决?能否将程序借我参考一下
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-22 19:41 , Processed in 0.034564 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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