STM32 4*4矩阵键盘实现原理(附程序)

STM32 4*4矩阵键盘实现原理(附程序)

: 理解矩阵键盘之前,先要了解一下独立按键的触发原理。下图是普通独立 按键的接线图。
在这里插入图片描述

: 按键的一端接地,一端接MCU的GPIO。当按键没有被按下的时候,这条路其实是一个断路,我们通常会将单片机该引脚设置成输入上拉状态。所以当按键没有按下的时候,这个引脚读到的电平一直是高电平。当按下按键的时候,那么此时的引脚会被地强行拉低,此时这个引脚读到的电平为低电平,那说明按键已经被按下。独立按键到这里已经说完了,很简单。矩阵按键是由多个独立按键组成的,所以它的触发原理和独立按键相同,只是在电路和程序扫描上不同,略微复杂一点。

  通常用的最多的矩阵键盘是4*4的。如下图:

在这里插入图片描述
程序设计上通常采用逐行逐列进行扫描,4*4的矩阵键盘一共需要8个单片机的GPIO引脚,将控制行的引脚设置成输出,控制列的引脚设置成输入上拉。

先扫描第一行,那么就将PD0~PD2输出高电平,将PD3输出低电平,记为0xF7,行确定好后,开始扫描列,控制列的引脚为输入引脚,将其和0XF7相与,如果哪一位为0,那么就证明哪一个被按下。按键没有被按下的时候,IO口的状态为 **1111 0000 ,**扫描第一行将PD3输出低电平,其他行输出高电平,即为1111 0111,假设第一个按键被按下,那么此时PD4引脚读到低电平,那么读到的引脚变化

GPIOD->IDR & 1111 0111=1110 0111//这样就证明了第一个按键被按下。以此类推。

程序如下:

key_board.c

#include "stm32f10x.h"
#include "delay.h"
#include "key_board.h"


//uint8_t Send_F=0;


void Keyboard_GPIO_Config(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    
    KEYBOARD_GPIO_CLK_FUN(KEYBOARD_GPIO_CLK,ENABLE);
    
    //LINE    
    GPIO_InitStruct.GPIO_Pin=KEYBOARD_GPIO_PIN0|KEYBOARD_GPIO_PIN1|KEYBOARD_GPIO_PIN2|KEYBOARD_GPIO_PIN3;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(KEYBOARD_GPIO_PORT,&GPIO_InitStruct);

    //ROW
    GPIO_InitStruct.GPIO_Pin=KEYBOARD_GPIO_PIN4|KEYBOARD_GPIO_PIN5|KEYBOARD_GPIO_PIN6|KEYBOARD_GPIO_PIN7;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(KEYBOARD_GPIO_PORT,&GPIO_InitStruct);
}

uint16_t keyboard_scan(void)
{
    uint16_t key_val=0;
    uint16_t temp=0;
	
	
	/*************Scan  1st Line************************/

    GPIOD->ODR=0X00;

    GPIOD->ODR=0XF7;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XF7);
            switch(temp)
            {
                case 0xE7:  key_val=1;   break;

                case 0xD7:  key_val=2;   break;

                case 0xB7:  key_val=3;   break;

                case 0x77:  key_val=4;   break;

                default:    key_val=0;   break;
            }
        }
    }
    
		/*************Scan  2st Line************************/
    GPIOD->ODR=0X00;

    GPIOD->ODR=0XFB;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XFB);
            switch(temp)
            {
                case 0xEB:  key_val=5;  break;

                case 0xDB:  key_val=6;  break;

                case 0xBB:  key_val=7;  break;

                case 0x7B:  key_val=8;  break;

                default:    key_val=0;  break;
            }
        }
    }

		/*************Scan  3st Line************************/
    GPIOD->ODR=0X00;

    GPIOD->ODR=0XFD;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XFD);
            switch(temp)
            {
                case 0xED:  key_val=9;   break;

                case 0xDD:  key_val=10;  break;

                case 0xBD:  key_val=11;  break;

                case 0x7D:  key_val=12;  break;

                default:    key_val=0;   break;
            }
        }
    }

		/*************Scan  4st Line************************/
    GPIOD->ODR=0X00;

    GPIOD->ODR=0XFE;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XFE);
            switch(temp)
            {
                case 0xEE:  key_val=13;  break;

                case 0xDE:  key_val=14;  break;

                case 0xBE:  key_val=15;  break;

                case 0x7E:  key_val=16;  break;

                default:    key_val=0;   break;
            }
        }
    }

    return key_val;

}

key_board.h

#include "stm32f10x.h"

#ifndef     _KEY_BOARD_H_
#define     _KEY_BOARD_H_



#define   KEYBOARD_GPIO_PORT          GPIOD
#define   KEYBOARD_GPIO_CLK_FUN       RCC_APB2PeriphClockCmd
#define   KEYBOARD_GPIO_CLK           RCC_APB2Periph_GPIOD


//line    行
#define   KEYBOARD_GPIO_PIN0           GPIO_Pin_0
#define   KEYBOARD_GPIO_PIN1           GPIO_Pin_1
#define   KEYBOARD_GPIO_PIN2           GPIO_Pin_2
#define   KEYBOARD_GPIO_PIN3           GPIO_Pin_3



//row      列
#define   KEYBOARD_GPIO_PIN4           GPIO_Pin_4
#define   KEYBOARD_GPIO_PIN5           GPIO_Pin_5
#define   KEYBOARD_GPIO_PIN6           GPIO_Pin_6
#define   KEYBOARD_GPIO_PIN7           GPIO_Pin_7



//extern uint8_t Send_F;

extern void Keyboard_GPIO_Config(void);
extern uint16_t keyboard_scan(void);

#endif

程序运行结果如下:

在这里插入图片描述

  • 66
    点赞
  • 370
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
### 回答1: 您好!关于 stm32f103 所对应的 4x4 矩阵键盘程序,您可以参考以下代码: ``` #include "stm32f10x.h" #define ROWS 4 #define COLS 4 GPIO_InitTypeDef GPIO_InitStructure; // 按键映射表 const char keymap[ROWS][COLS] = { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; // 初始化 GPIO void GPIO_Config(void) { // 使能 GPIOA 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 初始化行引脚 PA0 - PA3,设置为推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化列引脚 PA4 - PA7,设置为浮空输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } // 读取按键状态 char getKey(void) { int row, col; // 将行引脚设置为高电平,列引脚设置为输入 for (row = 0; row < ROWS; row++) { GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3); GPIO_SetBits(GPIOA, GPIO_Pin_0 << row); for (col = 0; col < COLS; col++) { if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4 << col) == Bit_RESET) { // 等待按键释放 while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4 << col) == Bit_RESET); // 返回按键对应字符 return keymap[row][col]; } } } // 没有按键按下,返回空字符 return '\0'; } int main(void) { char key; GPIO_Config(); while (1) { key = getKey(); if (key != '\0') { // 按键被按下,执行相应操作 // 这里可以添加自己的代码 } } } ``` 该程序使用 GPIOA 的 4 个引脚作为矩阵键盘的行引脚,使用 GPIOA 的另外 4 个引脚作为列引脚。程序首先将行引脚设置为高电平,列引脚设置为输入,然后检测每个按键是否被按下,如果检测到按键被按下,则返回按键对应的字符。您可以根据需要修改 keymap 数组以映射不同的按键。 ### 回答2: STM32F103是一款功能强大的微控制器,能够轻松实现4*4矩阵键盘的数据读取。实现这个功能的关键在于矩阵键盘的工作原理。矩阵键盘通常由一个行和列的矩阵组成,因此需要读取每一行和每一列的数据。对于STM32F103微控制器来说,需要先将每一列与悬空引脚相连,同时将每一行与输入引脚相连。 在程序开发中,首先需要声明引脚的输入和输出,然后开始扫描矩阵键盘。对于每一列引脚,需要将其设置为输出模式,同时输出高电平。然后再读取每一行的电平状态,如果有电平变化,则说明该行对应的按键按下,程序相应地记录下按键的状态。接着,对于下一列,需要将其输出低电平,然后重新读取每一行状态,以便继续记录按键状态。当所有列都扫描完毕,程序就能够得到整个矩阵键盘的按键状态,并可以进行相应的操作。 实现4*4矩阵键盘程序的关键在于代码的编写和调试,需要仔细分析引脚和按键的连接方式,并逐一调试程序,确保能够准确地读取矩阵键盘的按键状态。此外,还需要注意程序的实时性和可靠性,避免由于程序出现问题导致按键读取不准确或程序崩溃等情况。因此,在编写程序时,需要加入各种保护机制和异常处理机制,保证程序的稳定性和可靠性。 总之,STM32F103微控制器可以轻松实现4*4矩阵键盘程序,能够广泛应用于各种嵌入式系统中,为产品的功能提升和应用拓展提供了极大的便利。 ### 回答3: stm32f103矩阵键盘程序4*4的实现可以采用按键扫描的方式。主控芯片通过按键矩阵的行列脚引脚完成与按键的连接,同时,程序需要设置行列的扫描方式,这是因为按键所在的矩阵,需要在一定的时间间隔内进行周期性扫描,以判断当前是否有按键按下,相应地进行按键的收发动作。 在实现矩阵键盘程序的过程中,需要进行如下步骤: 1. 配置主控芯片的引脚,将矩阵键盘的行列脚连接到主控芯片。 2. 编写键盘扫描程序,使主控芯片能够周期性扫描按键矩阵,以判断是否有按键动作产生。键盘扫描程序一般采用轮询方式扫描,也可以使用中断方式进行扫描。 3. 编写按键检测程序,将扫描到的按键编码进行处理,使得按键对应的信息能够被主控芯片识别并处理。按键检测程序需要采用状态机的方式进行编写,以实现较为灵活和可靠的按键检测和处理功能。 4. 进行按键的反馈操作,将按键的信息进行发送或接收处理。 总之,实现stm32f103矩阵键盘程序4*4的过程较为繁琐,需要掌握一定的硬件和软件知识,同时,需要充分了解所采用的主控芯片的特性和编程方法,以保证程序的正确性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值