打印
[STM32F1]

stm32f103——按键检测(轮询方式)

[复制链接]
280|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

我们下面来讲一讲,GPIO在输入模式下检测按键是否被按下:


使用特权

评论回复
沙发
梵蒂冈是神uy|  楼主 | 2022-9-28 16:04 | 只看该作者
首先我们来看看按键按下时,K1处电压的变化情况是什么:

使用特权

评论回复
板凳
梵蒂冈是神uy|  楼主 | 2022-9-28 16:05 | 只看该作者
  我们看到,按键按下时,K1处的电压并不是立马就下降为0v,因为按键有机械的弹性形变,导致按键被按下时,会发生抖动。我们用GPIO来读取K1处的电压是否为0,如果为低电平,则表示按键被按下。被按下后,如果为高电平,则表示按键被抬起来了。

使用特权

评论回复
地板
梵蒂冈是神uy|  楼主 | 2022-9-28 16:07 | 只看该作者
  但是,在这个按键抖动的过程中,电平有上升沿也有下降沿,电压有高电平也有低电平。所以,在这一段抖动的部分的时间段内,如果我们用GPIO去判断,由于电平忽高忽低,我们的程序就会识别出来,按键在被按下后马上就抬起来了。但是,实际上并不是这样。所以,我们需要跳过按键被按下时的前50ms,在K1处电压稳定时,再来对K1处电压进行判断。这个过程我们称为按键"消抖"。

使用特权

评论回复
5
梵蒂冈是神uy|  楼主 | 2022-9-28 16:14 | 只看该作者
读取PA0的按键值,编程步骤:
        1,打开时钟----GPIOA
        2,初始化GPIOA
            ---GPIO_Pin_0
            ---上拉输入
        3,判断PA0是否为低电平
        4,如果为低电平,延时50ms,消除抖动
        5,再次判断PA0是否为低电平---结合第3步,判断是否为按键按下过程
        6,如果是为低电平,等待按键抬起----耗尽按键按下的时间
        7,确认按键按下,执行按键按下相应的操作

使用特权

评论回复
6
梵蒂冈是神uy|  楼主 | 2022-9-28 16:16 | 只看该作者
编程:
//按键按下后,LED灯的状态反转

void KEY_Config(void)
{
     GPIO_InitTypeDef  GPIO_InitStruct;
    // 1,打开时钟----GPIOA
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

    // 2,初始化GPIOA
    GPIO_InitStruct.GPIO_Pin  =GPIO_Pin_0;                   //注意:在输入模式下,不用设置I/O口的速度
    GPIO_InitStruct.GPIO_Mode =GPIO_Mode_IPU;        //按键检测时,选择上拉输入模式
    GPIO_Init( GPIOA,&GPIO_InitStruct);
   
}

uint8_t KEY_isPress(void)
{
    uint8_t ret=0;
    // 3,判断PA0是否为低电平
    if(0==GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)){
        // 4,如果为低电平,延时50ms,消除抖动
        Systick_NmsDelay(50);
        // 5,再次判断PA0是否为低电平---结合第3步,判断是否为按键按下过程   
        if(0==GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)){
            // 6,如果是为低电平,等待按键抬起----耗尽按键按下的时间
            while(0==GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))
                ;
            // 7,确认按键按下,执行按键按下相应的操作
            ret=1;
        }
    }
    return ret;
}

uint8_t ledflag=0;

int main(void)
{
    LED_Config();   
    RCC_ConfigTo72M();//将系统时钟配置成72MHZ
    Systick_Config(72);
    KEY_Config();


    while(1){
        if(0==ledflag){
            LED_CTRL(LEDR,LED_CLOSE);
        }else{
            LED_CTRL(LEDR,LED_OPEN);
        }
        if( 1==KEY_isPress() ){
            ledflag=~ledflag;
        }
    }
}

使用特权

评论回复
7
梵蒂冈是神uy|  楼主 | 2022-9-28 16:56 | 只看该作者
这里提出一个问题:

使用特权

评论回复
8
梵蒂冈是神uy|  楼主 | 2022-9-28 16:57 | 只看该作者
请问红框部分可以写成1==ledflag吗?反正只要按键按下,就会执行 ledflag=~ledflag,ledflag一开始为0,"~"(反)一下不就是1了吗?1的时候LED灯关闭。

使用特权

评论回复
9
梵蒂冈是神uy|  楼主 | 2022-9-28 17:02 | 只看该作者
不行,因为ledflag虽然一开始是0,但是uint8_t 类型,uint8_t类型的0实际上是0000 0000(即0x00),所以~(0000 0000) = 1111 1111 (即:0xff)其不等于1,所以,此时LED灯不会关闭。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

47

主题

680

帖子

1

粉丝