月初丶 2023-03-06 20:10 采纳率: 0%
浏览 76

STM32F1基于HAL库矩阵键盘扫描

我自己写了个矩阵键盘扫描的程序,但是不知为什么,每次按下一次按键,总是会串口返回三次信息,有时后两条为0,有时为536,872,356,百思不得其解,求指点
key.c

#include "key.h"
#include "delay.h"


/**
 * @brief       按键初始化函数
 * @param       无
 * @retval      无
 */
void key_init(void)
{
    /* 初始化行按键 */
    GPIO_InitTypeDef gpio_init_struct;  
    KEY_GPIO_CLK_ENABLE();                                      /* KEY时钟使能 */
    gpio_init_struct.Pin = KEY5 | KEY6 | KEY7 | KEY8;           /* 行引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
    HAL_GPIO_Init(KEY_GPIO_PORT, &gpio_init_struct);            /* 引脚模式设置,上拉输入 */
    /* 初始化列按键 */
    gpio_init_struct.Pin = KEY1 | KEY2 | KEY3 | KEY4;           /* 列引脚 */
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;                /* 输出 */
    gpio_init_struct.Pull = GPIO_NOPULL;                        /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
    HAL_GPIO_Init(KEY_GPIO_PORT, &gpio_init_struct);            /* KEY0引脚模式设置,上拉输入 */
    /* 初始化状态 */
    HAL_GPIO_WritePin(KEY_GPIO_PORT, KEY1|KEY2|KEY3|KEY4, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(KEY_GPIO_PORT, KEY5|KEY6|KEY7|KEY8, GPIO_PIN_SET);
}


void key_init2(void)
{
    /* 初始化行按键 */
    GPIO_InitTypeDef gpio_init_struct;  
    KEY_GPIO_CLK_ENABLE();                                      /* KEY时钟使能 */
    gpio_init_struct.Pin = KEY5 | KEY6 | KEY7 | KEY8;           /* 行引脚 */
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;                /* 输出 */
    gpio_init_struct.Pull = GPIO_NOPULL;                        /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
    HAL_GPIO_Init(KEY_GPIO_PORT, &gpio_init_struct);            /* KEY0引脚模式设置,上拉输入 */
    /* 初始化列按键 */
    gpio_init_struct.Pin = KEY1 | KEY2 | KEY3 | KEY4;           /* 列引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
    HAL_GPIO_Init(KEY_GPIO_PORT, &gpio_init_struct);            /* 引脚模式设置,上拉输入 */
    /* 初始化状态 */
    HAL_GPIO_WritePin(KEY_GPIO_PORT, KEY5|KEY6|KEY7|KEY8, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(KEY_GPIO_PORT, KEY1|KEY2|KEY3|KEY4, GPIO_PIN_SET);
}

uint8_t key_scan(void)
{
    uint8_t line, column, key_value;
    key_init ();
    /* 查寻键盘口的值是否变化,本来全是1,接通变0,!取反 */
    if(!HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY5) || 
       !HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY6) || 
       !HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY7) || 
       !HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY8))
    {
        if (HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY5) == 0)/* 第1行 */
        {
            line = 1;
        }
        else if (HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY6) == 0)/* 第2行 */
        {
            line = 2;
        }
        else if (HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY7) == 0)/* 第3行 */
        {
            line = 3;
        }
        else if (HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY8) == 0)/* 第4行 */
        {
            line = 4;
        }
        key_init2 ();
        /* 查寻键盘口的值是否变化,本来全是1,接通变0,!取反 */
       if(!HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY1) || 
          !HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY2) || 
          !HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY3) || 
          !HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY4))
       {
            if (HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY1) == 0)/* 第1列 */
            {
                column = 1;
            }
            else if (HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY2) == 0)/* 第2列 */
            {
                column = 2;
            }
            else if (HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY3) == 0)/* 第3列 */
            {
                column = 3;
            }
            else if (HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY4) == 0)/* 第4列 */
            {
                column = 4;
            }
        }
        key_value = 4*(line-1) + column;
        switch (key_value)
        {
            case 1:
                key_value = 1;
                break;
            case 2:
                key_value = 2;
                break;
            case 3:
                key_value = 3;
                break;
            case 4:
                key_value = 'A';/* 65 */
                break;
            case 5:
                key_value = 4;
                break;
            case 6:
                key_value = 5;
                break;
            case 7:
                key_value = 6;
                break;
            case 8:
                key_value = 'B';/* 66 */
                break;
            case 9:
                key_value = 7;
                break;
            case 10:
                key_value = 8;
                break;
            case 11:
                key_value = 9;
                break;
            case 12:
                key_value = 'C';/* 67 */
                break;
            case 13:
                key_value = '#';
                break;
            case 14:
                key_value = 0;
                break;
            case 15:
                key_value = '*';
                break;
            case 16:
                key_value = 'D';/* 68 */
                break;
        }
        /* 等待按键放开 */
        while(!HAL_GPIO_ReadPin(KEY_GPIO_PORT,KEY1) ||
              !HAL_GPIO_ReadPin(KEY_GPIO_PORT,KEY2) || 
              !HAL_GPIO_ReadPin(KEY_GPIO_PORT,KEY3) || 
              !HAL_GPIO_ReadPin(KEY_GPIO_PORT,KEY4));
       delay_ms (20);//延时20毫秒
    }
    return (key_value);
}


key.h


#ifndef __KEY_H
#define __KEY_H

#include "sys.h"

#define KEY_GPIO_PORT    GPIOA   /* 定义IO接口组A */
/* 第一列——第四列 PA3-PA0 */
#define KEY4    GPIO_PIN_0
#define KEY3    GPIO_PIN_1
#define KEY2    GPIO_PIN_2
#define KEY1    GPIO_PIN_3
/* 第一行——第四行 PA7-PA4*/
#define KEY8    GPIO_PIN_4
#define KEY7    GPIO_PIN_5
#define KEY6    GPIO_PIN_6
#define KEY5    GPIO_PIN_7

#define KEY_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)             /* PB口时钟使能 */


void key_init(void);                /* 按键初始化函数 */
uint8_t key_scan(void);             /* 按键扫描函数 */

#endif


exti.c

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"

uint8_t key_flag = 0;/* 按键标志位 */
/**
 * @brief       KEY1 外部中断服务程序
 * @param       无
 * @retval      无
 */
void KEY5_INT_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(KEY5_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY0所在中断线 的中断标志位 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY5_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

/**
 * @brief       KEY2-4 外部中断服务程序
 * @param       无
 * @retval      无
 */
void KEY6_8_INT_IRQHandler(void)
{
    /* 调用中断处理公用函数 清除KEY1所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    HAL_GPIO_EXTI_IRQHandler(KEY6_INT_GPIO_PIN);
    __HAL_GPIO_EXTI_CLEAR_IT(KEY6_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */


    HAL_GPIO_EXTI_IRQHandler(KEY7_INT_GPIO_PIN);
    __HAL_GPIO_EXTI_CLEAR_IT(KEY7_INT_GPIO_PIN);


    HAL_GPIO_EXTI_IRQHandler(KEY8_INT_GPIO_PIN);
    __HAL_GPIO_EXTI_CLEAR_IT(KEY8_INT_GPIO_PIN);
    
}

/**
 * @brief       中断服务程序中需要做的事情
                在HAL库中所有的外部中断服务函数都会调用此函数
 * @param       GPIO_Pin:中断引脚号
 * @retval      无
 */

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    switch(GPIO_Pin)
    {
        case KEY5_INT_GPIO_PIN:
            key_flag = 1;
            break;
        case KEY6_INT_GPIO_PIN:
            key_flag = 1;
            break;
        case KEY7_INT_GPIO_PIN:
            key_flag = 1;
            break;
        case KEY8_INT_GPIO_PIN:
            key_flag = 1;
            break;
    }
}
/**
 * @brief       外部中断初始化程序
 * @param       无
 * @retval      无
 */
void extix_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    KEY_GPIO_CLK_ENABLE();                                   /* KEY时钟使能 */

    gpio_init_struct.Pin = KEY5 | KEY6 | KEY7 | KEY8;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY5_INT_GPIO_PORT, &gpio_init_struct);    /* 行线配置为下降沿触发中断 */

    HAL_NVIC_SetPriority(KEY5_INT_IRQn, 2, 2);               /* 抢占2,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY5_INT_IRQn);                       /* 使能中断线1 */

    HAL_NVIC_SetPriority(KEY6_8_INT_IRQn, 2, 2);             /* 抢占2,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY6_8_INT_IRQn);                     /* 使能中断线15 */
}


exti.h

#ifndef __EXTI_H
#define __EXTI_H

#include "./SYSTEM/sys/sys.h"

/******************************************************************************************/
/* 引脚 和 中断编号 & 中断服务函数 定义 */ 

#define KEY5_INT_GPIO_PORT              GPIOA
#define KEY5_INT_GPIO_PIN               GPIO_PIN_4
#define KEY5_INT_IRQn                   EXTI4_IRQn
#define KEY5_INT_IRQHandler             EXTI4_IRQHandler

#define KEY6_INT_GPIO_PORT              GPIOA
#define KEY6_INT_GPIO_PIN               GPIO_PIN_5

#define KEY6_8_INT_IRQn                 EXTI9_5_IRQn
#define KEY6_8_INT_IRQHandler           EXTI9_5_IRQHandler

#define KEY7_INT_GPIO_PORT              GPIOA
#define KEY7_INT_GPIO_PIN               GPIO_PIN_6

#define KEY8_INT_GPIO_PORT              GPIOA
#define KEY8_INT_GPIO_PIN               GPIO_PIN_7



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


void extix_init(void);  /* 外部中断初始化 */

#endif




main.c

#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "exti.h"
extern uint8_t key_flag;


int main(void)
{
    uint8_t key_value;
    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    delay_init(72);                         /* 延时初始化 */
    usart1_init(115200);                    /* 串口1初始化 */
    extix_init();                           /* 外部中断初始化 */
    led_init();                             /* 初始化LED */
    key_init();                             /* 初始化按键 */
    oled_init();                            /* 初始化OLED */
    
    printf("初始化完成");
    while(1)
    {
            
        if (key_flag == 1)
        {
            key_flag = 0;
            key_value = key_scan();
            printf("键值:%d\r\n", key_value);
        }
    }
}



img

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-03-06 22:08
    关注
    评论

报告相同问题?

问题事件

  • 创建了问题 3月6日

悬赏问题

  • ¥100 求懂行的大ge给小di解答下!
  • ¥15 pcl运行在qt msvc2019环境运行效率低于visual studio 2019
  • ¥15 MAUI,Zxing扫码,华为手机没反应。可提高悬赏
  • ¥15 python运行报错 ModuleNotFoundError: No module named 'torch'
  • ¥100 华为手机私有App后台保活
  • ¥15 sqlserver中加密的密码字段查询问题
  • ¥20 有谁能看看我coe文件到底哪儿有问题吗?
  • ¥20 我的这个coe文件到底哪儿出问题了
  • ¥15 matlab使用自定义函数时一直报错输入参数过多
  • ¥15 设计一个温度闭环控制系统