基于STM32的矩阵按键

思路:

将输入和输出互换分别确定列和行来找到对应的按键。

若S6被按下,第一次没有翻转之前PA0~PA3为输入,PA4~PA7为输出,S6被按下此时PA5输出低电平到达PA1,此时PA1从原来的高电平变为低电平,此时我们确定了按键在第二列

进行一次翻转,此时PA0~PA3为输出,PA4~PA7为输入,此时PA1输出低电平,PA5由翻转之后的内部上拉1也转为0,此时我们确定了按键在第二行,从而确定了S6的位置

7c492ca2bba0452f8a91191b49ecfd6d.jpeg

此时如何让我们的S6和第二行第二列对应:

第一行我们是1,5,9,13的编号第二列开始每个数一次+1

de568068e68b4952bb06f03bf83bf154.jpeg

设计一个函数,函数返回我们按下按键的编号

1.将PA0~PA3定义成上拉输入,将PA4~PA7定义成通用推挽输出低电平。

int Matrix_Key(int value)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

2.读取PA0~PA3的电平状态。(没有按键按下去四个管脚均为1111)

GPIO_WriteBit(GPIOA, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7, Bit_SET);
if((GPIOA->IDR & 0XF)!= 0XF)//直接操作寄存器的前四位如果不等于0XF则说明有按键被按下
{
    Delay(1000);//消抖
    if((GPIOA->IDR & 0XF)!= 0X0F)//再次判断按键是否按下
    {
        switch((GPIOA->IDR & 0XF))
        case 0xE:val = 1;break;
        case 0xD:val = 5;break;
        case 0xB:val = 9;break;
        case 0x7:val = 13;break;
        default:break;             
    }
    else
        return 0;

    //将PA0~PA3设置成通用推挽输出且输出低电平,将PA4~PA7设置成上拉输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_WriteBit(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3, Bit_SET);

    if((GPIOA->IDR & 0XF0) != 0XF0)
    {
        Delay(1000);//消抖
        if((GPIOA->IDR & 0XF0) != 0XF0)
        {
            switch((GPIOA->IDR & 0XF0))
            case 0xE0:val += 0;break;
            case 0xD0:val += 1;break;
            case 0xB0:val += 2;break;
            case 0x70:val += 3;break;
            default:break;
        }
        else
            return 0;             
    }
    else
        return 0;

while(((GPIOA->IDR & 0XF0) != 0XF0) != 0xF0)//确保我们按键松手的时候返回val,否则会一直扫描
return val;
}
else
    return 0;//没有按键被按下

3.软件消抖:SYSTICK

4.UART口配置:UART口介绍

最后附上整合好的主要代码

int main(void)
{
	int key_num;
	
	SysTick_Configuration();
	
	Uart1_Configuration();
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	while(1)
	{
		key_num = Matrix_Key_Scan();
		if(key_num != 0)
			printf("Key %d is pressed.\n", key_num);
	}
}

int Matrix_Key(int value)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_WriteBit(GPIOA, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7, Bit_SET);

    if((GPIOA->IDR & 0XF)!= 0XF)
    {
        Delay(1000);
        if((GPIOA->IDR & 0XF)!= 0X0F)
        {
            switch((GPIOA->IDR & 0XF))
            case 0xE:val = 1;break;
            case 0xD:val = 5;break;
            case 0xB:val = 9;break;
            case 0x7:val = 13;break;
            default:break;             
        }
        else
            return 0;

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; 
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; 
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_WriteBit(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3, Bit_SET);

        if((GPIOA->IDR & 0XF0) != 0XF0)
        {
            Delay(1000);
            if((GPIOA->IDR & 0XF0) != 0XF0)
            {
                switch((GPIOA->IDR & 0XF0))
                case 0xE0:val += 0;break;
                case 0xD0:val += 1;break;
                case 0xB0:val += 2;break;
                case 0x70:val += 3;break;
                default:break;
            }
            else
                return 0;             
        }
        else
            return 0;

    while(((GPIOA->IDR & 0XF0) != 0XF0) != 0xF0)
    return val;
    }
    else
        return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值